From c1820fa551301ab13fa3ddefcab72836fff0a3bb Mon Sep 17 00:00:00 2001 From: brayden-dowson Date: Sat, 26 Apr 2025 19:36:48 +0930 Subject: [PATCH 001/215] Obselete Lock(DoorLockReason reason, bool enabled) --- LabApi/Features/Wrappers/Facility/Doors/Door.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/LabApi/Features/Wrappers/Facility/Doors/Door.cs b/LabApi/Features/Wrappers/Facility/Doors/Door.cs index 94f3caab..4e319689 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/Door.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/Door.cs @@ -242,6 +242,20 @@ public bool Bypass2176 /// public void PlayPermissionDeniedAnimation() => Base.PermissionsDenied(null, 0); + /// + /// Locks the door. + /// + /// The reason. + /// Whether the door lock reason is new. + [Obsolete($"Use {nameof(ChangeLock)} instead")] + public void Lock(DoorLockReason reason, bool enabled) => Base.ServerChangeLock(reason, enabled); + + /// + /// Changes the door's lock flags. + /// + /// The reason flag to add or remove. + /// Whether to apply this door lock flag or release it. + public void ChangeLock(DoorLockReason reason, bool enabled) => Base.ServerChangeLock(reason, enabled); /// /// Gets the door wrapper from the , or creates a new one if it doesn't exist. /// From 08a2991497743e4bca02796f1acbc1c34c40d466 Mon Sep 17 00:00:00 2001 From: brayden-dowson Date: Sat, 26 Apr 2025 19:37:03 +0930 Subject: [PATCH 002/215] Added open and close methods to door --- LabApi/Features/Wrappers/Facility/Doors/Door.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/LabApi/Features/Wrappers/Facility/Doors/Door.cs b/LabApi/Features/Wrappers/Facility/Doors/Door.cs index 4e319689..05fc2eb4 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/Door.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/Door.cs @@ -242,6 +242,16 @@ public bool Bypass2176 /// public void PlayPermissionDeniedAnimation() => Base.PermissionsDenied(null, 0); + /// + /// Opens the door. + /// + public void Open() => IsOpened = true; + + /// + /// Closes the door. + /// + public void Close() => IsOpened = false; + /// /// Locks the door. /// From f6f24f5f626ef7c36b31eb4772c71fea8bde8b59 Mon Sep 17 00:00:00 2001 From: brayden-dowson Date: Sat, 26 Apr 2025 19:37:30 +0930 Subject: [PATCH 003/215] Used wrapper type for Door.Rooms --- LabApi/Features/Wrappers/Facility/Doors/Door.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LabApi/Features/Wrappers/Facility/Doors/Door.cs b/LabApi/Features/Wrappers/Facility/Doors/Door.cs index 05fc2eb4..8516e1b7 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/Door.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/Door.cs @@ -143,7 +143,7 @@ internal virtual void OnRemove() /// /// Gets the rooms which have this door. /// - public RoomIdentifier[] Rooms => Base.Rooms; + public IEnumerable Rooms => Base.Rooms.Select(Room.Get)!; /// /// Gets the zone in which this door is. From 355f11bbd75412af07386802e7b2003c10d62546 Mon Sep 17 00:00:00 2001 From: brayden-dowson Date: Sat, 26 Apr 2025 19:37:59 +0930 Subject: [PATCH 004/215] Moved Door.Lock method --- LabApi/Features/Wrappers/Facility/Doors/Door.cs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Doors/Door.cs b/LabApi/Features/Wrappers/Facility/Doors/Door.cs index 8516e1b7..ad22fe06 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/Door.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/Door.cs @@ -187,13 +187,6 @@ public bool IsLocked /// public DoorLockReason LockReason => (DoorLockReason)Base.ActiveLocks; - /// - /// Locks the door. - /// - /// The reason. - /// Whether the door lock reason is new. - public void Lock(DoorLockReason reason, bool enabled) => Base.ServerChangeLock(reason, enabled); - /// /// Gets or sets the required . /// From d9a068ab7edc8bbdc561ce2b977dfbc4b0eea037 Mon Sep 17 00:00:00 2001 From: brayden-dowson Date: Sat, 26 Apr 2025 19:38:16 +0930 Subject: [PATCH 005/215] Added Door Lock Unlock and HasLock methods --- .../Features/Wrappers/Facility/Doors/Door.cs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/LabApi/Features/Wrappers/Facility/Doors/Door.cs b/LabApi/Features/Wrappers/Facility/Doors/Door.cs index ad22fe06..0563f018 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/Door.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/Door.cs @@ -259,6 +259,32 @@ public bool Bypass2176 /// The reason flag to add or remove. /// Whether to apply this door lock flag or release it. public void ChangeLock(DoorLockReason reason, bool enabled) => Base.ServerChangeLock(reason, enabled); + + /// + /// Locks the door. + /// + /// The reason flag to add for the lock. + /// + /// A door is locked when it has any flag. + /// + public void Lock(DoorLockReason reason = DoorLockReason.AdminCommand) => Base.ServerChangeLock(reason, true); + + /// + /// Unlocks the door. + /// + /// The reason flag to remove for the lock. + /// + /// A door is unlocked when it has zero flags. + /// + public void Unlock(DoorLockReason reason = DoorLockReason.AdminCommand) => Base.ServerChangeLock(reason, false); + + /// + /// Whether the door has the specified . + /// + /// The to test. + /// if locked with the specified lock reason. + public bool HasLock(DoorLockReason reason) => (Base.ActiveLocks | (ushort)reason) > 0; + /// /// Gets the door wrapper from the , or creates a new one if it doesn't exist. /// From acbed442298b37c81e9d9521e42b6b06ea003071 Mon Sep 17 00:00:00 2001 From: brayden-dowson Date: Sat, 26 Apr 2025 19:38:45 +0930 Subject: [PATCH 006/215] fix --- LabApi/Features/Wrappers/Facility/Rooms/Scp914/Scp914.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LabApi/Features/Wrappers/Facility/Rooms/Scp914/Scp914.cs b/LabApi/Features/Wrappers/Facility/Rooms/Scp914/Scp914.cs index 4b770262..7d7bee87 100644 --- a/LabApi/Features/Wrappers/Facility/Rooms/Scp914/Scp914.cs +++ b/LabApi/Features/Wrappers/Facility/Rooms/Scp914/Scp914.cs @@ -57,7 +57,7 @@ internal override void OnRemoved() /// /// Gets the entrance of the SCP-914 room. /// - public Door Entrance => Doors.FirstOrDefault(x => x.Rooms.Length == 2); + public Door Entrance => Doors.FirstOrDefault(x => x.Rooms.Count() == 2); /// /// Gets the intake of the SCP-914 machine. From 22be70dae44b95cc658c97ecd067738fd9cf79c0 Mon Sep 17 00:00:00 2001 From: brayden-dowson Date: Sat, 26 Apr 2025 19:39:18 +0930 Subject: [PATCH 007/215] Used wrapper type for Room.ConnectedRooms --- LabApi/Features/Wrappers/Facility/Rooms/Room.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LabApi/Features/Wrappers/Facility/Rooms/Room.cs b/LabApi/Features/Wrappers/Facility/Rooms/Room.cs index b440c5a3..bcb62fa2 100644 --- a/LabApi/Features/Wrappers/Facility/Rooms/Room.cs +++ b/LabApi/Features/Wrappers/Facility/Rooms/Room.cs @@ -74,7 +74,7 @@ internal virtual void OnRemoved() /// /// Gets the room's neighbors. /// - public HashSet ConnectedRooms => Base.ConnectedRooms; + public IEnumerable ConnectedRooms => Base.ConnectedRooms.Select(Get)!; /// /// Gets the doors that are a part of this room. TODO: Cache in base game code? From 9c680725b19f39be19941128bc0ac985cef2c9ee Mon Sep 17 00:00:00 2001 From: brayden-dowson Date: Sat, 26 Apr 2025 19:39:58 +0930 Subject: [PATCH 008/215] Added Player.AuthenticatedList to make it easy to get all authenticated players --- LabApi/Features/Wrappers/Players/Player.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/LabApi/Features/Wrappers/Players/Player.cs b/LabApi/Features/Wrappers/Players/Player.cs index 929cb526..caa0f28c 100644 --- a/LabApi/Features/Wrappers/Players/Player.cs +++ b/LabApi/Features/Wrappers/Players/Player.cs @@ -75,10 +75,18 @@ public class Player public static IEnumerable NpcList => List.Where(x => x.IsNpc); /// - /// A reference to all instance that are real players but are not authenticated yet. + /// A reference to all instances that are real players but are not authenticated yet. /// public static IEnumerable UnauthenticatedList => List.Where(x => x.IsPlayer && !x.IsReady); + /// + /// A reference to all instances that are real players and that have authenticated. + /// + /// + /// This is the set of all players that it is safe to send network messages too. + /// + public static IEnumerable AuthenticatedList => List.Where(x => x.IsPlayer && x.IsReady); + /// /// The representing the host or server. /// From d5ba0897c5ee0a76d9061fdb0852074ee76b8bcf Mon Sep 17 00:00:00 2001 From: brayden-dowson Date: Tue, 29 Apr 2025 20:43:08 +0930 Subject: [PATCH 009/215] added missing interface to PlayerDroppingItemEventArgs --- .../Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs index 3ae57892..02800029 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// /// Represents the arguments for the event. /// -public class PlayerDroppingItemEventArgs : EventArgs, ICancellableEvent, IItemEvent +public class PlayerDroppingItemEventArgs : EventArgs, ICancellableEvent, IItemEvent, IPlayerEvent { /// /// Initializes a new instance of the class. From 68e35099c1b2e2f7c3e2d24bc5c1d132e903546d Mon Sep 17 00:00:00 2001 From: brayden-dowson Date: Tue, 29 Apr 2025 20:44:20 +0930 Subject: [PATCH 010/215] additional player properties --- LabApi/Features/Wrappers/Players/Player.cs | 35 ++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/LabApi/Features/Wrappers/Players/Player.cs b/LabApi/Features/Wrappers/Players/Player.cs index caa0f28c..fae0da94 100644 --- a/LabApi/Features/Wrappers/Players/Player.cs +++ b/LabApi/Features/Wrappers/Players/Player.cs @@ -31,6 +31,7 @@ using VoiceChat; using VoiceChat.Playbacks; using static PlayerStatsSystem.AhpStat; +using InventorySystem.Items.Armor; namespace LabApi.Features.Wrappers; @@ -128,6 +129,7 @@ internal Player(ReferenceHub referenceHub) { Dictionary.Add(referenceHub, this); ReferenceHub = referenceHub; + Transform = referenceHub.transform; CustomDataStoreManager.AddPlayer(this); } @@ -141,6 +143,16 @@ internal Player(ReferenceHub referenceHub) /// public GameObject GameObject => ReferenceHub.gameObject; + /// + /// Gets the player's . + /// + public Transform Transform { get; } + + /// + /// Gets whether the player was destroyed. + /// + public bool IsDestroyed => ReferenceHub == null || GameObject == null; + /// /// Gets whether the player is the host or server. /// @@ -453,6 +465,11 @@ public Item? CurrentItem } } + /// + /// Gets the current being used. + /// + public BodyArmorItem? CurrentArmor => BodyArmorUtils.TryGetBodyArmor(Inventory, out BodyArmor baseArmor) ? BodyArmorItem.Get(baseArmor) : null; + /// /// Gets the player's currently active status effects. /// @@ -1197,6 +1214,24 @@ public List DropAllItems() /// The amount of ammo which the player has. public ushort GetAmmo(ItemType item) => ReferenceHub.inventory.GetCurAmmo(item); + /// + /// Attempts to get the first specified by its from the inventory. + /// + /// The to search for. + /// The found instance. + /// if found, otherwise . + public bool TryGetItem(ItemType type, [NotNullWhen(true)] out Item? item) + { + if(Inventory.TryGetInventoryItem(type, out ItemBase itemBase)) + { + item = Item.Get(itemBase); + return true; + } + + item = null; + return false; + } + /// /// Drops ammo of the specified type from the player's inventory. /// From 993613ddc6022654bbce04ea346bcf55788a2102 Mon Sep 17 00:00:00 2001 From: brayden-dowson Date: Tue, 29 Apr 2025 20:44:35 +0930 Subject: [PATCH 011/215] additional ragdoll properties --- LabApi/Features/Wrappers/Players/Ragdoll.cs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/LabApi/Features/Wrappers/Players/Ragdoll.cs b/LabApi/Features/Wrappers/Players/Ragdoll.cs index 78197f33..72368783 100644 --- a/LabApi/Features/Wrappers/Players/Ragdoll.cs +++ b/LabApi/Features/Wrappers/Players/Ragdoll.cs @@ -1,4 +1,5 @@ using Generators; +using InventorySystem.Items.Pickups; using Mirror; using PlayerRoles; using PlayerRoles.PlayableScps.Scp049; @@ -32,6 +33,8 @@ public class Ragdoll private Ragdoll(BasicRagdoll ragdoll) { Base = ragdoll; + GameObject = ragdoll.gameObject; + Transform = ragdoll.transform; Dictionary.TryAdd(ragdoll, this); } @@ -40,6 +43,21 @@ private Ragdoll(BasicRagdoll ragdoll) /// public BasicRagdoll Base { get; private set; } + /// + /// Gets the ragdoll's . + /// + public GameObject GameObject { get; } + + /// + /// Gets the pickup's . + /// + public Transform Transform { get; } + + /// + /// Gets whether the ragdoll was destroyed. + /// + public bool IsDestroyed => Base == null || GameObject == null; + /// /// Gets or sets the role info of the ragdoll. /// This does NOT change the ragdoll visually. From 4572e045017153ee3e86e4d6d3dd0328adba6824 Mon Sep 17 00:00:00 2001 From: brayden-dowson Date: Tue, 29 Apr 2025 20:51:10 +0930 Subject: [PATCH 012/215] added parent and spawn option to pickup create functions --- LabApi/Features/Wrappers/Pickups/Pickup.cs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/LabApi/Features/Wrappers/Pickups/Pickup.cs b/LabApi/Features/Wrappers/Pickups/Pickup.cs index cb71e69b..5a4d867b 100644 --- a/LabApi/Features/Wrappers/Pickups/Pickup.cs +++ b/LabApi/Features/Wrappers/Pickups/Pickup.cs @@ -301,9 +301,10 @@ public void Destroy() /// /// The . /// The initial position. + /// The initial parent transform or . + /// Whether to spawn the pickup on the client. /// The instantiated - /// The pickup is only spawned on the server, to spawn the pickup for clients use . - public static Pickup? Create(ItemType type, Vector3 position) => Create(type, position, Quaternion.identity, Vector3.one); + public static Pickup? Create(ItemType type, Vector3 position, Transform? parent = null, bool networkSpawn = true) => Create(type, position, Quaternion.identity, Vector3.one, parent, networkSpawn); /// /// Creates a new . @@ -311,9 +312,10 @@ public void Destroy() /// The . /// The initial position. /// The initial rotation. + /// The initial parent transform or . + /// Whether to spawn the pickup on the client. /// The instantiated - /// The pickup is only spawned on the server, to spawn the pickup for clients use . - public static Pickup? Create(ItemType type, Vector3 position, Quaternion rotation) => Create(type, position, rotation, Vector3.one); + public static Pickup? Create(ItemType type, Vector3 position, Quaternion rotation, Transform? parent = null, bool networkSpawn = true) => Create(type, position, rotation, Vector3.one, parent, networkSpawn); /// /// Creates a new . @@ -322,15 +324,21 @@ public void Destroy() /// The initial position. /// The initial rotation. /// The initial scale. + /// The initial parent transform or . + /// Whether to spawn the pickup on the client. /// The instantiated - /// The pickup is only spawned on the server, to spawn the pickup for clients use . - public static Pickup? Create(ItemType type, Vector3 position, Quaternion rotation, Vector3 scale) + public static Pickup? Create(ItemType type, Vector3 position, Quaternion rotation, Vector3 scale, Transform? parent = null, bool networkSpawn = true) { if (type == ItemType.None || !InventoryItemLoader.AvailableItems.TryGetValue(type, out ItemBase itemBase)) return null; ItemPickupBase newPickupBase = InventoryExtensions.ServerCreatePickup(itemBase, new PickupSyncInfo(type, itemBase.Weight), position, rotation, false); newPickupBase.transform.localScale = scale; + newPickupBase.transform.SetParent(parent, false); + + if (networkSpawn) + NetworkServer.Spawn(newPickupBase.gameObject); + return Get(newPickupBase); } From 8a9cd9a1efa4240f45dfb92800172e3cc9b52385 Mon Sep 17 00:00:00 2001 From: brayden-dowson Date: Tue, 29 Apr 2025 21:49:49 +0930 Subject: [PATCH 013/215] more elevator properties --- LabApi/Features/Wrappers/Facility/Elevator.cs | 59 ++++++++++++++++--- 1 file changed, 50 insertions(+), 9 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Elevator.cs b/LabApi/Features/Wrappers/Facility/Elevator.cs index 05b34fc9..8242ef90 100644 --- a/LabApi/Features/Wrappers/Facility/Elevator.cs +++ b/LabApi/Features/Wrappers/Facility/Elevator.cs @@ -5,6 +5,8 @@ using System.Linq; using UnityEngine; using Generators; +using BaseElevatorDoor = Interactables.Interobjects.ElevatorDoor; + namespace LabApi.Features.Wrappers; @@ -13,6 +15,18 @@ namespace LabApi.Features.Wrappers; /// public class Elevator { + /// + /// Initializes the class to subscribe to events. + /// + [InitializeWrapper] + internal static void Initialize() + { + Dictionary.Clear(); + + ElevatorChamber.OnElevatorSpawned += (chamber) => _ = new Elevator(chamber); + ElevatorChamber.OnElevatorRemoved += (chamber) => Dictionary.Remove(chamber); + } + /// /// Contains all the cached generators in the game, accessible through their . /// @@ -29,8 +43,10 @@ public class Elevator /// The of the elevator. private Elevator(ElevatorChamber elevator) { - Dictionary.Add(elevator, this); Base = elevator; + GameObject = Base.gameObject; + Transform = Base.transform; + Dictionary.Add(elevator, this); } /// @@ -39,16 +55,34 @@ private Elevator(ElevatorChamber elevator) public ElevatorChamber Base { get; } /// - /// Initializes the class to subscribe to events. + /// The . /// - [InitializeWrapper] - internal static void Initialize() - { - Dictionary.Clear(); + public GameObject GameObject { get; } - ElevatorChamber.OnElevatorSpawned += (chamber) => _ = new Elevator(chamber); - ElevatorChamber.OnElevatorRemoved += (chamber) => Dictionary.Remove(chamber); - } + /// + /// The . + /// + public Transform Transform { get; } + + /// + /// The world space position of the elevator. + /// + public Vector3 Position => Transform.position; + + /// + /// The world space rotation of the elevator. + /// + public Quaternion Rotation => Transform.rotation; + + /// + /// Gets all the doors associated with this elevator. + /// + public IEnumerable Doors => BaseElevatorDoor.GetDoorsForGroup(Group).Select(ElevatorDoor.Get)!; + + /// + /// Gets all the rooms associated with this elevator. + /// + public IEnumerable Rooms => Doors.SelectMany(x => x.Rooms); /// /// Gets the current destination / location of the elevator. @@ -167,6 +201,13 @@ public static void UnlockAll() /// public void UnlockAllDoors() => Base.ServerLockAllDoors(DoorLockReason.AdminCommand, false); + /// + /// Checks to see if the position in considered inside the elevators bounds. + /// + /// The world space position to check. + /// if the position is contained in the elevators world space bounds. + public bool IsInside(Vector3 position) => Base.WorldspaceBounds.Contains(position); + /// /// Gets the elevator wrapper from the , or creates a new one if it doesn't exist. /// From f3bc5ecfa61f886c4b1e34c56c72f554f59c2e9d Mon Sep 17 00:00:00 2001 From: brayden-dowson Date: Tue, 29 Apr 2025 21:50:22 +0930 Subject: [PATCH 014/215] removed nullable from elevator door.elevator --- LabApi/Features/Wrappers/Facility/Doors/ElevatorDoor.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Doors/ElevatorDoor.cs b/LabApi/Features/Wrappers/Facility/Doors/ElevatorDoor.cs index b0e586b8..2466d871 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/ElevatorDoor.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/ElevatorDoor.cs @@ -1,7 +1,6 @@ using Interactables.Interobjects; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; -using System.Linq; using BaseElevatorDoor = Interactables.Interobjects.ElevatorDoor; namespace LabApi.Features.Wrappers; @@ -49,7 +48,7 @@ internal override void OnRemove() /// /// Gets the this door belongs to. /// - public Elevator? Elevator => Elevator.GetByGroup(Base.Group).FirstOrDefault(); + public Elevator Elevator => Elevator.Get(Base.Chamber); /// /// Gets the this door belongs to. From 57992085e6794e56d98df32053da56e659019450 Mon Sep 17 00:00:00 2001 From: brayden-dowson Date: Tue, 29 Apr 2025 22:44:29 +0930 Subject: [PATCH 015/215] fix --- LabApi/Features/Wrappers/Facility/Doors/Door.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LabApi/Features/Wrappers/Facility/Doors/Door.cs b/LabApi/Features/Wrappers/Facility/Doors/Door.cs index 0563f018..980dee39 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/Door.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/Door.cs @@ -283,7 +283,7 @@ public bool Bypass2176 /// /// The to test. /// if locked with the specified lock reason. - public bool HasLock(DoorLockReason reason) => (Base.ActiveLocks | (ushort)reason) > 0; + public bool HasLock(DoorLockReason reason) => (Base.ActiveLocks & (ushort)reason) > 0; /// /// Gets the door wrapper from the , or creates a new one if it doesn't exist. From f9e74b19c9d932d2852f77a795f8d1ab0ae7f549 Mon Sep 17 00:00:00 2001 From: brayden-dowson Date: Tue, 6 May 2025 16:43:36 +0930 Subject: [PATCH 016/215] fixes --- LabApi/Features/Wrappers/Pickups/Pickup.cs | 20 ++++++-------------- LabApi/Features/Wrappers/Players/Player.cs | 2 +- LabApi/Features/Wrappers/Players/Ragdoll.cs | 2 +- 3 files changed, 8 insertions(+), 16 deletions(-) diff --git a/LabApi/Features/Wrappers/Pickups/Pickup.cs b/LabApi/Features/Wrappers/Pickups/Pickup.cs index 59044797..855044a1 100644 --- a/LabApi/Features/Wrappers/Pickups/Pickup.cs +++ b/LabApi/Features/Wrappers/Pickups/Pickup.cs @@ -307,10 +307,9 @@ public override string ToString() /// /// The . /// The initial position. - /// The initial parent transform or . - /// Whether to spawn the pickup on the client. /// The instantiated - public static Pickup? Create(ItemType type, Vector3 position, Transform? parent = null, bool networkSpawn = true) => Create(type, position, Quaternion.identity, Vector3.one, parent, networkSpawn); + /// The pickup is only spawned on the server, to spawn the pickup for clients use . + public static Pickup? Create(ItemType type, Vector3 position) => Create(type, position, Quaternion.identity, Vector3.one); /// /// Creates a new . @@ -318,10 +317,9 @@ public override string ToString() /// The . /// The initial position. /// The initial rotation. - /// The initial parent transform or . - /// Whether to spawn the pickup on the client. /// The instantiated - public static Pickup? Create(ItemType type, Vector3 position, Quaternion rotation, Transform? parent = null, bool networkSpawn = true) => Create(type, position, rotation, Vector3.one, parent, networkSpawn); + /// The pickup is only spawned on the server, to spawn the pickup for clients use . + public static Pickup? Create(ItemType type, Vector3 position, Quaternion rotation) => Create(type, position, rotation, Vector3.one); /// /// Creates a new . @@ -330,21 +328,15 @@ public override string ToString() /// The initial position. /// The initial rotation. /// The initial scale. - /// The initial parent transform or . - /// Whether to spawn the pickup on the client. /// The instantiated - public static Pickup? Create(ItemType type, Vector3 position, Quaternion rotation, Vector3 scale, Transform? parent = null, bool networkSpawn = true) + /// The pickup is only spawned on the server, to spawn the pickup for clients use . + public static Pickup? Create(ItemType type, Vector3 position, Quaternion rotation, Vector3 scale) { if (type == ItemType.None || !InventoryItemLoader.AvailableItems.TryGetValue(type, out ItemBase itemBase)) return null; ItemPickupBase newPickupBase = InventoryExtensions.ServerCreatePickup(itemBase, new PickupSyncInfo(type, itemBase.Weight), position, rotation, false); newPickupBase.transform.localScale = scale; - newPickupBase.transform.SetParent(parent, false); - - if (networkSpawn) - NetworkServer.Spawn(newPickupBase.gameObject); - return Get(newPickupBase); } diff --git a/LabApi/Features/Wrappers/Players/Player.cs b/LabApi/Features/Wrappers/Players/Player.cs index 23edb9f8..d279c7b1 100644 --- a/LabApi/Features/Wrappers/Players/Player.cs +++ b/LabApi/Features/Wrappers/Players/Player.cs @@ -162,7 +162,7 @@ internal Player(ReferenceHub referenceHub) /// /// Gets whether the player was destroyed. /// - public bool IsDestroyed => ReferenceHub == null || GameObject == null; + public bool IsDestroyed => ReferenceHub == null; /// /// Gets whether the player is the host or server. diff --git a/LabApi/Features/Wrappers/Players/Ragdoll.cs b/LabApi/Features/Wrappers/Players/Ragdoll.cs index 66ea943e..87789dd1 100644 --- a/LabApi/Features/Wrappers/Players/Ragdoll.cs +++ b/LabApi/Features/Wrappers/Players/Ragdoll.cs @@ -56,7 +56,7 @@ private Ragdoll(BasicRagdoll ragdoll) /// /// Gets whether the ragdoll was destroyed. /// - public bool IsDestroyed => Base == null || GameObject == null; + public bool IsDestroyed => Base == null; /// /// Gets or sets the role info of the ragdoll. From e79a828095b4c651b1f9376cdd4fba5c424800e2 Mon Sep 17 00:00:00 2001 From: brayden-dowson <88667957+brayden-dowson@users.noreply.github.com> Date: Tue, 20 May 2025 04:08:55 +0930 Subject: [PATCH 017/215] Adds throw propertly to Item EventsArgs (#246) --- .../Arguments/PlayerEvents/PlayerDroppedItemEventArgs.cs | 9 ++++++++- .../PlayerEvents/PlayerDroppingItemEventArgs.cs | 9 ++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppedItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppedItemEventArgs.cs index b6f17fd0..9dd3ff9e 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppedItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppedItemEventArgs.cs @@ -15,10 +15,12 @@ public class PlayerDroppedItemEventArgs : EventArgs, IPlayerEvent, IPickupEvent /// /// The player who dropped the item. /// The item pickup. - public PlayerDroppedItemEventArgs(ReferenceHub player, ItemPickupBase pickup) + /// Whether the item will be thrown. + public PlayerDroppedItemEventArgs(ReferenceHub player, ItemPickupBase pickup, bool isThrowing) { Player = Player.Get(player); Pickup = Pickup.Get(pickup); + Throw = isThrowing; } /// @@ -30,4 +32,9 @@ public PlayerDroppedItemEventArgs(ReferenceHub player, ItemPickupBase pickup) /// Gets the item pickup. /// public Pickup Pickup { get; } + + /// + /// Gets or sets whether the will be thrown by the . + /// + public bool Throw { get; set; } } \ No newline at end of file diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs index 3ae57892..dc5f3e4d 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs @@ -15,11 +15,13 @@ public class PlayerDroppingItemEventArgs : EventArgs, ICancellableEvent, IItemEv /// /// The player who is dropping the item. /// The item being dropped. - public PlayerDroppingItemEventArgs(ReferenceHub player, ItemBase item) + /// Whether the item will be thrown. + public PlayerDroppingItemEventArgs(ReferenceHub player, ItemBase item, bool isThrowing) { IsAllowed = true; Player = Player.Get(player); Item = Item.Get(item); + Throw = isThrowing; } /// @@ -32,6 +34,11 @@ public PlayerDroppingItemEventArgs(ReferenceHub player, ItemBase item) /// public Item Item { get; } + /// + /// Gets or sets whether the will be thrown by the . + /// + public bool Throw { get; set; } + /// public bool IsAllowed { get; set; } } \ No newline at end of file From 0bbdeee431b8d09db6b1e24434d399daec148e48 Mon Sep 17 00:00:00 2001 From: brayden-dowson <88667957+brayden-dowson@users.noreply.github.com> Date: Tue, 20 May 2025 07:48:56 +0930 Subject: [PATCH 018/215] Added more properties to PlayerDeath event arg (#241) * Added OldRole to PlayerDeath event arg * docs * more properties * Apply suggestions from code review --------- Co-authored-by: Beryl <10091181+SebasCapo@users.noreply.github.com> --- .../PlayerEvents/PlayerDeathEventArgs.cs | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDeathEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDeathEventArgs.cs index b32a0366..d58359eb 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDeathEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDeathEventArgs.cs @@ -1,7 +1,9 @@ using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using PlayerRoles; using PlayerStatsSystem; using System; +using UnityEngine; namespace LabApi.Events.Arguments.PlayerEvents; @@ -16,11 +18,20 @@ public class PlayerDeathEventArgs : EventArgs, IPlayerEvent /// The player who died. /// The player who caused the death. /// The damage that caused the death. - public PlayerDeathEventArgs(ReferenceHub player, ReferenceHub? attacker, DamageHandlerBase damageHandler) + /// The previous role of the player before death. + /// The previous world position of the player before death. + /// The previous velocity of the player before death. + /// The previous world rotation of the players camera before death. + public PlayerDeathEventArgs(ReferenceHub player, ReferenceHub? attacker, DamageHandlerBase damageHandler, + RoleTypeId oldRole, Vector3 oldPosition, Vector3 oldVelocity, Quaternion oldCameraRotation) { Player = Player.Get(player); Attacker = Player.Get(attacker); DamageHandler = damageHandler; + OldRole = oldRole; + OldPosition = oldPosition; + OldVelocity = oldVelocity; + OldCameraRotation = oldCameraRotation; } /// @@ -37,4 +48,24 @@ public PlayerDeathEventArgs(ReferenceHub player, ReferenceHub? attacker, DamageH /// Gets the damage that caused the death. /// public DamageHandlerBase DamageHandler { get; } + + /// + /// Gets the role of the before they had died. + /// + public RoleTypeId OldRole { get; } + + /// + /// Gets the player's position before they died. + /// + public Vector3 OldPosition { get; } + + /// + /// Gets the player's velocity before they died. + /// + public Vector3 OldVelocity { get; } + + /// + /// Gets the player's camera rotation before they died. + /// + public Quaternion OldCameraRotation { get; } } \ No newline at end of file From c554b39bf0ea11165782d9d3db9f2f3cbe7f1774 Mon Sep 17 00:00:00 2001 From: brayden-dowson <88667957+brayden-dowson@users.noreply.github.com> Date: Tue, 20 May 2025 07:52:14 +0930 Subject: [PATCH 019/215] Adds attacker player to placed blood event (#239) --- .../Arguments/PlayerEvents/PlayerPlacedBloodEventArgs.cs | 9 ++++++++- .../PlayerEvents/PlayerPlacingBloodEventArgs.cs | 9 ++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBloodEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBloodEventArgs.cs index 344c74a2..e4385b58 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBloodEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBloodEventArgs.cs @@ -14,11 +14,13 @@ public class PlayerPlacedBloodEventArgs : EventArgs, IPlayerEvent /// Initializes a new instance of the class. /// /// The player whose blood it is. + /// The player that attacked. /// Position at which blood has been spawned. /// Position where the blood decal raycast will start for it to be properly attached to surface. - public PlayerPlacedBloodEventArgs(ReferenceHub player, Vector3 hitPosition, Vector3 startRaycast) + public PlayerPlacedBloodEventArgs(ReferenceHub player, ReferenceHub attacker, Vector3 hitPosition, Vector3 startRaycast) { Player = Player.Get(player); + Attacker = Player.Get(attacker); HitPosition = hitPosition; RaycastStart = startRaycast; } @@ -28,6 +30,11 @@ public PlayerPlacedBloodEventArgs(ReferenceHub player, Vector3 hitPosition, Vect /// public Player Player { get; } + /// + /// Gets the player that attacked the . + /// + public Player Attacker { get; } + /// /// Gets the position at which blood has been spawned. /// diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacingBloodEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacingBloodEventArgs.cs index 26bcf50d..cf28fff4 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacingBloodEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacingBloodEventArgs.cs @@ -14,12 +14,14 @@ public class PlayerPlacingBloodEventArgs : EventArgs, IPlayerEvent, ICancellable /// Initializes a new instance of the class. /// /// The player whose blood it is. + /// The player that attacked. /// Position at which is blood being placed. /// Position where the blood decal raycast will start for it to be properly attached to surface. - public PlayerPlacingBloodEventArgs(ReferenceHub player, Vector3 hitPosition, Vector3 startRaycast) + public PlayerPlacingBloodEventArgs(ReferenceHub player, ReferenceHub attacker, Vector3 hitPosition, Vector3 startRaycast) { IsAllowed = true; Player = Player.Get(player); + Attacker = Player.Get(attacker); HitPosition = hitPosition; RaycastStart = startRaycast; } @@ -29,6 +31,11 @@ public PlayerPlacingBloodEventArgs(ReferenceHub player, Vector3 hitPosition, Vec /// public Player Player { get; } + /// + /// Gets the player that attacked the . + /// + public Player Attacker { get; } + /// /// Gets the position at which is blood being placed. /// From 35b8b80936aa2c9013247a59a765745559643816 Mon Sep 17 00:00:00 2001 From: David Date: Fri, 6 Jun 2025 01:31:08 +0200 Subject: [PATCH 020/215] Playerscale + events (#244) * Scale * Added chaos and surface pass keycard to the keycard item register * Added CanOpen to UnlockingGenerator event Added Scp079Pinging/ed event Added RoundEndingConditionsCheck event Added permisisosn to the keycard wrapper * PingType to enum namespace * Ping to enum, comments --- .../PlayerUnlockingGeneratorEventArgs.cs | 13 ++++- .../Scp079Events/Scp079PingedEventArgs.cs | 48 +++++++++++++++++ .../Scp079Events/Scp079PingingEventArgs.cs | 52 +++++++++++++++++++ .../RoundEndingConditionsCheckEventArgs.cs | 23 ++++++++ .../Handlers/Scp079Events.EventHandlers.cs | 10 ++++ .../Handlers/ServerEvents.EventHandlers.cs | 5 ++ LabApi/Features/Enums/Scp079PingType.cs | 44 ++++++++++++++++ .../Features/Wrappers/Facility/Doors/Door.cs | 3 +- LabApi/Features/Wrappers/Items/Item.cs | 2 + LabApi/Features/Wrappers/Items/KeycardItem.cs | 14 ++++- LabApi/Features/Wrappers/Players/Player.cs | 22 ++++++++ 11 files changed, 230 insertions(+), 6 deletions(-) create mode 100644 LabApi/Events/Arguments/Scp079Events/Scp079PingedEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp079Events/Scp079PingingEventArgs.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/RoundEndingConditionsCheckEventArgs.cs create mode 100644 LabApi/Features/Enums/Scp079PingType.cs diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockingGeneratorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockingGeneratorEventArgs.cs index 57794b3f..9cb18a10 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockingGeneratorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockingGeneratorEventArgs.cs @@ -15,11 +15,13 @@ public class PlayerUnlockingGeneratorEventArgs : EventArgs, IPlayerEvent, IGener /// /// The player who is unlocking the generator. /// The generator that the player is unlocking. - public PlayerUnlockingGeneratorEventArgs(ReferenceHub player, Scp079Generator generator) + /// Whether the generator can be opened. + public PlayerUnlockingGeneratorEventArgs(ReferenceHub player, Scp079Generator generator, bool canOpen) { Player = Player.Get(player); Generator = Generator.Get(generator); IsAllowed = true; + CanOpen = canOpen; } /// @@ -30,7 +32,14 @@ public PlayerUnlockingGeneratorEventArgs(ReferenceHub player, Scp079Generator ge /// public Generator Generator { get; } - /// + /// + /// Gets whether the player can open the generator. + /// + public bool CanOpen { get; set; } + + /// + /// Gets whether this event is allowed. Not allowing this event will not unlock the generator and no denied animation is played. + /// public bool IsAllowed { get; set; } } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079PingedEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079PingedEventArgs.cs new file mode 100644 index 00000000..19b49334 --- /dev/null +++ b/LabApi/Events/Arguments/Scp079Events/Scp079PingedEventArgs.cs @@ -0,0 +1,48 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Enums; +using LabApi.Features.Wrappers; +using System; +using UnityEngine; + +namespace LabApi.Events.Arguments.Scp079Events; + +/// +/// Represents the arguments for the event. +/// +public class Scp079PingedEventArgs : EventArgs, IPlayerEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The SCP-079 player instance. + /// The world position of the ping. + /// Normal vector for the ping. + /// The index of the ping type. + public Scp079PingedEventArgs(ReferenceHub player, Vector3 position, Vector3 normal, byte index) + { + Player = Player.Get(player); + Position = position; + Normal = normal; + PingType = (Scp079PingType)index; + } + + /// + /// Gets the SCP-079 player instance. + /// + public Player Player { get; } + + /// + /// Gets the world ping position. + /// + public Vector3 Position { get; } + + /// + /// Gets the ping normal vector. + /// + public Vector3 Normal { get; } + + /// + /// Gets the type of the ping used the icon. + /// + public Scp079PingType PingType { get; } +} diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079PingingEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079PingingEventArgs.cs new file mode 100644 index 00000000..f27502db --- /dev/null +++ b/LabApi/Events/Arguments/Scp079Events/Scp079PingingEventArgs.cs @@ -0,0 +1,52 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Enums; +using LabApi.Features.Wrappers; +using System; +using UnityEngine; + +namespace LabApi.Events.Arguments.Scp079Events; + +/// +/// Represents the arguments for the event. +/// +public class Scp079PingingEventArgs : EventArgs, IPlayerEvent, ICancellableEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The SCP-079 player instance. + /// The world position of the ping. + /// Normal vector for the ping. + /// The index of the ping type. + public Scp079PingingEventArgs(ReferenceHub player, Vector3 position, Vector3 normal, byte index) + { + Player = Player.Get(player); + Position = position; + Normal = normal; + PingType = (Scp079PingType)index; + IsAllowed = true; + } + + /// + /// Gets the SCP-079 player instance. + /// + public Player Player { get; } + + /// + /// Gets or sets the world ping position. + /// + public Vector3 Position { get; set; } + + /// + /// Gets or sets the ping normal vector. + /// + public Vector3 Normal { get; set; } + + /// + /// Gets or sets the type of the ping used the icon. + /// + public Scp079PingType PingType { get; set; } + + /// + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/RoundEndingConditionsCheckEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/RoundEndingConditionsCheckEventArgs.cs new file mode 100644 index 00000000..4ddd004b --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/RoundEndingConditionsCheckEventArgs.cs @@ -0,0 +1,23 @@ +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// +/// Contains the arguments for the event. +/// +public class RoundEndingConditionsCheckEventArgs : EventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// Whether the round end conditions are met + public RoundEndingConditionsCheckEventArgs(bool canEnd) + { + CanEnd = canEnd; + } + + /// + /// Gets or sets whether the round end conditions are met. + /// + public bool CanEnd { get; set; } +} diff --git a/LabApi/Events/Handlers/Scp079Events.EventHandlers.cs b/LabApi/Events/Handlers/Scp079Events.EventHandlers.cs index d3820f8e..43b2097e 100644 --- a/LabApi/Events/Handlers/Scp079Events.EventHandlers.cs +++ b/LabApi/Events/Handlers/Scp079Events.EventHandlers.cs @@ -116,4 +116,14 @@ public static partial class Scp079Events /// Gets called when SCP-079 has used a tesla. /// public static event LabEventHandler? UsedTesla; + + /// + /// Gets called when SCP-079 is using ping ability. + /// + public static event LabEventHandler? Pinging; + + /// + /// Gets called when SCP-079 used ping ability. + /// + public static event LabEventHandler? Pinged; } \ No newline at end of file diff --git a/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs b/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs index ef5066ec..7c8ea582 100644 --- a/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs +++ b/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs @@ -17,6 +17,11 @@ public static partial class ServerEvents /// public static event LabEventHandler? RoundRestarted; + /// + /// Gets called when round end conditions are checked. + /// + public static event LabEventHandler? RoundEndingConditionsCheck; + /// /// Gets called when the round is ending. /// diff --git a/LabApi/Features/Enums/Scp079PingType.cs b/LabApi/Features/Enums/Scp079PingType.cs new file mode 100644 index 00000000..9060ef6d --- /dev/null +++ b/LabApi/Features/Enums/Scp079PingType.cs @@ -0,0 +1,44 @@ +using LabApi.Features.Wrappers; + +namespace LabApi.Features.Enums; + +/// +/// Enum used for type of the ping. +/// +public enum Scp079PingType : byte +{ + /// + /// ping. + /// + Generator = 0, + + /// + /// and pings. + /// + Projectile = 1, + + /// + /// Micro-HID ping. + /// + MicroHid = 2, + + /// + /// human role ping. + /// + Human = 3, + + /// + /// ping. + /// + Elevator = 4, + + /// + /// ping. + /// + Door = 5, + + /// + /// Default "i" icon ping. + /// + Default = 6, +} diff --git a/LabApi/Features/Wrappers/Facility/Doors/Door.cs b/LabApi/Features/Wrappers/Facility/Doors/Door.cs index 14bddcb2..6e2c6ff5 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/Door.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/Door.cs @@ -1,5 +1,4 @@ using Generators; -using Hazards; using Interactables.Interobjects; using Interactables.Interobjects.DoorUtils; using LabApi.Features.Enums; @@ -143,7 +142,7 @@ internal virtual void OnRemove() /// /// Gets the rooms which have this door. /// - public RoomIdentifier[] Rooms => Base.Rooms; + public Room[] Rooms => Base.Rooms.Select(Room.Get).ToArray(); /// /// Gets the zone in which this door is. diff --git a/LabApi/Features/Wrappers/Items/Item.cs b/LabApi/Features/Wrappers/Items/Item.cs index c0c32280..6cb82c72 100644 --- a/LabApi/Features/Wrappers/Items/Item.cs +++ b/LabApi/Features/Wrappers/Items/Item.cs @@ -65,6 +65,8 @@ internal static void Initialize() Register(x => new BodyArmorItem(x)); Register(x => new ThrowableItem(x)); Register(x => new KeycardItem(x)); + Register(x => new KeycardItem(x)); + Register(x => new KeycardItem(x)); Register(x => new MicroHIDItem(x)); } diff --git a/LabApi/Features/Wrappers/Items/KeycardItem.cs b/LabApi/Features/Wrappers/Items/KeycardItem.cs index cd605b66..f6ba7f73 100644 --- a/LabApi/Features/Wrappers/Items/KeycardItem.cs +++ b/LabApi/Features/Wrappers/Items/KeycardItem.cs @@ -51,6 +51,16 @@ internal override void OnRemove() /// public new BaseKeycardItem Base { get; } + /// + /// Gets the of the keycard. + /// + public DoorPermissionFlags Permissions => Base.GetPermissions(null); + + /// + /// Gets the of the keycard which represent the tiers shown on the keycard. + /// + public KeycardLevels Levels => new KeycardLevels(Permissions); + #region Custom Keycards /// @@ -140,8 +150,8 @@ internal override void OnRemove() if (detailBase is not ICustomizableDetail customizableDetail) continue; - customizableDetail.SetArguments(new ArraySegment(args, index, customizableDetail.CustomizablePropertiesAmount)); - index += customizableDetail.CustomizablePropertiesAmount; + customizableDetail.SetArguments(new ArraySegment(args, index, customizableDetail.CustomizablePropertiesAmount)); + index += customizableDetail.CustomizablePropertiesAmount; } return (KeycardItem?)targetPlayer.AddItem(itemType); diff --git a/LabApi/Features/Wrappers/Players/Player.cs b/LabApi/Features/Wrappers/Players/Player.cs index d6bca3d0..b3592af2 100644 --- a/LabApi/Features/Wrappers/Players/Player.cs +++ b/LabApi/Features/Wrappers/Players/Player.cs @@ -754,6 +754,28 @@ public Vector2 LookRotation set => ReferenceHub.TryOverrideRotation(value); } + /// + /// Gets or sets player's scale. Player's role must be for it to take effect.
+ /// Vertical scale is not linear as the model's origin and scaling is done from player's feet. + ///
+ public Vector3 Scale + { + get + { + if (ReferenceHub.roleManager.CurrentRole is not IFpcRole fpcRole) + return Vector3.zero; + + return fpcRole.FpcModule.Motor.ScaleController.Scale; + } + set + { + if (ReferenceHub.roleManager.CurrentRole is not IFpcRole fpcRole) + return; + + fpcRole.FpcModule.Motor.ScaleController.Scale = value; + } + } + /// /// Gets or sets player's remaining stamina (min = 0, max = 1). /// From 3206e28df5cba879b6a294f1dbbf83692e238226 Mon Sep 17 00:00:00 2001 From: Beryl <10091181+SebasCapo@users.noreply.github.com> Date: Sun, 8 Jun 2025 21:33:12 -0300 Subject: [PATCH 021/215] 1.1.0 Version Bump --- LabApi/LabApi.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LabApi/LabApi.csproj b/LabApi/LabApi.csproj index d5c4a3b7..0a4ab084 100644 --- a/LabApi/LabApi.csproj +++ b/LabApi/LabApi.csproj @@ -6,7 +6,7 @@ x64 12.0 - 1.0.2 + 1.1.0 LabApi Northwood.LabAPI From d8b6b2ae2276e1a58761d13f3a45102fa56b11b4 Mon Sep 17 00:00:00 2001 From: brayden-dowson Date: Sat, 14 Jun 2025 22:29:25 +0930 Subject: [PATCH 022/215] missing null check --- LabApi/Features/Wrappers/Players/Ragdoll.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/LabApi/Features/Wrappers/Players/Ragdoll.cs b/LabApi/Features/Wrappers/Players/Ragdoll.cs index 87789dd1..c56d050b 100644 --- a/LabApi/Features/Wrappers/Players/Ragdoll.cs +++ b/LabApi/Features/Wrappers/Players/Ragdoll.cs @@ -33,9 +33,14 @@ public class Ragdoll private Ragdoll(BasicRagdoll ragdoll) { Base = ragdoll; - GameObject = ragdoll.gameObject; - Transform = ragdoll.transform; - Dictionary.TryAdd(ragdoll, this); + + // fix when #257 is merged. + if (ragdoll != null) + { + GameObject = ragdoll.gameObject; + Transform = ragdoll.transform; + Dictionary.TryAdd(ragdoll, this); + } } /// From 030d5ca37dbe1af88142219295aa2027b6a436ff Mon Sep 17 00:00:00 2001 From: brayden-dowson <88667957+brayden-dowson@users.noreply.github.com> Date: Fri, 27 Jun 2025 06:00:08 +0930 Subject: [PATCH 023/215] Fixed issue where getting player wrapper before unity Start has been called caused error in AddPlayer (#248) --- LabApi/Features/Wrappers/Players/Player.cs | 50 ++++++++++++++++++---- LabApi/Features/Wrappers/Players/Server.cs | 32 +------------- 2 files changed, 43 insertions(+), 39 deletions(-) diff --git a/LabApi/Features/Wrappers/Players/Player.cs b/LabApi/Features/Wrappers/Players/Player.cs index b3592af2..d23dadb8 100644 --- a/LabApi/Features/Wrappers/Players/Player.cs +++ b/LabApi/Features/Wrappers/Players/Player.cs @@ -844,7 +844,7 @@ public static IEnumerable GetAll(PlayerSearchFlags flags = PlayerSearchF if (referenceHub == null) return null; - return Dictionary.TryGetValue(referenceHub, out Player player) ? player : new Player(referenceHub); + return Dictionary.TryGetValue(referenceHub, out Player player) ? player : CreatePlayerWrapper(referenceHub); } /// @@ -1586,14 +1586,38 @@ public override string ToString() return $"[Player: DisplayName={DisplayName}, PlayerId={PlayerId}, NetworkId={NetworkId}, UserId={UserId}, IpAddress={IpAddress}, Role={Role}, IsServer={IsServer}, IsReady={IsReady}]"; } + /// + /// Creates a new wrapper for the player using the player's . + /// + /// The of the player. + /// The created player wrapper. + private static Player CreatePlayerWrapper(ReferenceHub referenceHub) + { + Player player = new(referenceHub); + + if (referenceHub.isLocalPlayer) + Server.Host = player; + + return player; + } + /// /// Handles the creation of a player in the server. /// /// The reference hub of the player. private static void AddPlayer(ReferenceHub referenceHub) { - if (!referenceHub.isLocalPlayer) - _ = new Player(referenceHub); + try + { + if (Dictionary.ContainsKey(referenceHub)) + return; + + CreatePlayerWrapper(referenceHub); + } + catch(Exception ex) + { + Console.Logger.InternalError($"Failed to handle player addition with exception: {ex}"); + } } /// @@ -1602,12 +1626,22 @@ private static void AddPlayer(ReferenceHub referenceHub) /// The reference hub of the player. private static void RemovePlayer(ReferenceHub referenceHub) { - if (referenceHub.authManager.UserId != null) - UserIdCache.Remove(referenceHub.authManager.UserId); + try + { + if (referenceHub.authManager.UserId != null) + UserIdCache.Remove(referenceHub.authManager.UserId); - if (TryGet(referenceHub.gameObject, out Player? player)) - CustomDataStoreManager.RemovePlayer(player); + if (TryGet(referenceHub.gameObject, out Player? player)) + CustomDataStoreManager.RemovePlayer(player); - Dictionary.Remove(referenceHub); + if (referenceHub.isLocalPlayer) + Server.Host = null; + + Dictionary.Remove(referenceHub); + } + catch(Exception ex) + { + Console.Logger.InternalError($"Failed to handle player removal with exception: {ex}"); + } } } diff --git a/LabApi/Features/Wrappers/Players/Server.cs b/LabApi/Features/Wrappers/Players/Server.cs index 48fd949c..3639e8d1 100644 --- a/LabApi/Features/Wrappers/Players/Server.cs +++ b/LabApi/Features/Wrappers/Players/Server.cs @@ -20,20 +20,10 @@ namespace LabApi.Features.Wrappers; /// public static class Server { - /// - /// Initializes the class to subscribe to events. - /// - [InitializeWrapper] - internal static void Initialize() - { - ReferenceHub.OnPlayerAdded += AddHost; - ReferenceHub.OnPlayerRemoved += RemoveHost; - } - /// /// The Instance. /// - public static Player? Host { get; private set; } + public static Player? Host { get; internal set; } /// /// Gets the IP address of the server. @@ -449,26 +439,6 @@ public static void SendBroadcast(Player player, string message, ushort duration, /// The player to clear the broadcast's. public static void ClearBroadcasts(Player player) => Broadcast.Singleton.TargetClearElements(player.Connection); - /// - /// Handles the creation of the host in the server. - /// - /// The reference hub to add. - private static void AddHost(ReferenceHub referenceHub) - { - if (referenceHub.isLocalPlayer) - Host = new Player(referenceHub); - } - - /// - /// Handles the removal of the host from the server. - /// - /// The reference hub to remove. - private static void RemoveHost(ReferenceHub referenceHub) - { - if (referenceHub.isLocalPlayer) - Host = null; - } - /// /// Interface for getting and setting key value limits. /// From 838e39eafbf5fc8d9e06d41930cbd6379e2e0de6 Mon Sep 17 00:00:00 2001 From: Lumi Date: Thu, 26 Jun 2025 22:05:38 +0100 Subject: [PATCH 024/215] feat: player factions (#184) * feat: player sides * feat: use faction instead * docs: wrong see cref * using the team instead --------- Co-authored-by: Jesus QC <69375249+Jesus-QC@users.noreply.github.com> --- LabApi/Features/Wrappers/Players/Player.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/LabApi/Features/Wrappers/Players/Player.cs b/LabApi/Features/Wrappers/Players/Player.cs index d6bca3d0..c4df50b4 100644 --- a/LabApi/Features/Wrappers/Players/Player.cs +++ b/LabApi/Features/Wrappers/Players/Player.cs @@ -677,6 +677,11 @@ public Player? DisarmedBy /// public Team Team => RoleBase.Team; + /// + /// Gets the player's current . + /// + public Faction Faction => Team.GetFaction(); + /// /// Gets whether the player is currently Alive. /// From 2c88d2e5ca6cc9b66939a7db380659259c5f0b66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?paws=20=E2=99=A1?= <135553058+pawslee@users.noreply.github.com> Date: Thu, 26 Jun 2025 16:05:55 -0500 Subject: [PATCH 025/215] replace issue templates with forms (#150) --- .github/ISSUE_TEMPLATE/1-bug-template.yml | 44 ++++++++++++++++++++++ .github/ISSUE_TEMPLATE/2-idea-template.yml | 18 +++++++++ .github/ISSUE_TEMPLATE/3-task-template.yml | 27 +++++++++++++ .github/ISSUE_TEMPLATE/idea-template.md | 18 --------- .github/ISSUE_TEMPLATE/task-template.md | 18 --------- 5 files changed, 89 insertions(+), 36 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/1-bug-template.yml create mode 100644 .github/ISSUE_TEMPLATE/2-idea-template.yml create mode 100644 .github/ISSUE_TEMPLATE/3-task-template.yml delete mode 100644 .github/ISSUE_TEMPLATE/idea-template.md delete mode 100644 .github/ISSUE_TEMPLATE/task-template.md diff --git a/.github/ISSUE_TEMPLATE/1-bug-template.yml b/.github/ISSUE_TEMPLATE/1-bug-template.yml new file mode 100644 index 00000000..d5879d7a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/1-bug-template.yml @@ -0,0 +1,44 @@ +name: Bug Template +description: Template for reporting a bug with LabAPI. +title: "[BUG]: " +labels: ["bug"] +body: + - type: checkboxes + attributes: + label: Before You Report + options: + - label: I have [searched](https://github.com/northwood-studios/LabAPI/issues/) for existing reports of this bug, and this bug report is unique. + required: + - type: input + attributes: + label: Version + placeholder: "Example: 1.0.2" + validations: + required: true + - type: textarea + id: desc + attributes: + label: Description + description: Provide a clear description for the bug. What are the effects of it? + validations: + required: true + - type: textarea + id: to-reproduce + attributes: + label: To Reproduce + description: Include steps to reproduce, and code if applicable and possible. + validations: + required: true + - type: textarea + id: expected-behavior + attributes: + label: Expected Behavior + description: What did you expect to happen? + - type: textarea + id: logs + attributes: + label: Additional Information + description: Attach any pictures of the bug, if possible, and the logs when it happened. + validations: + required: true + \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/2-idea-template.yml b/.github/ISSUE_TEMPLATE/2-idea-template.yml new file mode 100644 index 00000000..82d9c118 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/2-idea-template.yml @@ -0,0 +1,18 @@ +name: Idea Template +description: Template for ideas we may not want to spend too much time formalizing into tasks. +title: "[IDEA] <title>" +labels: ["idea"] +body: + - type: textarea + id: goal-description + attributes: + label: Goal Description + description: A description of what you would like to see implemented, and perhaps how. Can be as vague and informal as you want. However, being descriptive is always appreciated. 😉 + validations: + required: true + - type: textarea + id: notes + attributes: + label: Notes + description: These should serve as a guide of different ideas or concerns you may have regarding the task, providing some insight of your vision to the programmer working on it. + \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/3-task-template.yml b/.github/ISSUE_TEMPLATE/3-task-template.yml new file mode 100644 index 00000000..f8c56b5d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/3-task-template.yml @@ -0,0 +1,27 @@ +name: Task Template +description: Template for tasks regarding new improvements for programmers. +title: "[TASK] <title>" +labels: ["task"] +body: + - type: textarea + id: desc + attributes: + label: Description + description: A description of the task, and a brief overview of what must be done to accomplish it. + validations: + required: true + - type: textarea + id: notes + attributes: + label: Notes + description: These should serve as a guide of different ideas or concerns you may have regarding the task, providing some insight of your vision to the programmer working on it. + - type: textarea + id: checklist + attributes: + label: Checklist + description: Everything that needs to be completed for the task to be considered complete and ready to be closed. + value: | + - [ ] Example 1. + - [ ] Example 2. + + \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/idea-template.md b/.github/ISSUE_TEMPLATE/idea-template.md deleted file mode 100644 index c5b90dd8..00000000 --- a/.github/ISSUE_TEMPLATE/idea-template.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -name: Idea Template -about: Template for ideas we may not want to spend too much time formalizing into - tasks -title: "[IDEA] Title" -labels: idea -assignees: '' - ---- - -## Goal Description -> A description of what you would like to see implemented, and perhaps how. Can be as vague and informal as you want. However, being descriptive is always appreciated. 😉 -Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. - -## Notes -> These should serve as a guide of different ideas or concerns you may have regarding task, providing some insight of your vision to the programmer working on it. -- Example1. -- Example2. diff --git a/.github/ISSUE_TEMPLATE/task-template.md b/.github/ISSUE_TEMPLATE/task-template.md deleted file mode 100644 index 50eaf2e5..00000000 --- a/.github/ISSUE_TEMPLATE/task-template.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -name: Task Template -about: Template for tasks regarding new improvements for programmers -title: "[TASK] Title" -labels: task -assignees: '' - ---- - -## Notes -> These should serve as a guide of different ideas or concerns you may have regarding task, providing some insight of your vision to the programmer working on it. -- Example1. -- Example2. - -## Task / Checklist -> Everything that needs to be completed for the task to be considered complete and ready to be closed. -- [ ] Example1. -- [ ] Example2. From cff520368c384799f7dd6bb1df8a9a762b52e53b Mon Sep 17 00:00:00 2001 From: Morgan <72927329+LilNesquuik@users.noreply.github.com> Date: Thu, 26 Jun 2025 23:06:05 +0200 Subject: [PATCH 026/215] load config before commands (#134) --- LabApi/Loader/PluginLoader.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/LabApi/Loader/PluginLoader.cs b/LabApi/Loader/PluginLoader.cs index 07f15392..bc3b8ec6 100644 --- a/LabApi/Loader/PluginLoader.cs +++ b/LabApi/Loader/PluginLoader.cs @@ -258,11 +258,11 @@ public static void EnablePlugin(Plugin plugin) // We mark the server as modded. CustomNetworkManager.Modded = true; - // We register all the plugin commands - plugin.RegisterCommands(); - // We load the configurations of the plugin plugin.LoadConfigs(); + + // We register all the plugin commands + plugin.RegisterCommands(); // We enable the plugin if it is not disabled plugin.Enable(); From 4238efad1e716523d04c452d885ff2f31f51fa13 Mon Sep 17 00:00:00 2001 From: Crous <150693998+CCrous@users.noreply.github.com> Date: Fri, 27 Jun 2025 05:06:29 +0800 Subject: [PATCH 027/215] fix: token name error (#69) --- .../Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs b/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs index 3f4bc79a..db8b61c8 100644 --- a/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs +++ b/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs @@ -76,7 +76,7 @@ public int RespawnTokens if (Base is not ILimitedWave wave) return; - wave.InitialRespawnTokens = value; + wave.RespawnTokens = value; WaveUpdateMessage.ServerSendUpdate(Base, UpdateMessageFlags.Tokens); } } From 4982c420a693b3722c1bad6a908d4420cc1c7770 Mon Sep 17 00:00:00 2001 From: Jesus QC <69375249+Jesus-QC@users.noreply.github.com> Date: Thu, 26 Jun 2025 23:42:19 +0200 Subject: [PATCH 028/215] Dev Fetch (#197) * Adds throw propertly to Item EventsArgs (#246) * Added more properties to PlayerDeath event arg (#241) * Added OldRole to PlayerDeath event arg * docs * more properties * Apply suggestions from code review --------- Co-authored-by: Beryl <10091181+SebasCapo@users.noreply.github.com> * Adds attacker player to placed blood event (#239) * Playerscale + events (#244) * Scale * Added chaos and surface pass keycard to the keycard item register * Added CanOpen to UnlockingGenerator event Added Scp079Pinging/ed event Added RoundEndingConditionsCheck event Added permisisosn to the keycard wrapper * PingType to enum namespace * Ping to enum, comments * 1.1.0 Version Bump --------- Co-authored-by: brayden-dowson <88667957+brayden-dowson@users.noreply.github.com> Co-authored-by: Beryl <10091181+SebasCapo@users.noreply.github.com> Co-authored-by: David <david.sebesta@post.cz> --- .../PlayerEvents/PlayerDeathEventArgs.cs | 33 +++++++++++- .../PlayerDroppedItemEventArgs.cs | 9 +++- .../PlayerDroppingItemEventArgs.cs | 9 +++- .../PlayerPlacedBloodEventArgs.cs | 9 +++- .../PlayerPlacingBloodEventArgs.cs | 9 +++- .../PlayerUnlockingGeneratorEventArgs.cs | 13 ++++- .../Scp079Events/Scp079PingedEventArgs.cs | 48 +++++++++++++++++ .../Scp079Events/Scp079PingingEventArgs.cs | 52 +++++++++++++++++++ .../RoundEndingConditionsCheckEventArgs.cs | 23 ++++++++ .../Handlers/Scp079Events.EventHandlers.cs | 10 ++++ .../Handlers/ServerEvents.EventHandlers.cs | 5 ++ LabApi/Features/Enums/Scp079PingType.cs | 44 ++++++++++++++++ .../Features/Wrappers/Facility/Doors/Door.cs | 3 +- LabApi/Features/Wrappers/Items/Item.cs | 2 + LabApi/Features/Wrappers/Items/KeycardItem.cs | 14 ++++- LabApi/Features/Wrappers/Players/Player.cs | 22 ++++++++ LabApi/LabApi.csproj | 2 +- 17 files changed, 295 insertions(+), 12 deletions(-) create mode 100644 LabApi/Events/Arguments/Scp079Events/Scp079PingedEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp079Events/Scp079PingingEventArgs.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/RoundEndingConditionsCheckEventArgs.cs create mode 100644 LabApi/Features/Enums/Scp079PingType.cs diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDeathEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDeathEventArgs.cs index b32a0366..d58359eb 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDeathEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDeathEventArgs.cs @@ -1,7 +1,9 @@ using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using PlayerRoles; using PlayerStatsSystem; using System; +using UnityEngine; namespace LabApi.Events.Arguments.PlayerEvents; @@ -16,11 +18,20 @@ public class PlayerDeathEventArgs : EventArgs, IPlayerEvent /// <param name="player">The player who died.</param> /// <param name="attacker">The player who caused the death.</param> /// <param name="damageHandler">The damage that caused the death.</param> - public PlayerDeathEventArgs(ReferenceHub player, ReferenceHub? attacker, DamageHandlerBase damageHandler) + /// <param name="oldRole">The previous role of the player before death.</param> + /// <param name="oldPosition">The previous world position of the player before death.</param> + /// <param name="oldVelocity">The previous velocity of the player before death.</param> + /// <param name="oldCameraRotation">The previous world rotation of the players camera before death.</param> + public PlayerDeathEventArgs(ReferenceHub player, ReferenceHub? attacker, DamageHandlerBase damageHandler, + RoleTypeId oldRole, Vector3 oldPosition, Vector3 oldVelocity, Quaternion oldCameraRotation) { Player = Player.Get(player); Attacker = Player.Get(attacker); DamageHandler = damageHandler; + OldRole = oldRole; + OldPosition = oldPosition; + OldVelocity = oldVelocity; + OldCameraRotation = oldCameraRotation; } /// <summary> @@ -37,4 +48,24 @@ public PlayerDeathEventArgs(ReferenceHub player, ReferenceHub? attacker, DamageH /// Gets the damage that caused the death. /// </summary> public DamageHandlerBase DamageHandler { get; } + + /// <summary> + /// Gets the role of the <see cref="Player"/> before they had died. + /// </summary> + public RoleTypeId OldRole { get; } + + /// <summary> + /// Gets the player's position before they died. + /// </summary> + public Vector3 OldPosition { get; } + + /// <summary> + /// Gets the player's velocity before they died. + /// </summary> + public Vector3 OldVelocity { get; } + + /// <summary> + /// Gets the player's camera rotation before they died. + /// </summary> + public Quaternion OldCameraRotation { get; } } \ No newline at end of file diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppedItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppedItemEventArgs.cs index b6f17fd0..9dd3ff9e 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppedItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppedItemEventArgs.cs @@ -15,10 +15,12 @@ public class PlayerDroppedItemEventArgs : EventArgs, IPlayerEvent, IPickupEvent /// </summary> /// <param name="player">The player who dropped the item.</param> /// <param name="pickup">The item pickup.</param> - public PlayerDroppedItemEventArgs(ReferenceHub player, ItemPickupBase pickup) + /// <param name="isThrowing">Whether the item will be thrown.</param> + public PlayerDroppedItemEventArgs(ReferenceHub player, ItemPickupBase pickup, bool isThrowing) { Player = Player.Get(player); Pickup = Pickup.Get(pickup); + Throw = isThrowing; } /// <summary> @@ -30,4 +32,9 @@ public PlayerDroppedItemEventArgs(ReferenceHub player, ItemPickupBase pickup) /// Gets the item pickup. /// </summary> public Pickup Pickup { get; } + + /// <summary> + /// Gets or sets whether the <see cref="Pickup"/> will be thrown by the <see cref="Player"/>. + /// </summary> + public bool Throw { get; set; } } \ No newline at end of file diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs index 3ae57892..dc5f3e4d 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs @@ -15,11 +15,13 @@ public class PlayerDroppingItemEventArgs : EventArgs, ICancellableEvent, IItemEv /// </summary> /// <param name="player">The player who is dropping the item.</param> /// <param name="item">The item being dropped.</param> - public PlayerDroppingItemEventArgs(ReferenceHub player, ItemBase item) + /// <param name="isThrowing">Whether the item will be thrown.</param> + public PlayerDroppingItemEventArgs(ReferenceHub player, ItemBase item, bool isThrowing) { IsAllowed = true; Player = Player.Get(player); Item = Item.Get(item); + Throw = isThrowing; } /// <summary> @@ -32,6 +34,11 @@ public PlayerDroppingItemEventArgs(ReferenceHub player, ItemBase item) /// </summary> public Item Item { get; } + /// <summary> + /// Gets or sets whether the <see cref="Pickup"/> will be thrown by the <see cref="Player"/>. + /// </summary> + public bool Throw { get; set; } + /// <inheritdoc /> public bool IsAllowed { get; set; } } \ No newline at end of file diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBloodEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBloodEventArgs.cs index 344c74a2..e4385b58 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBloodEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBloodEventArgs.cs @@ -14,11 +14,13 @@ public class PlayerPlacedBloodEventArgs : EventArgs, IPlayerEvent /// Initializes a new instance of the <see cref="PlayerPlacedBloodEventArgs"/> class. /// </summary> /// <param name="player">The player whose blood it is.</param> + /// <param name="attacker">The player that attacked.</param> /// <param name="hitPosition">Position at which blood has been spawned.</param> /// <param name="startRaycast">Position where the blood decal raycast will start for it to be properly attached to surface.</param> - public PlayerPlacedBloodEventArgs(ReferenceHub player, Vector3 hitPosition, Vector3 startRaycast) + public PlayerPlacedBloodEventArgs(ReferenceHub player, ReferenceHub attacker, Vector3 hitPosition, Vector3 startRaycast) { Player = Player.Get(player); + Attacker = Player.Get(attacker); HitPosition = hitPosition; RaycastStart = startRaycast; } @@ -28,6 +30,11 @@ public PlayerPlacedBloodEventArgs(ReferenceHub player, Vector3 hitPosition, Vect /// </summary> public Player Player { get; } + /// <summary> + /// Gets the player that attacked the <see cref="Player"/>. + /// </summary> + public Player Attacker { get; } + /// <summary> /// Gets the position at which blood has been spawned. /// </summary> diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacingBloodEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacingBloodEventArgs.cs index 26bcf50d..cf28fff4 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacingBloodEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacingBloodEventArgs.cs @@ -14,12 +14,14 @@ public class PlayerPlacingBloodEventArgs : EventArgs, IPlayerEvent, ICancellable /// Initializes a new instance of the <see cref="PlayerPlacingBloodEventArgs"/> class. /// </summary> /// <param name="player">The player whose blood it is.</param> + /// <param name="attacker">The player that attacked.</param> /// <param name="hitPosition">Position at which is blood being placed.</param> /// <param name="startRaycast">Position where the blood decal raycast will start for it to be properly attached to surface.</param> - public PlayerPlacingBloodEventArgs(ReferenceHub player, Vector3 hitPosition, Vector3 startRaycast) + public PlayerPlacingBloodEventArgs(ReferenceHub player, ReferenceHub attacker, Vector3 hitPosition, Vector3 startRaycast) { IsAllowed = true; Player = Player.Get(player); + Attacker = Player.Get(attacker); HitPosition = hitPosition; RaycastStart = startRaycast; } @@ -29,6 +31,11 @@ public PlayerPlacingBloodEventArgs(ReferenceHub player, Vector3 hitPosition, Vec /// </summary> public Player Player { get; } + /// <summary> + /// Gets the player that attacked the <see cref="Player"/>. + /// </summary> + public Player Attacker { get; } + /// <summary> /// Gets the position at which is blood being placed. /// </summary> diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockingGeneratorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockingGeneratorEventArgs.cs index 57794b3f..9cb18a10 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockingGeneratorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockingGeneratorEventArgs.cs @@ -15,11 +15,13 @@ public class PlayerUnlockingGeneratorEventArgs : EventArgs, IPlayerEvent, IGener /// </summary> /// <param name="player">The player who is unlocking the generator.</param> /// <param name="generator">The generator that the player is unlocking.</param> - public PlayerUnlockingGeneratorEventArgs(ReferenceHub player, Scp079Generator generator) + /// <param name="canOpen">Whether the generator can be opened.</param> + public PlayerUnlockingGeneratorEventArgs(ReferenceHub player, Scp079Generator generator, bool canOpen) { Player = Player.Get(player); Generator = Generator.Get(generator); IsAllowed = true; + CanOpen = canOpen; } /// <summary> @@ -30,7 +32,14 @@ public PlayerUnlockingGeneratorEventArgs(ReferenceHub player, Scp079Generator ge /// <inheritdoc /> public Generator Generator { get; } - /// <inheritdoc/> + /// <summary> + /// Gets whether the player can open the generator. + /// </summary> + public bool CanOpen { get; set; } + + /// <summary> + /// Gets whether this event is allowed. Not allowing this event will not unlock the generator and no denied animation is played. + /// </summary> public bool IsAllowed { get; set; } } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079PingedEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079PingedEventArgs.cs new file mode 100644 index 00000000..19b49334 --- /dev/null +++ b/LabApi/Events/Arguments/Scp079Events/Scp079PingedEventArgs.cs @@ -0,0 +1,48 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Enums; +using LabApi.Features.Wrappers; +using System; +using UnityEngine; + +namespace LabApi.Events.Arguments.Scp079Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp079Events.Pinged"/> event. +/// </summary> +public class Scp079PingedEventArgs : EventArgs, IPlayerEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp079PingedEventArgs"/> class. + /// </summary> + /// <param name="player">The SCP-079 player instance.</param> + /// <param name="position">The world position of the ping.</param> + /// <param name="normal">Normal vector for the ping.</param> + /// <param name="index">The index of the ping type.</param> + public Scp079PingedEventArgs(ReferenceHub player, Vector3 position, Vector3 normal, byte index) + { + Player = Player.Get(player); + Position = position; + Normal = normal; + PingType = (Scp079PingType)index; + } + + /// <summary> + /// Gets the SCP-079 player instance. + /// </summary> + public Player Player { get; } + + /// <summary> + /// Gets the world ping position. + /// </summary> + public Vector3 Position { get; } + + /// <summary> + /// Gets the ping normal vector. + /// </summary> + public Vector3 Normal { get; } + + /// <summary> + /// Gets the type of the ping used the icon. + /// </summary> + public Scp079PingType PingType { get; } +} diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079PingingEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079PingingEventArgs.cs new file mode 100644 index 00000000..f27502db --- /dev/null +++ b/LabApi/Events/Arguments/Scp079Events/Scp079PingingEventArgs.cs @@ -0,0 +1,52 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Enums; +using LabApi.Features.Wrappers; +using System; +using UnityEngine; + +namespace LabApi.Events.Arguments.Scp079Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp079Events.Pinging"/> event. +/// </summary> +public class Scp079PingingEventArgs : EventArgs, IPlayerEvent, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp079PingingEventArgs"/> class. + /// </summary> + /// <param name="player">The SCP-079 player instance.</param> + /// <param name="position">The world position of the ping.</param> + /// <param name="normal">Normal vector for the ping.</param> + /// <param name="index">The index of the ping type.</param> + public Scp079PingingEventArgs(ReferenceHub player, Vector3 position, Vector3 normal, byte index) + { + Player = Player.Get(player); + Position = position; + Normal = normal; + PingType = (Scp079PingType)index; + IsAllowed = true; + } + + /// <summary> + /// Gets the SCP-079 player instance. + /// </summary> + public Player Player { get; } + + /// <summary> + /// Gets or sets the world ping position. + /// </summary> + public Vector3 Position { get; set; } + + /// <summary> + /// Gets or sets the ping normal vector. + /// </summary> + public Vector3 Normal { get; set; } + + /// <summary> + /// Gets or sets the type of the ping used the icon. + /// </summary> + public Scp079PingType PingType { get; set; } + + /// <inheritdoc/> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/RoundEndingConditionsCheckEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/RoundEndingConditionsCheckEventArgs.cs new file mode 100644 index 00000000..4ddd004b --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/RoundEndingConditionsCheckEventArgs.cs @@ -0,0 +1,23 @@ +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Contains the arguments for the <see cref="Handlers.ServerEvents.RoundEnding"/> event. +/// </summary> +public class RoundEndingConditionsCheckEventArgs : EventArgs +{ + /// <summary> + /// Initializes a new instance of the <see cref="RoundEndingConditionsCheckEventArgs"/> class. + /// </summary> + /// <param name="canEnd">Whether the round end conditions are met</param> + public RoundEndingConditionsCheckEventArgs(bool canEnd) + { + CanEnd = canEnd; + } + + /// <summary> + /// Gets or sets whether the round end conditions are met. + /// </summary> + public bool CanEnd { get; set; } +} diff --git a/LabApi/Events/Handlers/Scp079Events.EventHandlers.cs b/LabApi/Events/Handlers/Scp079Events.EventHandlers.cs index d3820f8e..43b2097e 100644 --- a/LabApi/Events/Handlers/Scp079Events.EventHandlers.cs +++ b/LabApi/Events/Handlers/Scp079Events.EventHandlers.cs @@ -116,4 +116,14 @@ public static partial class Scp079Events /// Gets called when SCP-079 has used a tesla. /// </summary> public static event LabEventHandler<Scp079UsedTeslaEventArgs>? UsedTesla; + + /// <summary> + /// Gets called when SCP-079 is using ping ability. + /// </summary> + public static event LabEventHandler<Scp079PingingEventArgs>? Pinging; + + /// <summary> + /// Gets called when SCP-079 used ping ability. + /// </summary> + public static event LabEventHandler<Scp079PingedEventArgs>? Pinged; } \ No newline at end of file diff --git a/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs b/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs index ef5066ec..7c8ea582 100644 --- a/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs +++ b/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs @@ -17,6 +17,11 @@ public static partial class ServerEvents /// </summary> public static event LabEventHandler? RoundRestarted; + /// <summary> + /// Gets called when round end conditions are checked. + /// </summary> + public static event LabEventHandler<RoundEndingConditionsCheckEventArgs>? RoundEndingConditionsCheck; + /// <summary> /// Gets called when the round is ending. /// </summary> diff --git a/LabApi/Features/Enums/Scp079PingType.cs b/LabApi/Features/Enums/Scp079PingType.cs new file mode 100644 index 00000000..9060ef6d --- /dev/null +++ b/LabApi/Features/Enums/Scp079PingType.cs @@ -0,0 +1,44 @@ +using LabApi.Features.Wrappers; + +namespace LabApi.Features.Enums; + +/// <summary> +/// Enum used for type of the ping. +/// </summary> +public enum Scp079PingType : byte +{ + /// <summary> + /// <see cref="Wrappers.Generator"/> ping. + /// </summary> + Generator = 0, + + /// <summary> + /// <see cref="ExplosiveGrenadeProjectile"/> and <see cref="FlashbangProjectile"/> pings. + /// </summary> + Projectile = 1, + + /// <summary> + /// Micro-HID ping. + /// </summary> + MicroHid = 2, + + /// <summary> + /// <see cref="Player"/> human role ping. + /// </summary> + Human = 3, + + /// <summary> + /// <see cref="Wrappers.Elevator"/> ping. + /// </summary> + Elevator = 4, + + /// <summary> + /// <see cref="Wrappers.Door"/> ping. + /// </summary> + Door = 5, + + /// <summary> + /// Default "i" icon ping. + /// </summary> + Default = 6, +} diff --git a/LabApi/Features/Wrappers/Facility/Doors/Door.cs b/LabApi/Features/Wrappers/Facility/Doors/Door.cs index 14bddcb2..6e2c6ff5 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/Door.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/Door.cs @@ -1,5 +1,4 @@ using Generators; -using Hazards; using Interactables.Interobjects; using Interactables.Interobjects.DoorUtils; using LabApi.Features.Enums; @@ -143,7 +142,7 @@ internal virtual void OnRemove() /// <summary> /// Gets the rooms which have this door. /// </summary> - public RoomIdentifier[] Rooms => Base.Rooms; + public Room[] Rooms => Base.Rooms.Select(Room.Get).ToArray(); /// <summary> /// Gets the zone in which this door is. diff --git a/LabApi/Features/Wrappers/Items/Item.cs b/LabApi/Features/Wrappers/Items/Item.cs index c0c32280..6cb82c72 100644 --- a/LabApi/Features/Wrappers/Items/Item.cs +++ b/LabApi/Features/Wrappers/Items/Item.cs @@ -65,6 +65,8 @@ internal static void Initialize() Register<BodyArmor>(x => new BodyArmorItem(x)); Register<InventorySystem.Items.ThrowableProjectiles.ThrowableItem>(x => new ThrowableItem(x)); Register<InventorySystem.Items.Keycards.KeycardItem>(x => new KeycardItem(x)); + Register<InventorySystem.Items.Keycards.ChaosKeycardItem>(x => new KeycardItem(x)); + Register<InventorySystem.Items.Keycards.SingleUseKeycardItem>(x => new KeycardItem(x)); Register<InventorySystem.Items.MicroHID.MicroHIDItem>(x => new MicroHIDItem(x)); } diff --git a/LabApi/Features/Wrappers/Items/KeycardItem.cs b/LabApi/Features/Wrappers/Items/KeycardItem.cs index cd605b66..f6ba7f73 100644 --- a/LabApi/Features/Wrappers/Items/KeycardItem.cs +++ b/LabApi/Features/Wrappers/Items/KeycardItem.cs @@ -51,6 +51,16 @@ internal override void OnRemove() /// </summary> public new BaseKeycardItem Base { get; } + /// <summary> + /// Gets the <see cref="DoorPermissionFlags"/> of the keycard. + /// </summary> + public DoorPermissionFlags Permissions => Base.GetPermissions(null); + + /// <summary> + /// Gets the <see cref="KeycardLevels"/> of the keycard which represent the tiers shown on the keycard. + /// </summary> + public KeycardLevels Levels => new KeycardLevels(Permissions); + #region Custom Keycards /// <summary> @@ -140,8 +150,8 @@ internal override void OnRemove() if (detailBase is not ICustomizableDetail customizableDetail) continue; - customizableDetail.SetArguments(new ArraySegment<object>(args, index, customizableDetail.CustomizablePropertiesAmount)); - index += customizableDetail.CustomizablePropertiesAmount; + customizableDetail.SetArguments(new ArraySegment<object>(args, index, customizableDetail.CustomizablePropertiesAmount)); + index += customizableDetail.CustomizablePropertiesAmount; } return (KeycardItem?)targetPlayer.AddItem(itemType); diff --git a/LabApi/Features/Wrappers/Players/Player.cs b/LabApi/Features/Wrappers/Players/Player.cs index c4df50b4..b9d3bc7e 100644 --- a/LabApi/Features/Wrappers/Players/Player.cs +++ b/LabApi/Features/Wrappers/Players/Player.cs @@ -759,6 +759,28 @@ public Vector2 LookRotation set => ReferenceHub.TryOverrideRotation(value); } + /// <summary> + /// Gets or sets player's scale. Player's role must be <see cref="IFpcRole"/> for it to take effect.<br/> + /// Vertical scale is not linear as the model's origin and scaling is done from player's feet. + /// </summary> + public Vector3 Scale + { + get + { + if (ReferenceHub.roleManager.CurrentRole is not IFpcRole fpcRole) + return Vector3.zero; + + return fpcRole.FpcModule.Motor.ScaleController.Scale; + } + set + { + if (ReferenceHub.roleManager.CurrentRole is not IFpcRole fpcRole) + return; + + fpcRole.FpcModule.Motor.ScaleController.Scale = value; + } + } + /// <summary> /// Gets or sets player's remaining stamina (min = 0, max = 1). /// </summary> diff --git a/LabApi/LabApi.csproj b/LabApi/LabApi.csproj index d5c4a3b7..0a4ab084 100644 --- a/LabApi/LabApi.csproj +++ b/LabApi/LabApi.csproj @@ -6,7 +6,7 @@ <PlatformTarget>x64</PlatformTarget> <LangVersion>12.0</LangVersion> - <Version>1.0.2</Version> + <Version>1.1.0</Version> <AssemblyName>LabApi</AssemblyName> <PackageId>Northwood.LabAPI</PackageId> From 329f3bbf33bd0e698026ba8864a6d6e41a3e9bc8 Mon Sep 17 00:00:00 2001 From: Jesus QC <69375249+Jesus-QC@users.noreply.github.com> Date: Thu, 26 Jun 2025 23:45:27 +0200 Subject: [PATCH 029/215] 1.1.0 (#198) * Adds throw propertly to Item EventsArgs (#246) * Added more properties to PlayerDeath event arg (#241) * Added OldRole to PlayerDeath event arg * docs * more properties * Apply suggestions from code review --------- Co-authored-by: Beryl <10091181+SebasCapo@users.noreply.github.com> * Adds attacker player to placed blood event (#239) * Playerscale + events (#244) * Scale * Added chaos and surface pass keycard to the keycard item register * Added CanOpen to UnlockingGenerator event Added Scp079Pinging/ed event Added RoundEndingConditionsCheck event Added permisisosn to the keycard wrapper * PingType to enum namespace * Ping to enum, comments * 1.1.0 Version Bump --------- Co-authored-by: brayden-dowson <88667957+brayden-dowson@users.noreply.github.com> Co-authored-by: Beryl <10091181+SebasCapo@users.noreply.github.com> Co-authored-by: David <david.sebesta@post.cz> --- .../PlayerEvents/PlayerDeathEventArgs.cs | 33 +++++++++++- .../PlayerDroppedItemEventArgs.cs | 9 +++- .../PlayerDroppingItemEventArgs.cs | 9 +++- .../PlayerPlacedBloodEventArgs.cs | 9 +++- .../PlayerPlacingBloodEventArgs.cs | 9 +++- .../PlayerUnlockingGeneratorEventArgs.cs | 13 ++++- .../Scp079Events/Scp079PingedEventArgs.cs | 48 +++++++++++++++++ .../Scp079Events/Scp079PingingEventArgs.cs | 52 +++++++++++++++++++ .../RoundEndingConditionsCheckEventArgs.cs | 23 ++++++++ .../Handlers/Scp079Events.EventHandlers.cs | 10 ++++ .../Handlers/ServerEvents.EventHandlers.cs | 5 ++ LabApi/Features/Enums/Scp079PingType.cs | 44 ++++++++++++++++ .../Features/Wrappers/Facility/Doors/Door.cs | 3 +- LabApi/Features/Wrappers/Items/Item.cs | 2 + LabApi/Features/Wrappers/Items/KeycardItem.cs | 14 ++++- LabApi/Features/Wrappers/Players/Player.cs | 22 ++++++++ LabApi/LabApi.csproj | 2 +- 17 files changed, 295 insertions(+), 12 deletions(-) create mode 100644 LabApi/Events/Arguments/Scp079Events/Scp079PingedEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp079Events/Scp079PingingEventArgs.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/RoundEndingConditionsCheckEventArgs.cs create mode 100644 LabApi/Features/Enums/Scp079PingType.cs diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDeathEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDeathEventArgs.cs index b32a0366..d58359eb 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDeathEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDeathEventArgs.cs @@ -1,7 +1,9 @@ using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using PlayerRoles; using PlayerStatsSystem; using System; +using UnityEngine; namespace LabApi.Events.Arguments.PlayerEvents; @@ -16,11 +18,20 @@ public class PlayerDeathEventArgs : EventArgs, IPlayerEvent /// <param name="player">The player who died.</param> /// <param name="attacker">The player who caused the death.</param> /// <param name="damageHandler">The damage that caused the death.</param> - public PlayerDeathEventArgs(ReferenceHub player, ReferenceHub? attacker, DamageHandlerBase damageHandler) + /// <param name="oldRole">The previous role of the player before death.</param> + /// <param name="oldPosition">The previous world position of the player before death.</param> + /// <param name="oldVelocity">The previous velocity of the player before death.</param> + /// <param name="oldCameraRotation">The previous world rotation of the players camera before death.</param> + public PlayerDeathEventArgs(ReferenceHub player, ReferenceHub? attacker, DamageHandlerBase damageHandler, + RoleTypeId oldRole, Vector3 oldPosition, Vector3 oldVelocity, Quaternion oldCameraRotation) { Player = Player.Get(player); Attacker = Player.Get(attacker); DamageHandler = damageHandler; + OldRole = oldRole; + OldPosition = oldPosition; + OldVelocity = oldVelocity; + OldCameraRotation = oldCameraRotation; } /// <summary> @@ -37,4 +48,24 @@ public PlayerDeathEventArgs(ReferenceHub player, ReferenceHub? attacker, DamageH /// Gets the damage that caused the death. /// </summary> public DamageHandlerBase DamageHandler { get; } + + /// <summary> + /// Gets the role of the <see cref="Player"/> before they had died. + /// </summary> + public RoleTypeId OldRole { get; } + + /// <summary> + /// Gets the player's position before they died. + /// </summary> + public Vector3 OldPosition { get; } + + /// <summary> + /// Gets the player's velocity before they died. + /// </summary> + public Vector3 OldVelocity { get; } + + /// <summary> + /// Gets the player's camera rotation before they died. + /// </summary> + public Quaternion OldCameraRotation { get; } } \ No newline at end of file diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppedItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppedItemEventArgs.cs index b6f17fd0..9dd3ff9e 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppedItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppedItemEventArgs.cs @@ -15,10 +15,12 @@ public class PlayerDroppedItemEventArgs : EventArgs, IPlayerEvent, IPickupEvent /// </summary> /// <param name="player">The player who dropped the item.</param> /// <param name="pickup">The item pickup.</param> - public PlayerDroppedItemEventArgs(ReferenceHub player, ItemPickupBase pickup) + /// <param name="isThrowing">Whether the item will be thrown.</param> + public PlayerDroppedItemEventArgs(ReferenceHub player, ItemPickupBase pickup, bool isThrowing) { Player = Player.Get(player); Pickup = Pickup.Get(pickup); + Throw = isThrowing; } /// <summary> @@ -30,4 +32,9 @@ public PlayerDroppedItemEventArgs(ReferenceHub player, ItemPickupBase pickup) /// Gets the item pickup. /// </summary> public Pickup Pickup { get; } + + /// <summary> + /// Gets or sets whether the <see cref="Pickup"/> will be thrown by the <see cref="Player"/>. + /// </summary> + public bool Throw { get; set; } } \ No newline at end of file diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs index 3ae57892..dc5f3e4d 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs @@ -15,11 +15,13 @@ public class PlayerDroppingItemEventArgs : EventArgs, ICancellableEvent, IItemEv /// </summary> /// <param name="player">The player who is dropping the item.</param> /// <param name="item">The item being dropped.</param> - public PlayerDroppingItemEventArgs(ReferenceHub player, ItemBase item) + /// <param name="isThrowing">Whether the item will be thrown.</param> + public PlayerDroppingItemEventArgs(ReferenceHub player, ItemBase item, bool isThrowing) { IsAllowed = true; Player = Player.Get(player); Item = Item.Get(item); + Throw = isThrowing; } /// <summary> @@ -32,6 +34,11 @@ public PlayerDroppingItemEventArgs(ReferenceHub player, ItemBase item) /// </summary> public Item Item { get; } + /// <summary> + /// Gets or sets whether the <see cref="Pickup"/> will be thrown by the <see cref="Player"/>. + /// </summary> + public bool Throw { get; set; } + /// <inheritdoc /> public bool IsAllowed { get; set; } } \ No newline at end of file diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBloodEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBloodEventArgs.cs index 344c74a2..e4385b58 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBloodEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBloodEventArgs.cs @@ -14,11 +14,13 @@ public class PlayerPlacedBloodEventArgs : EventArgs, IPlayerEvent /// Initializes a new instance of the <see cref="PlayerPlacedBloodEventArgs"/> class. /// </summary> /// <param name="player">The player whose blood it is.</param> + /// <param name="attacker">The player that attacked.</param> /// <param name="hitPosition">Position at which blood has been spawned.</param> /// <param name="startRaycast">Position where the blood decal raycast will start for it to be properly attached to surface.</param> - public PlayerPlacedBloodEventArgs(ReferenceHub player, Vector3 hitPosition, Vector3 startRaycast) + public PlayerPlacedBloodEventArgs(ReferenceHub player, ReferenceHub attacker, Vector3 hitPosition, Vector3 startRaycast) { Player = Player.Get(player); + Attacker = Player.Get(attacker); HitPosition = hitPosition; RaycastStart = startRaycast; } @@ -28,6 +30,11 @@ public PlayerPlacedBloodEventArgs(ReferenceHub player, Vector3 hitPosition, Vect /// </summary> public Player Player { get; } + /// <summary> + /// Gets the player that attacked the <see cref="Player"/>. + /// </summary> + public Player Attacker { get; } + /// <summary> /// Gets the position at which blood has been spawned. /// </summary> diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacingBloodEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacingBloodEventArgs.cs index 26bcf50d..cf28fff4 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacingBloodEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacingBloodEventArgs.cs @@ -14,12 +14,14 @@ public class PlayerPlacingBloodEventArgs : EventArgs, IPlayerEvent, ICancellable /// Initializes a new instance of the <see cref="PlayerPlacingBloodEventArgs"/> class. /// </summary> /// <param name="player">The player whose blood it is.</param> + /// <param name="attacker">The player that attacked.</param> /// <param name="hitPosition">Position at which is blood being placed.</param> /// <param name="startRaycast">Position where the blood decal raycast will start for it to be properly attached to surface.</param> - public PlayerPlacingBloodEventArgs(ReferenceHub player, Vector3 hitPosition, Vector3 startRaycast) + public PlayerPlacingBloodEventArgs(ReferenceHub player, ReferenceHub attacker, Vector3 hitPosition, Vector3 startRaycast) { IsAllowed = true; Player = Player.Get(player); + Attacker = Player.Get(attacker); HitPosition = hitPosition; RaycastStart = startRaycast; } @@ -29,6 +31,11 @@ public PlayerPlacingBloodEventArgs(ReferenceHub player, Vector3 hitPosition, Vec /// </summary> public Player Player { get; } + /// <summary> + /// Gets the player that attacked the <see cref="Player"/>. + /// </summary> + public Player Attacker { get; } + /// <summary> /// Gets the position at which is blood being placed. /// </summary> diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockingGeneratorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockingGeneratorEventArgs.cs index 57794b3f..9cb18a10 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockingGeneratorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockingGeneratorEventArgs.cs @@ -15,11 +15,13 @@ public class PlayerUnlockingGeneratorEventArgs : EventArgs, IPlayerEvent, IGener /// </summary> /// <param name="player">The player who is unlocking the generator.</param> /// <param name="generator">The generator that the player is unlocking.</param> - public PlayerUnlockingGeneratorEventArgs(ReferenceHub player, Scp079Generator generator) + /// <param name="canOpen">Whether the generator can be opened.</param> + public PlayerUnlockingGeneratorEventArgs(ReferenceHub player, Scp079Generator generator, bool canOpen) { Player = Player.Get(player); Generator = Generator.Get(generator); IsAllowed = true; + CanOpen = canOpen; } /// <summary> @@ -30,7 +32,14 @@ public PlayerUnlockingGeneratorEventArgs(ReferenceHub player, Scp079Generator ge /// <inheritdoc /> public Generator Generator { get; } - /// <inheritdoc/> + /// <summary> + /// Gets whether the player can open the generator. + /// </summary> + public bool CanOpen { get; set; } + + /// <summary> + /// Gets whether this event is allowed. Not allowing this event will not unlock the generator and no denied animation is played. + /// </summary> public bool IsAllowed { get; set; } } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079PingedEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079PingedEventArgs.cs new file mode 100644 index 00000000..19b49334 --- /dev/null +++ b/LabApi/Events/Arguments/Scp079Events/Scp079PingedEventArgs.cs @@ -0,0 +1,48 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Enums; +using LabApi.Features.Wrappers; +using System; +using UnityEngine; + +namespace LabApi.Events.Arguments.Scp079Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp079Events.Pinged"/> event. +/// </summary> +public class Scp079PingedEventArgs : EventArgs, IPlayerEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp079PingedEventArgs"/> class. + /// </summary> + /// <param name="player">The SCP-079 player instance.</param> + /// <param name="position">The world position of the ping.</param> + /// <param name="normal">Normal vector for the ping.</param> + /// <param name="index">The index of the ping type.</param> + public Scp079PingedEventArgs(ReferenceHub player, Vector3 position, Vector3 normal, byte index) + { + Player = Player.Get(player); + Position = position; + Normal = normal; + PingType = (Scp079PingType)index; + } + + /// <summary> + /// Gets the SCP-079 player instance. + /// </summary> + public Player Player { get; } + + /// <summary> + /// Gets the world ping position. + /// </summary> + public Vector3 Position { get; } + + /// <summary> + /// Gets the ping normal vector. + /// </summary> + public Vector3 Normal { get; } + + /// <summary> + /// Gets the type of the ping used the icon. + /// </summary> + public Scp079PingType PingType { get; } +} diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079PingingEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079PingingEventArgs.cs new file mode 100644 index 00000000..f27502db --- /dev/null +++ b/LabApi/Events/Arguments/Scp079Events/Scp079PingingEventArgs.cs @@ -0,0 +1,52 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Enums; +using LabApi.Features.Wrappers; +using System; +using UnityEngine; + +namespace LabApi.Events.Arguments.Scp079Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp079Events.Pinging"/> event. +/// </summary> +public class Scp079PingingEventArgs : EventArgs, IPlayerEvent, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp079PingingEventArgs"/> class. + /// </summary> + /// <param name="player">The SCP-079 player instance.</param> + /// <param name="position">The world position of the ping.</param> + /// <param name="normal">Normal vector for the ping.</param> + /// <param name="index">The index of the ping type.</param> + public Scp079PingingEventArgs(ReferenceHub player, Vector3 position, Vector3 normal, byte index) + { + Player = Player.Get(player); + Position = position; + Normal = normal; + PingType = (Scp079PingType)index; + IsAllowed = true; + } + + /// <summary> + /// Gets the SCP-079 player instance. + /// </summary> + public Player Player { get; } + + /// <summary> + /// Gets or sets the world ping position. + /// </summary> + public Vector3 Position { get; set; } + + /// <summary> + /// Gets or sets the ping normal vector. + /// </summary> + public Vector3 Normal { get; set; } + + /// <summary> + /// Gets or sets the type of the ping used the icon. + /// </summary> + public Scp079PingType PingType { get; set; } + + /// <inheritdoc/> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/RoundEndingConditionsCheckEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/RoundEndingConditionsCheckEventArgs.cs new file mode 100644 index 00000000..4ddd004b --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/RoundEndingConditionsCheckEventArgs.cs @@ -0,0 +1,23 @@ +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Contains the arguments for the <see cref="Handlers.ServerEvents.RoundEnding"/> event. +/// </summary> +public class RoundEndingConditionsCheckEventArgs : EventArgs +{ + /// <summary> + /// Initializes a new instance of the <see cref="RoundEndingConditionsCheckEventArgs"/> class. + /// </summary> + /// <param name="canEnd">Whether the round end conditions are met</param> + public RoundEndingConditionsCheckEventArgs(bool canEnd) + { + CanEnd = canEnd; + } + + /// <summary> + /// Gets or sets whether the round end conditions are met. + /// </summary> + public bool CanEnd { get; set; } +} diff --git a/LabApi/Events/Handlers/Scp079Events.EventHandlers.cs b/LabApi/Events/Handlers/Scp079Events.EventHandlers.cs index d3820f8e..43b2097e 100644 --- a/LabApi/Events/Handlers/Scp079Events.EventHandlers.cs +++ b/LabApi/Events/Handlers/Scp079Events.EventHandlers.cs @@ -116,4 +116,14 @@ public static partial class Scp079Events /// Gets called when SCP-079 has used a tesla. /// </summary> public static event LabEventHandler<Scp079UsedTeslaEventArgs>? UsedTesla; + + /// <summary> + /// Gets called when SCP-079 is using ping ability. + /// </summary> + public static event LabEventHandler<Scp079PingingEventArgs>? Pinging; + + /// <summary> + /// Gets called when SCP-079 used ping ability. + /// </summary> + public static event LabEventHandler<Scp079PingedEventArgs>? Pinged; } \ No newline at end of file diff --git a/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs b/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs index ef5066ec..7c8ea582 100644 --- a/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs +++ b/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs @@ -17,6 +17,11 @@ public static partial class ServerEvents /// </summary> public static event LabEventHandler? RoundRestarted; + /// <summary> + /// Gets called when round end conditions are checked. + /// </summary> + public static event LabEventHandler<RoundEndingConditionsCheckEventArgs>? RoundEndingConditionsCheck; + /// <summary> /// Gets called when the round is ending. /// </summary> diff --git a/LabApi/Features/Enums/Scp079PingType.cs b/LabApi/Features/Enums/Scp079PingType.cs new file mode 100644 index 00000000..9060ef6d --- /dev/null +++ b/LabApi/Features/Enums/Scp079PingType.cs @@ -0,0 +1,44 @@ +using LabApi.Features.Wrappers; + +namespace LabApi.Features.Enums; + +/// <summary> +/// Enum used for type of the ping. +/// </summary> +public enum Scp079PingType : byte +{ + /// <summary> + /// <see cref="Wrappers.Generator"/> ping. + /// </summary> + Generator = 0, + + /// <summary> + /// <see cref="ExplosiveGrenadeProjectile"/> and <see cref="FlashbangProjectile"/> pings. + /// </summary> + Projectile = 1, + + /// <summary> + /// Micro-HID ping. + /// </summary> + MicroHid = 2, + + /// <summary> + /// <see cref="Player"/> human role ping. + /// </summary> + Human = 3, + + /// <summary> + /// <see cref="Wrappers.Elevator"/> ping. + /// </summary> + Elevator = 4, + + /// <summary> + /// <see cref="Wrappers.Door"/> ping. + /// </summary> + Door = 5, + + /// <summary> + /// Default "i" icon ping. + /// </summary> + Default = 6, +} diff --git a/LabApi/Features/Wrappers/Facility/Doors/Door.cs b/LabApi/Features/Wrappers/Facility/Doors/Door.cs index 14bddcb2..6e2c6ff5 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/Door.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/Door.cs @@ -1,5 +1,4 @@ using Generators; -using Hazards; using Interactables.Interobjects; using Interactables.Interobjects.DoorUtils; using LabApi.Features.Enums; @@ -143,7 +142,7 @@ internal virtual void OnRemove() /// <summary> /// Gets the rooms which have this door. /// </summary> - public RoomIdentifier[] Rooms => Base.Rooms; + public Room[] Rooms => Base.Rooms.Select(Room.Get).ToArray(); /// <summary> /// Gets the zone in which this door is. diff --git a/LabApi/Features/Wrappers/Items/Item.cs b/LabApi/Features/Wrappers/Items/Item.cs index c0c32280..6cb82c72 100644 --- a/LabApi/Features/Wrappers/Items/Item.cs +++ b/LabApi/Features/Wrappers/Items/Item.cs @@ -65,6 +65,8 @@ internal static void Initialize() Register<BodyArmor>(x => new BodyArmorItem(x)); Register<InventorySystem.Items.ThrowableProjectiles.ThrowableItem>(x => new ThrowableItem(x)); Register<InventorySystem.Items.Keycards.KeycardItem>(x => new KeycardItem(x)); + Register<InventorySystem.Items.Keycards.ChaosKeycardItem>(x => new KeycardItem(x)); + Register<InventorySystem.Items.Keycards.SingleUseKeycardItem>(x => new KeycardItem(x)); Register<InventorySystem.Items.MicroHID.MicroHIDItem>(x => new MicroHIDItem(x)); } diff --git a/LabApi/Features/Wrappers/Items/KeycardItem.cs b/LabApi/Features/Wrappers/Items/KeycardItem.cs index cd605b66..f6ba7f73 100644 --- a/LabApi/Features/Wrappers/Items/KeycardItem.cs +++ b/LabApi/Features/Wrappers/Items/KeycardItem.cs @@ -51,6 +51,16 @@ internal override void OnRemove() /// </summary> public new BaseKeycardItem Base { get; } + /// <summary> + /// Gets the <see cref="DoorPermissionFlags"/> of the keycard. + /// </summary> + public DoorPermissionFlags Permissions => Base.GetPermissions(null); + + /// <summary> + /// Gets the <see cref="KeycardLevels"/> of the keycard which represent the tiers shown on the keycard. + /// </summary> + public KeycardLevels Levels => new KeycardLevels(Permissions); + #region Custom Keycards /// <summary> @@ -140,8 +150,8 @@ internal override void OnRemove() if (detailBase is not ICustomizableDetail customizableDetail) continue; - customizableDetail.SetArguments(new ArraySegment<object>(args, index, customizableDetail.CustomizablePropertiesAmount)); - index += customizableDetail.CustomizablePropertiesAmount; + customizableDetail.SetArguments(new ArraySegment<object>(args, index, customizableDetail.CustomizablePropertiesAmount)); + index += customizableDetail.CustomizablePropertiesAmount; } return (KeycardItem?)targetPlayer.AddItem(itemType); diff --git a/LabApi/Features/Wrappers/Players/Player.cs b/LabApi/Features/Wrappers/Players/Player.cs index d6bca3d0..b3592af2 100644 --- a/LabApi/Features/Wrappers/Players/Player.cs +++ b/LabApi/Features/Wrappers/Players/Player.cs @@ -754,6 +754,28 @@ public Vector2 LookRotation set => ReferenceHub.TryOverrideRotation(value); } + /// <summary> + /// Gets or sets player's scale. Player's role must be <see cref="IFpcRole"/> for it to take effect.<br/> + /// Vertical scale is not linear as the model's origin and scaling is done from player's feet. + /// </summary> + public Vector3 Scale + { + get + { + if (ReferenceHub.roleManager.CurrentRole is not IFpcRole fpcRole) + return Vector3.zero; + + return fpcRole.FpcModule.Motor.ScaleController.Scale; + } + set + { + if (ReferenceHub.roleManager.CurrentRole is not IFpcRole fpcRole) + return; + + fpcRole.FpcModule.Motor.ScaleController.Scale = value; + } + } + /// <summary> /// Gets or sets player's remaining stamina (min = 0, max = 1). /// </summary> diff --git a/LabApi/LabApi.csproj b/LabApi/LabApi.csproj index d5c4a3b7..0a4ab084 100644 --- a/LabApi/LabApi.csproj +++ b/LabApi/LabApi.csproj @@ -6,7 +6,7 @@ <PlatformTarget>x64</PlatformTarget> <LangVersion>12.0</LangVersion> - <Version>1.0.2</Version> + <Version>1.1.0</Version> <AssemblyName>LabApi</AssemblyName> <PackageId>Northwood.LabAPI</PackageId> From 20b08c537b7e636a7e6d46b5ad638f96573d5ef2 Mon Sep 17 00:00:00 2001 From: Lizabeth Gock <liz@blanky.dev> Date: Fri, 27 Jun 2025 06:52:52 -0500 Subject: [PATCH 030/215] fix: DropAllAmmo would modify the dictionary it was iterating over (#200) * fix: DropAllAmmo would modify the dictionary it was iterating over (cherry picked from commit 1fc906da45fdba1281db28448f264062688482eb) * Inline --------- Co-authored-by: Jesus QC <69375249+Jesus-QC@users.noreply.github.com> --- LabApi/Features/Wrappers/Players/Player.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/LabApi/Features/Wrappers/Players/Player.cs b/LabApi/Features/Wrappers/Players/Player.cs index b9d3bc7e..59ea8fc1 100644 --- a/LabApi/Features/Wrappers/Players/Player.cs +++ b/LabApi/Features/Wrappers/Players/Player.cs @@ -1284,7 +1284,8 @@ public List<Pickup> DropAllItems() public List<AmmoPickup> DropAllAmmo() { List<AmmoPickup> ammo = ListPool<AmmoPickup>.Shared.Rent(); - foreach (KeyValuePair<ItemType, ushort> pair in Ammo) + + foreach (KeyValuePair<ItemType, ushort> pair in Ammo.ToDictionary(e => e.Key, e => e.Value)) ammo.AddRange(DropAmmo(pair.Key, pair.Value)); return ammo; From 03d9310835dd2b1e4efa1d2d0147b6523d463759 Mon Sep 17 00:00:00 2001 From: Xname <66174882+Xname7@users.noreply.github.com> Date: Fri, 27 Jun 2025 13:55:34 +0200 Subject: [PATCH 031/215] Add LifeId property to Player class (#79) --- LabApi/Features/Wrappers/Players/Player.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/LabApi/Features/Wrappers/Players/Player.cs b/LabApi/Features/Wrappers/Players/Player.cs index 59ea8fc1..1d58a933 100644 --- a/LabApi/Features/Wrappers/Players/Player.cs +++ b/LabApi/Features/Wrappers/Players/Player.cs @@ -227,6 +227,11 @@ public RoleTypeId Role /// </summary> public PlayerRoleBase RoleBase => ReferenceHub.roleManager.CurrentRole; + /// <summary> + /// Get's the player's current role unique identifier. + /// </summary> + public int LifeId => RoleBase.UniqueLifeIdentifier; + /// <summary> /// Gets the Player's Nickname. /// </summary> From 70c25aad88c6373a8d6cf61bbedc2829102dd874 Mon Sep 17 00:00:00 2001 From: jesusqc <contact@jesusqc.es> Date: Fri, 27 Jun 2025 14:10:27 +0200 Subject: [PATCH 032/215] version bump --- LabApi/LabApi.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LabApi/LabApi.csproj b/LabApi/LabApi.csproj index 0a4ab084..deb9995d 100644 --- a/LabApi/LabApi.csproj +++ b/LabApi/LabApi.csproj @@ -6,7 +6,7 @@ <PlatformTarget>x64</PlatformTarget> <LangVersion>12.0</LangVersion> - <Version>1.1.0</Version> + <Version>1.1.1</Version> <AssemblyName>LabApi</AssemblyName> <PackageId>Northwood.LabAPI</PackageId> From 22559d0ba4d58a88fcf64fa1bddf4a903a35ce9b Mon Sep 17 00:00:00 2001 From: Romir Gade <romirgade@gmail.com> Date: Fri, 27 Jun 2025 08:20:15 -0400 Subject: [PATCH 033/215] Make CASSIE SCP termination event include damage handler. (#114) * make cassie SCP termination event include damage handler. * Update CassieQueuedScpTerminationEventArgs.cs * Update CassieQueuingScpTerminationEventArgs.cs * Update CassieQueuedScpTerminationEventArgs.cs * Update CassieQueuingScpTerminationEventArgs.cs --------- Co-authored-by: brayden-dowson <88667957+brayden-dowson@users.noreply.github.com> --- .../CassieQueuedScpTerminationEventArgs.cs | 10 +++++++++- .../CassieQueuingScpTerminationEventArgs.cs | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/LabApi/Events/Arguments/ServerEvents/CassieQueuedScpTerminationEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/CassieQueuedScpTerminationEventArgs.cs index 43d888b2..e0c5011e 100644 --- a/LabApi/Events/Arguments/ServerEvents/CassieQueuedScpTerminationEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/CassieQueuedScpTerminationEventArgs.cs @@ -1,5 +1,6 @@ using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using PlayerStatsSystem; using Subtitles; using System; @@ -16,11 +17,13 @@ public class CassieQueuedScpTerminationEventArgs : EventArgs, IPlayerEvent /// <param name="player">The SCP player the C.A.S.S.I.E termination announcement is for.</param> /// <param name="announcement">The message C.A.S.S.I.E is supposed to say.</param> /// <param name="subtitles">The subtitle part array of the message.</param> - public CassieQueuedScpTerminationEventArgs(ReferenceHub player, string announcement, SubtitlePart[] subtitles) + /// <param name="damageHandler">The damage handler that caused the termination of the SCP.</param> + public CassieQueuedScpTerminationEventArgs(ReferenceHub player, string announcement, SubtitlePart[] subtitles, DamageHandlerBase damageHandler) { Player = Player.Get(player); Announcement = announcement; SubtitleParts = subtitles; + DamageHandler = damageHandler; } /// <summary> @@ -37,4 +40,9 @@ public CassieQueuedScpTerminationEventArgs(ReferenceHub player, string announcem /// Gets or sets the subtitle parts of the message. /// </summary> public SubtitlePart[] SubtitleParts { get; } + + /// <summary> + /// The Damage Handler responsible for the SCP Termination. + /// </summary> + public DamageHandlerBase DamageHandler { get; } } diff --git a/LabApi/Events/Arguments/ServerEvents/CassieQueuingScpTerminationEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/CassieQueuingScpTerminationEventArgs.cs index f94c3e76..88afe799 100644 --- a/LabApi/Events/Arguments/ServerEvents/CassieQueuingScpTerminationEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/CassieQueuingScpTerminationEventArgs.cs @@ -1,5 +1,6 @@ using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using PlayerStatsSystem; using Subtitles; using System; @@ -16,12 +17,14 @@ public class CassieQueuingScpTerminationEventArgs : EventArgs, IPlayerEvent, ICa /// <param name="player">The SCP player the C.A.S.S.I.E termination announcement is for.</param> /// <param name="announcement">The message C.A.S.S.I.E is supposed to say.</param> /// <param name="subtitles">The subtitle part array of the message.</param> - public CassieQueuingScpTerminationEventArgs(ReferenceHub player, string announcement, SubtitlePart[] subtitles) + /// <param name="damageHandler">The damage handler that caused the termination of the SCP.</param> + public CassieQueuingScpTerminationEventArgs(ReferenceHub player, string announcement, SubtitlePart[] subtitles, DamageHandlerBase damageHandler) { IsAllowed = true; Player = Player.Get(player); Announcement = announcement; SubtitleParts = [.. subtitles]; + DamageHandler = damageHandler; } /// <summary> @@ -41,4 +44,9 @@ public CassieQueuingScpTerminationEventArgs(ReferenceHub player, string announce /// <inheritdoc /> public bool IsAllowed { get; set; } + + /// <summary> + /// The Damage Handler responsible for the SCP Termination. + /// </summary> + public DamageHandlerBase DamageHandler { get; } } From d390d544535d47452e820ef9c113245a8068db42 Mon Sep 17 00:00:00 2001 From: David <david.sebesta@post.cz> Date: Fri, 27 Jun 2025 14:22:26 +0200 Subject: [PATCH 034/215] Objective Events (#260) * Added objective completing/completed events * Fix docs * Doc fix 2 * And final docs * Added per-objective event * Events handler * Specific events args fix --- .../LogAll/LogPlugin/MyCustomEventsHandler.cs | 71 +++++++++++++++-- .../Arguments/Interfaces/IObjectiveEvent.cs | 40 ++++++++++ .../EnemyKilledObjectiveEventArgs.cs | 29 +++++++ .../EnemyKillingObjectiveEventArgs.cs | 28 +++++++ .../EscapedObjectiveEventArgs.cs | 28 +++++++ .../EscapingObjectiveEventArgs.cs | 27 +++++++ .../GeneratorActivatedObjectiveEventArgs.cs | 30 ++++++++ .../GeneratorActivatingObjectiveEventArgs.cs | 29 +++++++ .../ObjectiveCompletedBaseEventArgs.cs | 44 +++++++++++ .../ObjectiveCompletingBaseEventArgs.cs | 61 +++++++++++++++ .../ScpDamagedObjectiveEventArgs.cs | 29 +++++++ .../ScpDamagingObjectiveEventArgs.cs | 28 +++++++ .../ScpItemPickedObjectiveEventArgs.cs | 30 ++++++++ .../ScpItemPickingObjectiveEventArgs.cs | 29 +++++++ .../Handlers/ObjectiveEvents.EventHandlers.cs | 77 +++++++++++++++++++ 15 files changed, 575 insertions(+), 5 deletions(-) create mode 100644 LabApi/Events/Arguments/Interfaces/IObjectiveEvent.cs create mode 100644 LabApi/Events/Arguments/ObjectiveEvents/EnemyKilledObjectiveEventArgs.cs create mode 100644 LabApi/Events/Arguments/ObjectiveEvents/EnemyKillingObjectiveEventArgs.cs create mode 100644 LabApi/Events/Arguments/ObjectiveEvents/EscapedObjectiveEventArgs.cs create mode 100644 LabApi/Events/Arguments/ObjectiveEvents/EscapingObjectiveEventArgs.cs create mode 100644 LabApi/Events/Arguments/ObjectiveEvents/GeneratorActivatedObjectiveEventArgs.cs create mode 100644 LabApi/Events/Arguments/ObjectiveEvents/GeneratorActivatingObjectiveEventArgs.cs create mode 100644 LabApi/Events/Arguments/ObjectiveEvents/ObjectiveCompletedBaseEventArgs.cs create mode 100644 LabApi/Events/Arguments/ObjectiveEvents/ObjectiveCompletingBaseEventArgs.cs create mode 100644 LabApi/Events/Arguments/ObjectiveEvents/ScpDamagedObjectiveEventArgs.cs create mode 100644 LabApi/Events/Arguments/ObjectiveEvents/ScpDamagingObjectiveEventArgs.cs create mode 100644 LabApi/Events/Arguments/ObjectiveEvents/ScpItemPickedObjectiveEventArgs.cs create mode 100644 LabApi/Events/Arguments/ObjectiveEvents/ScpItemPickingObjectiveEventArgs.cs create mode 100644 LabApi/Events/Handlers/ObjectiveEvents.EventHandlers.cs diff --git a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs index 69fac15b..25d0f741 100644 --- a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs +++ b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs @@ -1,4 +1,5 @@ using System.Linq; +using LabApi.Events.Arguments.ObjectiveEvents; using LabApi.Events.Arguments.PlayerEvents; using LabApi.Events.Arguments.Scp0492Events; using LabApi.Events.Arguments.Scp049Events; @@ -26,7 +27,7 @@ public override void OnPlayerActivatedGenerator(PlayerActivatedGeneratorEventArg { Logger.Info($"{nameof(OnPlayerActivatedGenerator)} triggered by {ev.Player.UserId}"); } - + public override void OnPlayerUnlockingGenerator(PlayerUnlockingGeneratorEventArgs ev) { Logger.Info($"{nameof(OnPlayerUnlockingGenerator)} triggered by {ev.Player.UserId}"); @@ -36,7 +37,7 @@ public override void OnPlayerUnlockedGenerator(PlayerUnlockedGeneratorEventArgs { Logger.Info($"{nameof(OnPlayerUnlockedGenerator)} triggered by {ev.Player.UserId}"); } - + public override void OnPlayerUnlockingWarheadButton(PlayerUnlockingWarheadButtonEventArgs ev) { Logger.Info($"{nameof(OnPlayerUnlockingWarheadButton)} triggered by {ev.Player.UserId}"); @@ -1311,7 +1312,7 @@ public override void OnServerCassieQueuingScpTermination(CassieQueuingScpTermina { Logger.Info($"{nameof(OnServerCassieQueuingScpTermination)} triggered"); } - + public override void OnServerCassieQueuedScpTermination(CassieQueuedScpTerminationEventArgs ev) { Logger.Info($"{nameof(OnServerCassieQueuedScpTermination)} triggered"); @@ -1376,8 +1377,68 @@ public override void OnWarheadDetonated(WarheadDetonatedEventArgs ev) { Logger.Info($"{nameof(OnWarheadDetonated)} triggered by {ev.Player.UserId}"); } - - + + public override void OnObjectiveCompleting(ObjectiveCompletingBaseEventArgs ev) + { + Logger.Info($"{nameof(OnObjectiveCompleting)} triggered by {ev.Player.UserId}"); + } + + public override void OnObjectiveCompleted(ObjectiveCompletedBaseEventArgs ev) + { + Logger.Info($"{nameof(OnObjectiveCompleted)} triggered by {ev.Player.UserId}"); + } + + public override void OnObjectiveActivatedGeneratorCompleted(GeneratorActivatedObjectiveEventArgs ev) + { + Logger.Info($"{nameof(OnObjectiveActivatedGeneratorCompleted)} triggered by {ev.Player.UserId}"); + } + + public override void OnObjectiveActivatingGeneratorCompleting(GeneratorActivatingObjectiveEventArgs ev) + { + Logger.Info($"{nameof(OnObjectiveActivatingGeneratorCompleting)} triggered by {ev.Player.UserId}"); + } + + public override void OnObjectiveDamagedScpCompleted(ScpDamagedObjectiveEventArgs ev) + { + Logger.Info($"{nameof(OnObjectiveDamagedScpCompleted)} triggered by {ev.Player.UserId}"); + } + + public override void OnObjectiveDamagingScpCompleting(ScpDamagingObjectiveEventArgs ev) + { + Logger.Info($"{nameof(OnObjectiveDamagingScpCompleting)} triggered by {ev.Player.UserId}"); + } + + public override void OnObjectiveEscapingCompleting(EscapingObjectiveEventArgs ev) + { + Logger.Info($"{nameof(OnObjectiveEscapingCompleting)} triggered by {ev.Player.UserId}"); + } + + public override void OnObjectiveEscapedCompleted(EscapedObjectiveEventArgs ev) + { + Logger.Info($"{nameof(OnObjectiveEscapedCompleted)} triggered by {ev.Player.UserId}"); + } + + public override void OnObjectiveKillingEnemyCompleting(EnemyKillingObjectiveEventArgs ev) + { + Logger.Info($"{nameof(OnObjectiveKillingEnemyCompleting)} triggered by {ev.Player.UserId}"); + } + + public override void OnObjectiveKilledEnemyCompleted(EnemyKilledObjectiveEventArgs ev) + { + Logger.Info($"{nameof(OnObjectiveKilledEnemyCompleted)} triggered by {ev.Player.UserId}"); + } + + public override void OnObjectivePickingScpItemCompleting(ScpItemPickingObjectiveEventArgs ev) + { + Logger.Info($"{nameof(OnObjectivePickingScpItemCompleting)} triggered by {ev.Player.UserId}"); + } + + public override void OnObjectivePickedScpItemCompleted(ScpItemPickedObjectiveEventArgs ev) + { + Logger.Info($"{nameof(OnObjectivePickedScpItemCompleted)} triggered by {ev.Player.UserId}"); + } + + #region Excluded Events // The following events spam the console and are therefore excluded from this example: diff --git a/LabApi/Events/Arguments/Interfaces/IObjectiveEvent.cs b/LabApi/Events/Arguments/Interfaces/IObjectiveEvent.cs new file mode 100644 index 00000000..b408ce12 --- /dev/null +++ b/LabApi/Events/Arguments/Interfaces/IObjectiveEvent.cs @@ -0,0 +1,40 @@ +using LabApi.Features.Wrappers; +using PlayerRoles; +using Respawning.Objectives; + +namespace LabApi.Events.Arguments.Interfaces; + +/// <summary> +/// Represents an event that involves <see cref="FactionObjectiveBase"/>. +/// </summary> +public interface IObjectiveEvent +{ + /// <summary> + /// Gets the player who triggered the objective completion. + /// </summary> + public Player Player { get; } + + /// <summary> + /// Gets the <see cref="PlayerRoles.Faction"/> which will receive the <see cref="InfluenceToGrant"/> and <see cref="TimeToGrant"/> rewards. + /// </summary> + public Faction Faction { get; } + + /// <summary> + /// Gets the amount of influence to grant to the <see cref="Faction"/>. + /// </summary> + public float InfluenceToGrant { get; } + + /// <summary> + /// Gets the amount of time to be reduced from the <see cref="Faction"/>'s timer. + /// </summary> + /// <remarks> + /// Negative values reduce the timer, positive extends it. + /// </remarks> + public float TimeToGrant { get; } + + /// <summary> + /// Gets whether the objective completion should be sent to players and visible on their screen. + /// </summary> + public bool SendToPlayers { get; } + +} diff --git a/LabApi/Events/Arguments/ObjectiveEvents/EnemyKilledObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/EnemyKilledObjectiveEventArgs.cs new file mode 100644 index 00000000..96621342 --- /dev/null +++ b/LabApi/Events/Arguments/ObjectiveEvents/EnemyKilledObjectiveEventArgs.cs @@ -0,0 +1,29 @@ +using LabApi.Features.Wrappers; +using PlayerRoles; + +namespace LabApi.Events.Arguments.ObjectiveEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ObjectiveEvents.KilledEnemyCompleted"/> event. +/// </summary> +public class EnemyKilledObjectiveEventArgs : ObjectiveCompletedBaseEventArgs +{ + /// <summary> + /// Initializes a new instance of the <see cref="EnemyKilledObjectiveEventArgs"/> class. + /// </summary> + /// <param name="hub">The player hub who triggered the objective.</param> + /// <param name="faction">The Faction to grant the influence to.</param> + /// <param name="influenceToGrant">The influence points to grant to the <paramref name="faction"/>.</param> + /// <param name="timeToGrant">The time to reduce from the <paramref name="faction"/>.</param> + /// <param name="sendToPlayers">Whether the objective completion has been sent to players.</param> + /// <param name="targetHub">The player that has been killed.</param> + public EnemyKilledObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, bool sendToPlayers, ReferenceHub targetHub) : base(hub, faction, influenceToGrant, timeToGrant, sendToPlayers) + { + Target = Player.Get(targetHub); + } + + /// <summary> + /// Gets the player that has been killed. + /// </summary> + public Player Target { get; } +} diff --git a/LabApi/Events/Arguments/ObjectiveEvents/EnemyKillingObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/EnemyKillingObjectiveEventArgs.cs new file mode 100644 index 00000000..57808169 --- /dev/null +++ b/LabApi/Events/Arguments/ObjectiveEvents/EnemyKillingObjectiveEventArgs.cs @@ -0,0 +1,28 @@ +using LabApi.Features.Wrappers; +using PlayerRoles; + +namespace LabApi.Events.Arguments.ObjectiveEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ObjectiveEvents.KillingEnemyCompleting"/> event. +/// </summary> +public class EnemyKillingObjectiveEventArgs : ObjectiveCompletingBaseEventArgs +{ + /// <summary> + /// Initializes a new instance of the <see cref="EnemyKillingObjectiveEventArgs"/> class. + /// </summary> + /// <param name="hub">The player hub who triggered the objective.</param> + /// <param name="faction">The Faction to grant the influence to.</param> + /// <param name="influenceToGrant">The influence points to grant to the <paramref name="faction"/>.</param> + /// <param name="timeToGrant">The time to reduce from the <paramref name="faction"/>.</param> + /// <param name="targetHub">The player that has been killed.</param> + public EnemyKillingObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, ReferenceHub targetHub) : base(hub, faction, influenceToGrant, timeToGrant) + { + Target = Player.Get(targetHub); + } + + /// <summary> + /// Gets the player that has been killed. + /// </summary> + public Player Target { get; } +} diff --git a/LabApi/Events/Arguments/ObjectiveEvents/EscapedObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/EscapedObjectiveEventArgs.cs new file mode 100644 index 00000000..8a29f82a --- /dev/null +++ b/LabApi/Events/Arguments/ObjectiveEvents/EscapedObjectiveEventArgs.cs @@ -0,0 +1,28 @@ +using PlayerRoles; + +namespace LabApi.Events.Arguments.ObjectiveEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ObjectiveEvents.EscapedCompleted"/> event. +/// </summary> +public class EscapedObjectiveEventArgs : ObjectiveCompletedBaseEventArgs +{ + /// <summary> + /// Initializes a new instance of the <see cref="EscapedObjectiveEventArgs"/> class. + /// </summary> + /// <param name="hub">The player hub who triggered the objective.</param> + /// <param name="faction">The Faction to grant the influence to.</param> + /// <param name="influenceToGrant">The influence points to grant to the <paramref name="faction"/>.</param> + /// <param name="timeToGrant">The time to reduce from the <paramref name="faction"/>.</param> + /// <param name="newRole">The new role the player gets after escaping.</param> + /// <param name="sendToPlayers">Whether the objective completion has been sent to players.</param> + public EscapedObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, bool sendToPlayers, RoleTypeId newRole) : base(hub, faction, influenceToGrant, timeToGrant, sendToPlayers) + { + NewRole = newRole; + } + + /// <summary> + /// Gets the new role the player is getting. + /// </summary> + public RoleTypeId NewRole { get; } +} diff --git a/LabApi/Events/Arguments/ObjectiveEvents/EscapingObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/EscapingObjectiveEventArgs.cs new file mode 100644 index 00000000..db85602a --- /dev/null +++ b/LabApi/Events/Arguments/ObjectiveEvents/EscapingObjectiveEventArgs.cs @@ -0,0 +1,27 @@ +using PlayerRoles; + +namespace LabApi.Events.Arguments.ObjectiveEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ObjectiveEvents.EscapingCompleting"/> event. +/// </summary> +public class EscapingObjectiveEventArgs : ObjectiveCompletingBaseEventArgs +{ + /// <summary> + /// Initializes a new instance of the <see cref="EscapingObjectiveEventArgs"/> class. + /// </summary> + /// <param name="hub">The player hub who triggered the objective.</param> + /// <param name="faction">The Faction to grant the influence to.</param> + /// <param name="influenceToGrant">The influence points to grant to the <paramref name="faction"/>.</param> + /// <param name="timeToGrant">The time to reduce from the <paramref name="faction"/>.</param> + /// <param name="newRole">The new role the player gets after escaping.</param> + public EscapingObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, RoleTypeId newRole) : base(hub, faction, influenceToGrant, timeToGrant) + { + NewRole = newRole; + } + + /// <summary> + /// Gets the new role the player is getting. + /// </summary> + public RoleTypeId NewRole { get; } +} diff --git a/LabApi/Events/Arguments/ObjectiveEvents/GeneratorActivatedObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/GeneratorActivatedObjectiveEventArgs.cs new file mode 100644 index 00000000..e215245d --- /dev/null +++ b/LabApi/Events/Arguments/ObjectiveEvents/GeneratorActivatedObjectiveEventArgs.cs @@ -0,0 +1,30 @@ +using LabApi.Features.Wrappers; +using MapGeneration.Distributors; +using PlayerRoles; + +namespace LabApi.Events.Arguments.ObjectiveEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ObjectiveEvents.ActivatedGeneratorCompleted"/> event. +/// </summary> +public class GeneratorActivatedObjectiveEventArgs : ObjectiveCompletedBaseEventArgs +{ + /// <summary> + /// Initializes a new instance of the <see cref="GeneratorActivatedObjectiveEventArgs"/> class. + /// </summary> + /// <param name="hub">The player hub who triggered the objective.</param> + /// <param name="faction">The Faction to grant the influence to.</param> + /// <param name="influenceToGrant">The influence points to grant to the <paramref name="faction"/>.</param> + /// <param name="timeToGrant">The time to reduce from the <paramref name="faction"/>.</param> + /// <param name="sendToPlayers">Whether the objective completion has been sent to players.</param> + /// <param name="generator">The generator that has been activated.</param> + public GeneratorActivatedObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, bool sendToPlayers, Scp079Generator generator) : base(hub, faction, influenceToGrant, timeToGrant, sendToPlayers) + { + Generator = Generator.Get(generator); + } + + /// <summary> + /// Gets the generator that has been activated. + /// </summary> + public Generator Generator { get; } +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/ObjectiveEvents/GeneratorActivatingObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/GeneratorActivatingObjectiveEventArgs.cs new file mode 100644 index 00000000..d1d21687 --- /dev/null +++ b/LabApi/Events/Arguments/ObjectiveEvents/GeneratorActivatingObjectiveEventArgs.cs @@ -0,0 +1,29 @@ +using LabApi.Features.Wrappers; +using MapGeneration.Distributors; +using PlayerRoles; + +namespace LabApi.Events.Arguments.ObjectiveEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ObjectiveEvents.ActivatingGeneratorCompleting"/> event. +/// </summary> +public class GeneratorActivatingObjectiveEventArgs : ObjectiveCompletingBaseEventArgs +{ + /// <summary> + /// Initializes a new instance of the <see cref="GeneratorActivatingObjectiveEventArgs"/> class. + /// </summary> + /// <param name="hub">The player hub who triggered the objective.</param> + /// <param name="faction">The Faction to grant the influence to.</param> + /// <param name="influenceToGrant">The influence points to grant to the <paramref name="faction"/>.</param> + /// <param name="timeToGrant">The time to reduce from the <paramref name="faction"/>.</param> + /// <param name="generator">The generator that has been activated.</param> + public GeneratorActivatingObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, Scp079Generator generator) : base(hub, faction, influenceToGrant, timeToGrant) + { + Generator = Generator.Get(generator); + } + + /// <summary> + /// Gets the generator that has been activated. + /// </summary> + public Generator Generator { get; } +} diff --git a/LabApi/Events/Arguments/ObjectiveEvents/ObjectiveCompletedBaseEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/ObjectiveCompletedBaseEventArgs.cs new file mode 100644 index 00000000..76113da9 --- /dev/null +++ b/LabApi/Events/Arguments/ObjectiveEvents/ObjectiveCompletedBaseEventArgs.cs @@ -0,0 +1,44 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using PlayerRoles; +using System; + +namespace LabApi.Events.Arguments.ObjectiveEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ObjectiveEvents.Completed"/> event. +/// </summary> +public class ObjectiveCompletedBaseEventArgs : EventArgs, IPlayerEvent, IObjectiveEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="ObjectiveCompletingBaseEventArgs"/> class. + /// </summary> + /// <param name="hub">The player hub who triggered the objective.</param> + /// <param name="faction">The Faction to grant the influence to.</param> + /// <param name="influenceToGrant">The influence points granted to the <paramref name="faction"/>.</param> + /// <param name="timeToGrant">The time reduced from the <paramref name="faction"/>.</param> + /// <param name="sendToPlayers">Whether the objective completion has been sent to players.</param> + public ObjectiveCompletedBaseEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, bool sendToPlayers) + { + Player = Player.Get(hub); + Faction = faction; + InfluenceToGrant = influenceToGrant; + TimeToGrant = timeToGrant; + SendToPlayers = sendToPlayers; + } + + /// <inheritdoc/> + public Player Player { get; } + + /// <inheritdoc/> + public Faction Faction { get; } + + /// <inheritdoc/> + public float InfluenceToGrant { get; } + + /// <inheritdoc/> + public float TimeToGrant { get; } + + /// <inheritdoc/> + public bool SendToPlayers { get; } +} diff --git a/LabApi/Events/Arguments/ObjectiveEvents/ObjectiveCompletingBaseEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/ObjectiveCompletingBaseEventArgs.cs new file mode 100644 index 00000000..21194cd5 --- /dev/null +++ b/LabApi/Events/Arguments/ObjectiveEvents/ObjectiveCompletingBaseEventArgs.cs @@ -0,0 +1,61 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using PlayerRoles; +using System; + +namespace LabApi.Events.Arguments.ObjectiveEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ObjectiveEvents.Completing"/> event. +/// </summary> +public abstract class ObjectiveCompletingBaseEventArgs : EventArgs, ICancellableEvent, IPlayerEvent, IObjectiveEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="ObjectiveCompletingBaseEventArgs"/> class. + /// </summary> + /// <param name="hub">The player hub who triggered the objective.</param> + /// <param name="faction">The Faction to grant the influence to.</param> + /// <param name="influenceToGrant">The influence points to grant to the <paramref name="faction"/>.</param> + /// <param name="timeToGrant">The time to reduce from the <paramref name="faction"/>.</param> + public ObjectiveCompletingBaseEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant) + { + Player = Player.Get(hub); + Faction = faction; + InfluenceToGrant = influenceToGrant; + TimeToGrant = timeToGrant; + SendToPlayers = true; + + IsAllowed = true; + } + + /// <summary> + /// Gets or sets the player who triggered the objective completion. + /// </summary> + public Player Player { get; } + + /// <summary> + /// Gets or sets the <see cref="PlayerRoles.Faction"/> which receives the <see cref="InfluenceToGrant"/> and <see cref="TimeToGrant"/> rewards. + /// </summary> + public Faction Faction { get; } + + /// <summary> + /// Gets or sets the amount of influence granted to the <see cref="Faction"/>. + /// </summary> + public float InfluenceToGrant { get; } + + /// <summary> + /// Gets or sets the amount of time reduced from the <see cref="Faction"/>'s timer. + /// </summary> + /// <remarks> + /// Negative values reduce the timer, positive extends it. + /// </remarks> + public float TimeToGrant { get; } + + /// <summary> + /// Gets or sets whether the objective completion has been sent to players and is visible on their screen. + /// </summary> + public bool SendToPlayers { get; } + + /// <inheritdoc/> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/ObjectiveEvents/ScpDamagedObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/ScpDamagedObjectiveEventArgs.cs new file mode 100644 index 00000000..c1bb7b3d --- /dev/null +++ b/LabApi/Events/Arguments/ObjectiveEvents/ScpDamagedObjectiveEventArgs.cs @@ -0,0 +1,29 @@ +using LabApi.Features.Wrappers; +using PlayerRoles; + +namespace LabApi.Events.Arguments.ObjectiveEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ObjectiveEvents.DamagedScpCompleted"/> event. +/// </summary> +public class ScpDamagedObjectiveEventArgs : ObjectiveCompletedBaseEventArgs +{ + /// <summary> + /// Initializes a new instance of the <see cref="ScpDamagedObjectiveEventArgs"/> class. + /// </summary> + /// <param name="hub">The player hub who triggered the objective.</param> + /// <param name="Faction">The Faction to grant the influence to.</param> + /// <param name="influenceToGrant">The influence points to grant to the <paramref name="Faction"/>.</param> + /// <param name="timeToGrant">The time to reduce from the <paramref name="Faction"/>.</param> + /// <param name="sendToPlayers">Whether the objective completion has been sent to players.</param> + /// <param name="targetHub">The hub of the player SCP that has been damaged.</param> + public ScpDamagedObjectiveEventArgs(ReferenceHub hub, Faction Faction, float influenceToGrant, float timeToGrant, bool sendToPlayers, ReferenceHub targetHub) : base(hub, Faction, influenceToGrant, timeToGrant, sendToPlayers) + { + Target = Player.Get(targetHub); + } + + /// <summary> + /// Gets the SCP player that has been damaged. + /// </summary> + public Player Target { get; } +} diff --git a/LabApi/Events/Arguments/ObjectiveEvents/ScpDamagingObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/ScpDamagingObjectiveEventArgs.cs new file mode 100644 index 00000000..f04e0ea9 --- /dev/null +++ b/LabApi/Events/Arguments/ObjectiveEvents/ScpDamagingObjectiveEventArgs.cs @@ -0,0 +1,28 @@ +using LabApi.Features.Wrappers; +using PlayerRoles; + +namespace LabApi.Events.Arguments.ObjectiveEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ObjectiveEvents.DamagingScpCompleting"/> event. +/// </summary> +public class ScpDamagingObjectiveEventArgs : ObjectiveCompletingBaseEventArgs +{ + /// <summary> + /// Initializes a new instance of the <see cref="ScpDamagingObjectiveEventArgs"/> class. + /// </summary> + /// <param name="hub">The player hub who triggered the objective.</param> + /// <param name="faction">The Faction to grant the influence to.</param> + /// <param name="influenceToGrant">The influence points to grant to the <paramref name="faction"/>.</param> + /// <param name="timeToGrant">The time to reduce from the <paramref name="faction"/>.</param> + /// <param name="targetHub">The hub of the player SCP that has been damaged.</param> + public ScpDamagingObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, ReferenceHub targetHub) : base(hub, faction, influenceToGrant, timeToGrant) + { + Target = Player.Get(targetHub); + } + + /// <summary> + /// Gets the SCP player that has been damaged. + /// </summary> + public Player Target { get; } +} diff --git a/LabApi/Events/Arguments/ObjectiveEvents/ScpItemPickedObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/ScpItemPickedObjectiveEventArgs.cs new file mode 100644 index 00000000..0bf0d4a2 --- /dev/null +++ b/LabApi/Events/Arguments/ObjectiveEvents/ScpItemPickedObjectiveEventArgs.cs @@ -0,0 +1,30 @@ +using InventorySystem.Items; +using LabApi.Features.Wrappers; +using PlayerRoles; + +namespace LabApi.Events.Arguments.ObjectiveEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ObjectiveEvents.PickedScpItemCompleted"/> event. +/// </summary> +public class ScpItemPickedObjectiveEventArgs : ObjectiveCompletedBaseEventArgs +{ + /// <summary> + /// Initializes a new instance of the <see cref="ScpItemPickedObjectiveEventArgs"/> class. + /// </summary> + /// <param name="hub">The player hub who triggered the objective.</param> + /// <param name="faction">The Faction to grant the influence to.</param> + /// <param name="influenceToGrant">The influence points to grant to the <paramref name="faction"/>.</param> + /// <param name="timeToGrant">The time to reduce from the <paramref name="faction"/>.</param> + /// <param name="sendToPlayers">Whether the objective completion has been sent to players.</param> + /// <param name="item">The item that has been picked up.</param> + public ScpItemPickedObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, bool sendToPlayers, ItemBase item) : base(hub, faction, influenceToGrant, timeToGrant, sendToPlayers) + { + Item = Item.Get(item); + } + + /// <summary> + /// Gets the item that has been picked up. + /// </summary> + public Item Item { get; } +} diff --git a/LabApi/Events/Arguments/ObjectiveEvents/ScpItemPickingObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/ScpItemPickingObjectiveEventArgs.cs new file mode 100644 index 00000000..f2c1ba47 --- /dev/null +++ b/LabApi/Events/Arguments/ObjectiveEvents/ScpItemPickingObjectiveEventArgs.cs @@ -0,0 +1,29 @@ +using InventorySystem.Items; +using LabApi.Features.Wrappers; +using PlayerRoles; + +namespace LabApi.Events.Arguments.ObjectiveEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ObjectiveEvents.PickingScpItemCompleting"/> event. +/// </summary> +public class ScpItemPickingObjectiveEventArgs : ObjectiveCompletingBaseEventArgs +{ + /// <summary> + /// Initializes a new instance of the <see cref="ObjectiveCompletingBaseEventArgs"/> class. + /// </summary> + /// <param name="hub">The player hub who triggered the objective.</param> + /// <param name="faction">The Faction to grant the influence to.</param> + /// <param name="influenceToGrant">The influence points to grant to the <paramref name="faction"/>.</param> + /// <param name="timeToGrant">The time to reduce from the <paramref name="faction"/>.</param> + /// <param name="item">The item that has been picked up.</param> + public ScpItemPickingObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, ItemBase item) : base(hub, faction, influenceToGrant, timeToGrant) + { + Item = Item.Get(item); + } + + /// <summary> + /// Gets the item that has been picked up. + /// </summary> + public Item Item { get; } +} diff --git a/LabApi/Events/Handlers/ObjectiveEvents.EventHandlers.cs b/LabApi/Events/Handlers/ObjectiveEvents.EventHandlers.cs new file mode 100644 index 00000000..a1404722 --- /dev/null +++ b/LabApi/Events/Handlers/ObjectiveEvents.EventHandlers.cs @@ -0,0 +1,77 @@ +using LabApi.Events.Arguments.ObjectiveEvents; + +namespace LabApi.Events.Handlers; + +/// <summary> +/// Handles all events related to objectives. +/// </summary> +public static partial class ObjectiveEvents +{ + /// <summary> + /// Gets called when <b>any</b> objective is being completed.<br/> + /// Use specific events or the subclasses of the <see cref="ObjectiveCompletingBaseEventArgs"/> to determine which kind of the objective is being completed. + /// </summary> + /// <remarks> + /// This event is called <b>after</b> the very specific objective event has been triggered. + /// </remarks> + public static event LabEventHandler<ObjectiveCompletingBaseEventArgs>? Completing; + + /// <summary> + /// Gets called when <b>any</b> objective has been completed.<br/> + /// Use specific events or the subclasses of the <see cref="ObjectiveCompletedBaseEventArgs"/> to determine which kind of the objective has been completed. + /// </summary> + /// <remarks> + /// This event is called <b>after</b> the very specific objective event has been triggered. + /// </remarks> + public static event LabEventHandler<ObjectiveCompletedBaseEventArgs>? Completed; + + /// <summary> + /// Gets called when the enemy kill objective is being completed. + /// </summary> + public static event LabEventHandler<EnemyKillingObjectiveEventArgs>? KillingEnemyCompleting; + + /// <summary> + /// Gets called when the enemy kill objective has been completed. + /// </summary> + public static event LabEventHandler<EnemyKilledObjectiveEventArgs>? KilledEnemyCompleted; + + /// <summary> + /// Gets called when the player escape objective is being completed. + /// </summary> + public static event LabEventHandler<EscapingObjectiveEventArgs>? EscapingCompleting; + + /// <summary> + /// Gets called when the player escape objective has been completed. + /// </summary> + public static event LabEventHandler<EscapedObjectiveEventArgs>? EscapedCompleted; + + /// <summary> + /// Gets called when the generator activated objective is being completed. + /// </summary> + public static event LabEventHandler<GeneratorActivatingObjectiveEventArgs>? ActivatingGeneratorCompleting; + + /// <summary> + /// Gets called when the generator activated objective has been completed. + /// </summary> + public static event LabEventHandler<GeneratorActivatedObjectiveEventArgs>? ActivatedGeneratorCompleted; + + /// <summary> + /// Gets called when the scp damage objective is being completed. + /// </summary> + public static event LabEventHandler<ScpDamagingObjectiveEventArgs>? DamagingScpCompleting; + + /// <summary> + /// Gets called when the scp damage objective has been completed. + /// </summary> + public static event LabEventHandler<ScpDamagedObjectiveEventArgs>? DamagedScpCompleted; + + /// <summary> + /// Gets called when the scp item pickup objective is being completed. + /// </summary> + public static event LabEventHandler<ScpItemPickingObjectiveEventArgs>? PickingScpItemCompleting; + + /// <summary> + /// Gets called when the scp item pickup objective has been completed. + /// </summary> + public static event LabEventHandler<ScpItemPickedObjectiveEventArgs>? PickedScpItemCompleted; +} From 66f1d711f8c8791d7868646da06b55fecd56532f Mon Sep 17 00:00:00 2001 From: David <david.sebesta@post.cz> Date: Fri, 27 Jun 2025 14:22:48 +0200 Subject: [PATCH 035/215] Keycard Events (#256) * Added inspecting/ed keycard events * Sub-keycard items to normal keycard item (They are in other mr too but aint merged yet) --- .../Interfaces/Items/IKeycardItemEvent.cs | 18 +++++++++ .../PlayerInspectedKeycardEventArgs.cs | 33 +++++++++++++++++ .../PlayerInspectingKeycardEventArgs.cs | 37 +++++++++++++++++++ .../Handlers/PlayerEvents.EventHandlers.cs | 10 +++++ LabApi/Features/Wrappers/Items/Item.cs | 4 +- 5 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 LabApi/Events/Arguments/Interfaces/Items/IKeycardItemEvent.cs create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerInspectedKeycardEventArgs.cs create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerInspectingKeycardEventArgs.cs diff --git a/LabApi/Events/Arguments/Interfaces/Items/IKeycardItemEvent.cs b/LabApi/Events/Arguments/Interfaces/Items/IKeycardItemEvent.cs new file mode 100644 index 00000000..c270c19c --- /dev/null +++ b/LabApi/Events/Arguments/Interfaces/Items/IKeycardItemEvent.cs @@ -0,0 +1,18 @@ +using LabApi.Features.Wrappers; + +namespace LabApi.Events.Arguments.Interfaces; + +/// <summary> +/// Represents an event that involves a keycard item. +/// </summary> +public interface IKeycardItemEvent : IItemEvent +{ + /// <inheritdoc /> + Item? IItemEvent.Item => KeycardItem; + + /// <summary> + /// The keycard item that is involved in the event. + /// </summary> + public KeycardItem KeycardItem { get; } +} + diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInspectedKeycardEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInspectedKeycardEventArgs.cs new file mode 100644 index 00000000..0cee3ce8 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInspectedKeycardEventArgs.cs @@ -0,0 +1,33 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using BaseKeycardItem = InventorySystem.Items.Keycards.KeycardItem; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.InspectedKeycard"/> event. +/// </summary> +public class PlayerInspectedKeycardEventArgs : EventArgs, IPlayerEvent, IKeycardItemEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="PlayerInspectingKeycardEventArgs"/> class. + /// </summary> + /// <param name="hub">The player who inspected the <see cref="KeycardItem"/>.</param> + /// <param name="keycardItem">The keycard item.</param> + public PlayerInspectedKeycardEventArgs(ReferenceHub hub, BaseKeycardItem keycardItem) + { + Player = Player.Get(hub); + KeycardItem = KeycardItem.Get(keycardItem); + } + + /// <summary> + /// Gets the player who inspected the <see cref="KeycardItem"/>. + /// </summary> + public Player Player { get; } + + /// <summary> + /// Gets the keycard item. + /// </summary> + public KeycardItem KeycardItem { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInspectingKeycardEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInspectingKeycardEventArgs.cs new file mode 100644 index 00000000..668d4b87 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInspectingKeycardEventArgs.cs @@ -0,0 +1,37 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using BaseKeycardItem = InventorySystem.Items.Keycards.KeycardItem; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.InspectingKeycard"/> event. +/// </summary> +public class PlayerInspectingKeycardEventArgs : EventArgs, IPlayerEvent, IKeycardItemEvent, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="PlayerInspectingKeycardEventArgs"/> class. + /// </summary> + /// <param name="hub">The player who wants to inspect the <see cref="KeycardItem"/>.</param> + /// <param name="keycardItem">The keycard item.</param> + public PlayerInspectingKeycardEventArgs(ReferenceHub hub, BaseKeycardItem keycardItem) + { + Player = Player.Get(hub); + KeycardItem = KeycardItem.Get(keycardItem); + IsAllowed = true; + } + + /// <summary> + /// Gets the player who wants to inspect <see cref="KeycardItem"/>. + /// </summary> + public Player Player { get; } + + /// <summary> + /// Gets the keycard item. + /// </summary> + public KeycardItem KeycardItem { get; } + + /// <inheritdoc/> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs b/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs index b33a6643..da4cf4e0 100644 --- a/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs +++ b/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs @@ -357,6 +357,16 @@ public static partial class PlayerEvents /// </summary> public static event LabEventHandler<PlayerThrewProjectileEventArgs>? ThrewProjectile; + /// <summary> + /// Gets called when the player wants to inspect any keycard item. + /// </summary> + public static event LabEventHandler<PlayerInspectingKeycardEventArgs>? InspectingKeycard; + + /// <summary> + /// Gets called when the player inspected keycard item. + /// </summary> + public static event LabEventHandler<PlayerInspectedKeycardEventArgs>? InspectedKeycard; + #endregion #region Item Actions and Interactions diff --git a/LabApi/Features/Wrappers/Items/Item.cs b/LabApi/Features/Wrappers/Items/Item.cs index 6cb82c72..d327bf8d 100644 --- a/LabApi/Features/Wrappers/Items/Item.cs +++ b/LabApi/Features/Wrappers/Items/Item.cs @@ -359,7 +359,7 @@ private static void AddItem(ItemBase item) if (!Dictionary.ContainsKey(item)) _ = CreateItemWrapper(item); } - catch(Exception e) + catch (Exception e) { Console.Logger.InternalError($"Failed to handle item creation with error: {e}"); } @@ -380,7 +380,7 @@ private static void RemoveItem(ItemBase itemBase) item.OnRemove(); } } - catch(Exception e) + catch (Exception e) { Console.Logger.InternalError($"Failed to handle item destruction with error: {e}"); } From 2cc6d023864dd35fcfbeb5ea1cf6f6a517360dd3 Mon Sep 17 00:00:00 2001 From: brayden-dowson <88667957+brayden-dowson@users.noreply.github.com> Date: Fri, 27 Jun 2025 21:53:19 +0930 Subject: [PATCH 036/215] init (#259) --- .../Arguments/Interfaces/IDamageEvent.cs | 14 +++ .../Arguments/Interfaces/IRespawnWaveEvent.cs | 14 +++ .../PlayerCancelledUsingItemEventArgs.cs | 2 +- .../PlayerCancellingUsingItemEventArgs.cs | 2 +- .../PlayerChangedRadioRangeEventArgs.cs | 2 +- .../PlayerChangingRadioRangeEventArgs.cs | 2 +- .../PlayerDamagedShootingTargetEventArgs.cs | 2 +- .../PlayerDamagedWindowEventArgs.cs | 2 +- .../PlayerDamagingShootingTargetEventArgs.cs | 2 +- .../PlayerDamagingWindowEventArgs.cs | 2 +- .../PlayerDeactivatingGeneratorEventArgs.cs | 2 +- .../PlayerEvents/PlayerDeathEventArgs.cs | 2 +- .../PlayerDroppingItemEventArgs.cs | 2 +- .../PlayerDryFiringWeaponEventArgs.cs | 2 +- .../PlayerEvents/PlayerDyingEventArgs.cs | 2 +- .../PlayerEffectUpdatingEventArgs.cs | 2 +- .../PlayerFlippingCoinEventArgs.cs | 2 +- .../PlayerEvents/PlayerHurtEventArgs.cs | 2 +- .../PlayerEvents/PlayerHurtingEventArgs.cs | 2 +- .../PlayerInteractingDoorEventArgs.cs | 2 +- .../PlayerEvents/PlayerPlacedBulletHole.cs | 3 +- .../PlayerReloadingWeaponEventArgs.cs | 2 +- .../PlayerSpawnedRagdollEventArgs.cs | 2 +- .../PlayerSpawningRagdollEventArgs.cs | 2 +- .../ServerEvents/CassieAnnouncedEventArgs.cs | 2 +- .../ServerEvents/CassieAnnouncingEventArgs.cs | 2 +- .../ServerEvents/ExplosionSpawnedEventArgs.cs | 79 ++++++++------- .../ExplosionSpawningEventArgs.cs | 97 +++++++++---------- .../ServerEvents/WaveRespawnedEventArgs.cs | 3 +- .../ServerEvents/WaveRespawningEventArgs.cs | 2 +- .../ServerEvents/WaveTeamSelectedEventArgs.cs | 3 +- .../WaveTeamSelectingEventArgs.cs | 7 +- LabApi/Features/Enums/SpeakerToyMixerGroup.cs | 84 ++++++++++++++++ .../Features/Wrappers/AdminToys/AdminToy.cs | 2 +- .../Features/Wrappers/AdminToys/SpeakerToy.cs | 14 +++ LabApi/Features/Wrappers/AdminToys/TextToy.cs | 12 +++ 36 files changed, 260 insertions(+), 120 deletions(-) create mode 100644 LabApi/Events/Arguments/Interfaces/IDamageEvent.cs create mode 100644 LabApi/Events/Arguments/Interfaces/IRespawnWaveEvent.cs create mode 100644 LabApi/Features/Enums/SpeakerToyMixerGroup.cs diff --git a/LabApi/Events/Arguments/Interfaces/IDamageEvent.cs b/LabApi/Events/Arguments/Interfaces/IDamageEvent.cs new file mode 100644 index 00000000..3dea313c --- /dev/null +++ b/LabApi/Events/Arguments/Interfaces/IDamageEvent.cs @@ -0,0 +1,14 @@ +using PlayerStatsSystem; + +namespace LabApi.Events.Arguments.Interfaces; + +/// <summary> +/// Represents an event that involved a damage handler. +/// </summary> +public interface IDamageEvent +{ + /// <summary> + /// The damage handler that is involved in the event. + /// </summary> + public DamageHandlerBase? DamageHandler { get; } +} diff --git a/LabApi/Events/Arguments/Interfaces/IRespawnWaveEvent.cs b/LabApi/Events/Arguments/Interfaces/IRespawnWaveEvent.cs new file mode 100644 index 00000000..2ef197a8 --- /dev/null +++ b/LabApi/Events/Arguments/Interfaces/IRespawnWaveEvent.cs @@ -0,0 +1,14 @@ +using LabApi.Features.Wrappers; + +namespace LabApi.Events.Arguments.Interfaces; + +/// <summary> +/// Represents an event that involves a respawn wave. +/// </summary> +public interface IRespawnWaveEvent +{ + /// <summary> + /// The respawn wave that is involved in the event. + /// </summary> + public RespawnWave? Wave { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerCancelledUsingItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerCancelledUsingItemEventArgs.cs index ec2b16bd..5b795d28 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerCancelledUsingItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerCancelledUsingItemEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.CancelledUsingItem"/> event. /// </summary> -public class PlayerCancelledUsingItemEventArgs : EventArgs, IUsableItemEvent +public class PlayerCancelledUsingItemEventArgs : EventArgs, IPlayerEvent, IUsableItemEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerCancelledUsingItemEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerCancellingUsingItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerCancellingUsingItemEventArgs.cs index 60c16c64..66976cf2 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerCancellingUsingItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerCancellingUsingItemEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.CancellingUsingItem"/> event. /// </summary> -public class PlayerCancellingUsingItemEventArgs : EventArgs, IUsableItemEvent, ICancellableEvent +public class PlayerCancellingUsingItemEventArgs : EventArgs, IPlayerEvent, IUsableItemEvent, ICancellableEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerCancellingUsingItemEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangedRadioRangeEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedRadioRangeEventArgs.cs index 92984e5b..5dab65f4 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerChangedRadioRangeEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedRadioRangeEventArgs.cs @@ -9,7 +9,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.ChangedRadioRange"/> event. /// </summary> -public class PlayerChangedRadioRangeEventArgs : EventArgs, IRadioItemEvent +public class PlayerChangedRadioRangeEventArgs : EventArgs, IPlayerEvent, IRadioItemEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerChangedRadioRangeEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangingRadioRangeEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingRadioRangeEventArgs.cs index 0f79bfc5..a6443d9b 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerChangingRadioRangeEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingRadioRangeEventArgs.cs @@ -9,7 +9,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.ChangingRadioRange"/> event. /// </summary> -public class PlayerChangingRadioRangeEventArgs : EventArgs, IRadioItemEvent, ICancellableEvent +public class PlayerChangingRadioRangeEventArgs : EventArgs, IPlayerEvent, IRadioItemEvent, ICancellableEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerChangingRadioRangeEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagedShootingTargetEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagedShootingTargetEventArgs.cs index cf0010f7..ebdefb4f 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagedShootingTargetEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagedShootingTargetEventArgs.cs @@ -9,7 +9,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.DamagedShootingTarget"/> event. /// </summary> -public class PlayerDamagedShootingTargetEventArgs : EventArgs, IPlayerEvent, IShootingTargetEvent +public class PlayerDamagedShootingTargetEventArgs : EventArgs, IPlayerEvent, IShootingTargetEvent, IDamageEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerDamagedShootingTargetEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagedWindowEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagedWindowEventArgs.cs index 2a67d768..04928b9e 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagedWindowEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagedWindowEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.DamagedWindow"/> event. /// </summary> -public class PlayerDamagedWindowEventArgs : EventArgs, IPlayerEvent +public class PlayerDamagedWindowEventArgs : EventArgs, IPlayerEvent, IDamageEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerDamagedWindowEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingShootingTargetEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingShootingTargetEventArgs.cs index 1a25a160..3a571809 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingShootingTargetEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingShootingTargetEventArgs.cs @@ -9,7 +9,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.DamagingShootingTarget"/> event. /// </summary> -public class PlayerDamagingShootingTargetEventArgs : EventArgs, IPlayerEvent, IShootingTargetEvent, ICancellableEvent +public class PlayerDamagingShootingTargetEventArgs : EventArgs, IPlayerEvent, IShootingTargetEvent, IDamageEvent, ICancellableEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerDamagingShootingTargetEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingWindowEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingWindowEventArgs.cs index 3758606e..6053b36c 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingWindowEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingWindowEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.DamagingWindow"/> event. /// </summary> -public class PlayerDamagingWindowEventArgs : EventArgs, ICancellableEvent +public class PlayerDamagingWindowEventArgs : EventArgs, IPlayerEvent, IDamageEvent, ICancellableEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerDamagingWindowEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDeactivatingGeneratorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDeactivatingGeneratorEventArgs.cs index 57bbf5b6..70ff0fdd 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDeactivatingGeneratorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDeactivatingGeneratorEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.DeactivatingGenerator"/> event. /// </summary> -public class PlayerDeactivatingGeneratorEventArgs : EventArgs, IGeneratorEvent, ICancellableEvent +public class PlayerDeactivatingGeneratorEventArgs : EventArgs, IPlayerEvent, IGeneratorEvent, ICancellableEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerDeactivatingGeneratorEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDeathEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDeathEventArgs.cs index d58359eb..f0de17e1 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDeathEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDeathEventArgs.cs @@ -10,7 +10,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.Death"/> event. /// </summary> -public class PlayerDeathEventArgs : EventArgs, IPlayerEvent +public class PlayerDeathEventArgs : EventArgs, IPlayerEvent, IDamageEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerDeathEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs index dc5f3e4d..058a64d0 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.DroppingItem"/> event. /// </summary> -public class PlayerDroppingItemEventArgs : EventArgs, ICancellableEvent, IItemEvent +public class PlayerDroppingItemEventArgs : EventArgs, IPlayerEvent, ICancellableEvent, IItemEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerDroppingItemEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDryFiringWeaponEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDryFiringWeaponEventArgs.cs index 61d62ffe..ebfb6f6b 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDryFiringWeaponEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDryFiringWeaponEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.DryFiringWeapon"/> event. /// </summary> -public class PlayerDryFiringWeaponEventArgs : EventArgs, IFirearmItemEvent, ICancellableEvent +public class PlayerDryFiringWeaponEventArgs : EventArgs, IPlayerEvent, IFirearmItemEvent, ICancellableEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerDryFiringWeaponEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDyingEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDyingEventArgs.cs index 70dafb23..9daba48d 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDyingEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDyingEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.Dying"/> event. /// </summary> -public class PlayerDyingEventArgs : EventArgs, ICancellableEvent, IPlayerEvent +public class PlayerDyingEventArgs : EventArgs, IPlayerEvent, IDamageEvent, ICancellableEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerDyingEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerEffectUpdatingEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerEffectUpdatingEventArgs.cs index 54c84d53..1b85b948 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerEffectUpdatingEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerEffectUpdatingEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.UpdatingEffect"/> event. /// </summary> -public class PlayerEffectUpdatingEventArgs : EventArgs, ICancellableEvent +public class PlayerEffectUpdatingEventArgs : EventArgs, IPlayerEvent, ICancellableEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerEffectUpdatingEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerFlippingCoinEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerFlippingCoinEventArgs.cs index 84c1d6ad..0821f5e3 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerFlippingCoinEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerFlippingCoinEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.FlippingCoin"/> event. /// </summary> -public class PlayerFlippingCoinEventArgs : EventArgs, ICancellableEvent, ICoinItemEvent +public class PlayerFlippingCoinEventArgs : EventArgs, IPlayerEvent, ICancellableEvent, ICoinItemEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerFlippingCoinEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerHurtEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerHurtEventArgs.cs index 1e1603a7..044fd58c 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerHurtEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerHurtEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.Hurt"/> event. /// </summary> -public class PlayerHurtEventArgs : EventArgs, IPlayerEvent +public class PlayerHurtEventArgs : EventArgs, IPlayerEvent, IDamageEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerHurtEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerHurtingEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerHurtingEventArgs.cs index b60f1e24..30b54a8b 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerHurtingEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerHurtingEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.Hurting"/> event. /// </summary> -public class PlayerHurtingEventArgs : EventArgs, IPlayerEvent, ICancellableEvent +public class PlayerHurtingEventArgs : EventArgs, IPlayerEvent, IDamageEvent, ICancellableEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerHurtingEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingDoorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingDoorEventArgs.cs index 012e450f..f64b1fb0 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingDoorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingDoorEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.InteractingDoor"/> event. /// </summary> -public class PlayerInteractingDoorEventArgs : EventArgs, IDoorEvent, ICancellableEvent +public class PlayerInteractingDoorEventArgs : EventArgs, IPlayerEvent, IDoorEvent, ICancellableEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerInteractingDoorEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBulletHole.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBulletHole.cs index 0c9bab18..f71337cc 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBulletHole.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBulletHole.cs @@ -1,4 +1,5 @@ using Decals; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using System; using UnityEngine; @@ -8,7 +9,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.PlacedBulletHole"/> event. /// </summary> -public class PlayerPlacedBulletHoleEventArgs : EventArgs +public class PlayerPlacedBulletHoleEventArgs : EventArgs, IPlayerEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerPlacedBulletHoleEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerReloadingWeaponEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerReloadingWeaponEventArgs.cs index f98f9781..79b350f8 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerReloadingWeaponEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerReloadingWeaponEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.ReloadingWeapon"/> event. /// </summary> -public class PlayerReloadingWeaponEventArgs : EventArgs, IFirearmItemEvent, ICancellableEvent +public class PlayerReloadingWeaponEventArgs : EventArgs, IPlayerEvent, IFirearmItemEvent, ICancellableEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerReloadingWeaponEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSpawnedRagdollEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSpawnedRagdollEventArgs.cs index 7ccd0b9f..29fd164d 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSpawnedRagdollEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSpawnedRagdollEventArgs.cs @@ -9,7 +9,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.SpawnedRagdoll"/> event. /// </summary> -public class PlayerSpawnedRagdollEventArgs : EventArgs, IPlayerEvent, IRagdollEvent +public class PlayerSpawnedRagdollEventArgs : EventArgs, IPlayerEvent, IRagdollEvent, IDamageEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerSpawnedRagdollEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSpawningRagdollEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSpawningRagdollEventArgs.cs index 811263ee..67857a6b 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSpawningRagdollEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSpawningRagdollEventArgs.cs @@ -9,7 +9,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.SpawningRagdoll"/> event. /// </summary> -public class PlayerSpawningRagdollEventArgs : EventArgs, IPlayerEvent, IRagdollEvent, ICancellableEvent +public class PlayerSpawningRagdollEventArgs : EventArgs, IPlayerEvent, IRagdollEvent, IDamageEvent, ICancellableEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerSpawningRagdollEventArgs"/> class. diff --git a/LabApi/Events/Arguments/ServerEvents/CassieAnnouncedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/CassieAnnouncedEventArgs.cs index 2aff367f..acfa7c80 100644 --- a/LabApi/Events/Arguments/ServerEvents/CassieAnnouncedEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/CassieAnnouncedEventArgs.cs @@ -25,7 +25,7 @@ public CassieAnnouncedEventArgs(string words, bool makeHold, bool makeNoise, boo } /// <summary> - /// Gets sentece which C.A.S.S.I.E. said. + /// Gets sentence which C.A.S.S.I.E. said. /// </summary> public string Words { get; } diff --git a/LabApi/Events/Arguments/ServerEvents/CassieAnnouncingEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/CassieAnnouncingEventArgs.cs index 0ceb04ad..457ecf6a 100644 --- a/LabApi/Events/Arguments/ServerEvents/CassieAnnouncingEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/CassieAnnouncingEventArgs.cs @@ -27,7 +27,7 @@ public CassieAnnouncingEventArgs(string words, bool makeHold, bool makeNoise, bo } /// <summary> - /// Gets or sets sentece which C.A.S.S.I.E. will say. + /// Gets or sets sentence which C.A.S.S.I.E. will say. /// </summary> public string Words { get; set; } diff --git a/LabApi/Events/Arguments/ServerEvents/ExplosionSpawnedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/ExplosionSpawnedEventArgs.cs index fe56ed15..260bce39 100644 --- a/LabApi/Events/Arguments/ServerEvents/ExplosionSpawnedEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/ExplosionSpawnedEventArgs.cs @@ -4,53 +4,52 @@ using System; using UnityEngine; -namespace LabApi.Events.Arguments.ServerEvents +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.ExplosionSpawned"/> event. +/// </summary> +public class ExplosionSpawnedEventArgs : EventArgs, IPlayerEvent { /// <summary> - /// Represents the arguments for the <see cref="Handlers.ServerEvents.ExplosionSpawned"/> event. + /// Initializes a new instance of the <see cref="ExplosionSpawnedEventArgs"/> class. /// </summary> - public class ExplosionSpawnedEventArgs : EventArgs, IPlayerEvent + /// <param name="player">The player which caused this explosion.</param> + /// <param name="position">The position of explosion.</param> + /// <param name="settingsReference">The projectile which caused explosion.</param> + /// <param name="explosionType">The type of this explosion.</param> + /// <param name="destroyDoors">Whether the explosion was allowed to destroy doors.</param> + public ExplosionSpawnedEventArgs(ReferenceHub? player, Vector3 position, ExplosionGrenade settingsReference, ExplosionType explosionType, bool destroyDoors) { - /// <summary> - /// Initializes a new instance of the <see cref="ExplosionSpawnedEventArgs"/> class. - /// </summary> - /// <param name="player">The player which caused this explosion.</param> - /// <param name="position">The position of explosion.</param> - /// <param name="settingsReference">The projectile which caused explosion.</param> - /// <param name="explosionType">The type of this explosion.</param> - /// <param name="destroyDoors">Whether the explosion was allowed to destroy doors.</param> - public ExplosionSpawnedEventArgs(ReferenceHub? player, Vector3 position, ExplosionGrenade settingsReference, ExplosionType explosionType, bool destroyDoors) - { - Player = Player.Get(player); - Position = position; - Settings = settingsReference; - ExplosionType = explosionType; - DestroyDoors = destroyDoors; - } + Player = Player.Get(player); + Position = position; + Settings = settingsReference; + ExplosionType = explosionType; + DestroyDoors = destroyDoors; + } - /// <summary> - /// Gets the player which caused this explosion. - /// </summary> - public Player? Player { get; } + /// <summary> + /// Gets the player which caused this explosion. + /// </summary> + public Player? Player { get; } - /// <summary> - /// Gets the position of explosion. - /// </summary> - public Vector3 Position { get; } + /// <summary> + /// Gets the position of explosion. + /// </summary> + public Vector3 Position { get; } - /// <summary> - /// Gets the projectile which will cause explosion. - /// </summary> - public ExplosionGrenade Settings { get; } + /// <summary> + /// Gets the projectile which will cause explosion. + /// </summary> + public ExplosionGrenade Settings { get; } - /// <summary> - /// Gets the type of this explosion. - /// </summary> - public ExplosionType ExplosionType { get; } + /// <summary> + /// Gets the type of this explosion. + /// </summary> + public ExplosionType ExplosionType { get; } - /// <summary> - /// Gets whether the explosion should destroy doors. - /// </summary> - public bool DestroyDoors { get; } - } + /// <summary> + /// Gets whether the explosion should destroy doors. + /// </summary> + public bool DestroyDoors { get; } } diff --git a/LabApi/Events/Arguments/ServerEvents/ExplosionSpawningEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/ExplosionSpawningEventArgs.cs index 29638552..cf05158c 100644 --- a/LabApi/Events/Arguments/ServerEvents/ExplosionSpawningEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/ExplosionSpawningEventArgs.cs @@ -4,58 +4,57 @@ using System; using UnityEngine; -namespace LabApi.Events.Arguments.ServerEvents +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.ExplosionSpawning"/> event. +/// </summary> +public class ExplosionSpawningEventArgs : EventArgs, IPlayerEvent, ICancellableEvent { /// <summary> - /// Represents the arguments for the <see cref="Handlers.ServerEvents.ExplosionSpawning"/> event. + /// Initializes a new instance of the <see cref="ExplosionSpawningEventArgs"/> class. /// </summary> - public class ExplosionSpawningEventArgs : EventArgs, IPlayerEvent, ICancellableEvent + /// <param name="player">The player which caused this explosion.</param> + /// <param name="position">The position of explosion.</param> + /// <param name="settingsReference">The projectile which will cause the explosion.</param> + /// <param name="explosionType">The type of this explosion.</param> + /// <param name="destroyDoors">Whether the explosion should destroy doors.</param> + public ExplosionSpawningEventArgs(ReferenceHub? player, Vector3 position, ExplosionGrenade settingsReference, ExplosionType explosionType, bool destroyDoors) { - /// <summary> - /// Initializes a new instance of the <see cref="ExplosionSpawningEventArgs"/> class. - /// </summary> - /// <param name="player">The player which caused this explosion.</param> - /// <param name="position">The position of explosion.</param> - /// <param name="settingsReference">The projectile which will cause the explosion.</param> - /// <param name="explosionType">The type of this explosion.</param> - /// <param name="destroyDoors">Whether the explosion should destroy doors.</param> - public ExplosionSpawningEventArgs(ReferenceHub? player, Vector3 position, ExplosionGrenade settingsReference, ExplosionType explosionType, bool destroyDoors) - { - Player = Player.Get(player); - Position = position; - Settings = settingsReference; - ExplosionType = explosionType; - DestroyDoors = destroyDoors; - - IsAllowed = true; - } - - /// <summary> - /// Gets or sets the player which caused this explosion. - /// </summary> - public Player? Player { get; set; } - - /// <summary> - /// Gets or sets the position of explosion. - /// </summary> - public Vector3 Position { get; set; } - - /// <summary> - /// Gets or sets the projectile which will cause explosion. - /// </summary> - public ExplosionGrenade Settings { get; set; } - - /// <summary> - /// Gets or sets the type of this explosion. - /// </summary> - public ExplosionType ExplosionType { get; set; } - - /// <summary> - /// Gets or sets whether the explosion should destroy doors. - /// </summary> - public bool DestroyDoors { get; set; } - - /// <inheritdoc/> - public bool IsAllowed { get; set; } + Player = Player.Get(player); + Position = position; + Settings = settingsReference; + ExplosionType = explosionType; + DestroyDoors = destroyDoors; + + IsAllowed = true; } + + /// <summary> + /// Gets or sets the player which caused this explosion. + /// </summary> + public Player? Player { get; set; } + + /// <summary> + /// Gets or sets the position of explosion. + /// </summary> + public Vector3 Position { get; set; } + + /// <summary> + /// Gets or sets the projectile which will cause explosion. + /// </summary> + public ExplosionGrenade Settings { get; set; } + + /// <summary> + /// Gets or sets the type of this explosion. + /// </summary> + public ExplosionType ExplosionType { get; set; } + + /// <summary> + /// Gets or sets whether the explosion should destroy doors. + /// </summary> + public bool DestroyDoors { get; set; } + + /// <inheritdoc/> + public bool IsAllowed { get; set; } } diff --git a/LabApi/Events/Arguments/ServerEvents/WaveRespawnedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/WaveRespawnedEventArgs.cs index 8b930c55..6eb9e131 100644 --- a/LabApi/Events/Arguments/ServerEvents/WaveRespawnedEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/WaveRespawnedEventArgs.cs @@ -1,3 +1,4 @@ +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using Respawning.Waves; using System; @@ -8,7 +9,7 @@ namespace LabApi.Events.Arguments.ServerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.ServerEvents.WaveRespawned"/> event. /// </summary> -public class WaveRespawnedEventArgs : EventArgs +public class WaveRespawnedEventArgs : EventArgs, IRespawnWaveEvent { /// <summary> /// Initializes a new instance of the <see cref="WaveRespawnedEventArgs"/> class. diff --git a/LabApi/Events/Arguments/ServerEvents/WaveRespawningEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/WaveRespawningEventArgs.cs index 5a0f8683..15221cbc 100644 --- a/LabApi/Events/Arguments/ServerEvents/WaveRespawningEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/WaveRespawningEventArgs.cs @@ -11,7 +11,7 @@ namespace LabApi.Events.Arguments.ServerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.ServerEvents.WaveRespawning"/> event. /// </summary> -public class WaveRespawningEventArgs : EventArgs, ICancellableEvent +public class WaveRespawningEventArgs : EventArgs, IRespawnWaveEvent, ICancellableEvent { /// <summary> /// Initializes a new instance of the <see cref="WaveRespawningEventArgs"/> class. diff --git a/LabApi/Events/Arguments/ServerEvents/WaveTeamSelectedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/WaveTeamSelectedEventArgs.cs index 3a833c6e..8544e4ce 100644 --- a/LabApi/Events/Arguments/ServerEvents/WaveTeamSelectedEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/WaveTeamSelectedEventArgs.cs @@ -1,3 +1,4 @@ +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using Respawning.Waves; using System; @@ -7,7 +8,7 @@ namespace LabApi.Events.Arguments.ServerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.ServerEvents.WaveTeamSelected"/> event. /// </summary> -public class WaveTeamSelectedEventArgs : EventArgs +public class WaveTeamSelectedEventArgs : EventArgs, IRespawnWaveEvent { /// <summary> /// Initializes a new instance of the <see cref="WaveTeamSelectedEventArgs"/> class. diff --git a/LabApi/Events/Arguments/ServerEvents/WaveTeamSelectingEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/WaveTeamSelectingEventArgs.cs index d3ba16e1..f44dd7aa 100644 --- a/LabApi/Events/Arguments/ServerEvents/WaveTeamSelectingEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/WaveTeamSelectingEventArgs.cs @@ -1,4 +1,5 @@ using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; using Respawning; using Respawning.Waves; using System; @@ -8,7 +9,7 @@ namespace LabApi.Events.Arguments.ServerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.ServerEvents.WaveTeamSelecting"/> event. /// </summary> -public class WaveTeamSelectingEventArgs : EventArgs, ICancellableEvent +public class WaveTeamSelectingEventArgs : EventArgs, IRespawnWaveEvent, ICancellableEvent { /// <summary> /// Initializes a new instance of the <see cref="WaveTeamSelectingEventArgs"/> class. @@ -17,14 +18,14 @@ public class WaveTeamSelectingEventArgs : EventArgs, ICancellableEvent public WaveTeamSelectingEventArgs(SpawnableWaveBase wave) { IsAllowed = true; - Wave = wave; + Wave = RespawnWaves.Get(wave); } /// <summary> /// Gets or sets the spawnable wave. See <see cref="SpawnableWaveBase"/> and its subclasses.<br/> /// Use the <see cref="WaveManager.Waves"/> to set it to a different value. /// </summary> - public SpawnableWaveBase Wave { get; set; } + public RespawnWave Wave { get; set; } /// <inheritdoc /> public bool IsAllowed { get; set; } diff --git a/LabApi/Features/Enums/SpeakerToyMixerGroup.cs b/LabApi/Features/Enums/SpeakerToyMixerGroup.cs new file mode 100644 index 00000000..0d10c98e --- /dev/null +++ b/LabApi/Features/Enums/SpeakerToyMixerGroup.cs @@ -0,0 +1,84 @@ +using LabApi.Features.Wrappers; + +namespace LabApi.Features.Enums; + +/// <summary> +/// Represents the different types of audio mixer groups that can be assigned to a <see cref="SpeakerToy"/>. +/// Audio mixers group starting with Sfx are effected by the player Sound effect volume while ones with Vc are effected by Voice chat volume. +/// </summary> +public enum SpeakerToyMixerGroup +{ + /// <summary> + /// Mixer group used for general sound effects audio. + /// No audio effects are applied in this group. + /// </summary> + SfxGeneral, + + /// <summary> + /// Mixer group used for CASSIE related broadcasts. + /// Same audio effects used by CASSIE are applied. + /// </summary> + SfxCassie, + + /// <summary> + /// Mixer group used for weapons/gun shots. + /// </summary> + SfxWeapons, + + /// <summary> + /// Mixer group used to apply reverb. + /// </summary> + SfxReverbNoDucking, + + /// <summary> + /// Mixer group used to apply reverb and audio ducking. + /// </summary> + SfxReverbDucking, + + /// <summary> + /// Mixer group used for the games backgroud music. + /// </summary> + SfxMusic, + + /// <summary> + /// Mixer group used for general voice chat audio. + /// No audio effects are applied in this group. + /// </summary> + VcGeneral, + + /// <summary> + /// Mixer group used for intercom voice broadcasts. + /// Same effects used by the intercom are applied. + /// </summary> + VcIntercom, + + /// <summary> + /// Mixer group used for radio voice chat. + /// Same effects used by radio char are applied. + /// </summary> + VcRadio, + + /// <summary> + /// One of the two mixer groups used by proximity chat. + /// This is the dry unfiltered part of the proximity voice. + /// </summary> + /// <remarks> + /// True proximity chat cannot be replicated by a speaker toy. + /// </remarks> + VcProximity, + + /// <summary> + /// One of the two mixer group used by proximity chat. + /// This is the wet reverberated part of the proximity voice. + /// </summary> + /// <remarks> + /// True proximity chat cannot be replicated by a speaker toy. + /// </remarks> + VcProximityReverb, + + /// <summary> + /// Mixer group used by SCP-079 speakers. + /// Same effects used by SCP-079 speakers are applied. + /// </summary> + VcScp079 +} \ No newline at end of file diff --git a/LabApi/Features/Wrappers/AdminToys/AdminToy.cs b/LabApi/Features/Wrappers/AdminToys/AdminToy.cs index 507168bd..63326be9 100644 --- a/LabApi/Features/Wrappers/AdminToys/AdminToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/AdminToy.cs @@ -130,7 +130,7 @@ public Vector3 Scale /// Gets or sets the parent of the admin toy. /// </summary> /// <remarks> - /// If the parent object contains a <see cref="NetworkIdentity"/> component and has been <see cref="NetworkServer.Spawn(GameObject, GameObject)"/> the parent is synced with the client. + /// If the parent object contains a <see cref="NetworkIdentity"/> component or one of the objects higher up in the parents hierarchy has a <see cref="NetworkIdentity"/> component and it has been <see cref="NetworkServer.Spawn(GameObject, GameObject)"/> the parent is synced with the client. /// <para> /// Can be used even if <see cref="IsStatic"/> is true. /// When changing parent the toys relative <see cref="Position"/>, <see cref="Rotation"/> and <see cref="Scale"/> are retained. diff --git a/LabApi/Features/Wrappers/AdminToys/SpeakerToy.cs b/LabApi/Features/Wrappers/AdminToys/SpeakerToy.cs index 78c280d5..9c024b71 100644 --- a/LabApi/Features/Wrappers/AdminToys/SpeakerToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/SpeakerToy.cs @@ -1,4 +1,5 @@ using LabApi.Features.Audio; +using LabApi.Features.Enums; using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; @@ -100,6 +101,19 @@ public float MaxDistance set => Base.NetworkMaxDistance = value; } + /// <summary> + /// Gets or sets the audio mixer group used as output by the speaker. + /// By default this is set to <see cref="SpeakerToyMixerGroup.SfxReverbDucking"/>. + /// </summary> + /// <remarks> + /// Each <see cref="SpeakerToyMixerGroup"/> has a different set of effects or is attenuated differently by the players audio settings. + /// </remarks> + public SpeakerToyMixerGroup OutputMixer + { + get => (SpeakerToyMixerGroup)Base.OutputMixerId; + set => Base.NetworkOutputMixerId = (byte)value; + } + /// <summary> /// Gets or sets the current sample position of the playback head. /// </summary> diff --git a/LabApi/Features/Wrappers/AdminToys/TextToy.cs b/LabApi/Features/Wrappers/AdminToys/TextToy.cs index f2469f5e..fdb88fe3 100644 --- a/LabApi/Features/Wrappers/AdminToys/TextToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/TextToy.cs @@ -64,6 +64,18 @@ public Vector2 DisplaySize set => Base.DisplaySize = value; } + /// <summary> + /// Gets or sets whether or not the text should render as apart of the UI. + /// </summary> + /// <remarks> + /// When rendering as apart of the UI, text is not effected by any post processing effects that can blur/distort it and it can render on top of the players view model if placed correctly. + /// </remarks> + public bool RenderAsUserInterface + { + get => Base.RenderAsUserInterface; + set => Base.RenderAsUserInterface = value; + } + /// <summary> /// Gets the arguments used while formatting the <see cref="TextFormat"/>.<br/> /// Missing arguments for <see cref="TextFormat"/> are not replaced and any extra arguments are ignored. From 9118ae70c1f75916a1060a9dc4be64fd4c9ebac3 Mon Sep 17 00:00:00 2001 From: Jesus QC <69375249+Jesus-QC@users.noreply.github.com> Date: Fri, 27 Jun 2025 14:27:31 +0200 Subject: [PATCH 037/215] Revert "init (#259)" (#262) This reverts commit 2cc6d023864dd35fcfbeb5ea1cf6f6a517360dd3. --- .../Arguments/Interfaces/IDamageEvent.cs | 14 --- .../Arguments/Interfaces/IRespawnWaveEvent.cs | 14 --- .../PlayerCancelledUsingItemEventArgs.cs | 2 +- .../PlayerCancellingUsingItemEventArgs.cs | 2 +- .../PlayerChangedRadioRangeEventArgs.cs | 2 +- .../PlayerChangingRadioRangeEventArgs.cs | 2 +- .../PlayerDamagedShootingTargetEventArgs.cs | 2 +- .../PlayerDamagedWindowEventArgs.cs | 2 +- .../PlayerDamagingShootingTargetEventArgs.cs | 2 +- .../PlayerDamagingWindowEventArgs.cs | 2 +- .../PlayerDeactivatingGeneratorEventArgs.cs | 2 +- .../PlayerEvents/PlayerDeathEventArgs.cs | 2 +- .../PlayerDroppingItemEventArgs.cs | 2 +- .../PlayerDryFiringWeaponEventArgs.cs | 2 +- .../PlayerEvents/PlayerDyingEventArgs.cs | 2 +- .../PlayerEffectUpdatingEventArgs.cs | 2 +- .../PlayerFlippingCoinEventArgs.cs | 2 +- .../PlayerEvents/PlayerHurtEventArgs.cs | 2 +- .../PlayerEvents/PlayerHurtingEventArgs.cs | 2 +- .../PlayerInteractingDoorEventArgs.cs | 2 +- .../PlayerEvents/PlayerPlacedBulletHole.cs | 3 +- .../PlayerReloadingWeaponEventArgs.cs | 2 +- .../PlayerSpawnedRagdollEventArgs.cs | 2 +- .../PlayerSpawningRagdollEventArgs.cs | 2 +- .../ServerEvents/CassieAnnouncedEventArgs.cs | 2 +- .../ServerEvents/CassieAnnouncingEventArgs.cs | 2 +- .../ServerEvents/ExplosionSpawnedEventArgs.cs | 79 +++++++-------- .../ExplosionSpawningEventArgs.cs | 97 ++++++++++--------- .../ServerEvents/WaveRespawnedEventArgs.cs | 3 +- .../ServerEvents/WaveRespawningEventArgs.cs | 2 +- .../ServerEvents/WaveTeamSelectedEventArgs.cs | 3 +- .../WaveTeamSelectingEventArgs.cs | 7 +- LabApi/Features/Enums/SpeakerToyMixerGroup.cs | 84 ---------------- .../Features/Wrappers/AdminToys/AdminToy.cs | 2 +- .../Features/Wrappers/AdminToys/SpeakerToy.cs | 14 --- LabApi/Features/Wrappers/AdminToys/TextToy.cs | 12 --- 36 files changed, 120 insertions(+), 260 deletions(-) delete mode 100644 LabApi/Events/Arguments/Interfaces/IDamageEvent.cs delete mode 100644 LabApi/Events/Arguments/Interfaces/IRespawnWaveEvent.cs delete mode 100644 LabApi/Features/Enums/SpeakerToyMixerGroup.cs diff --git a/LabApi/Events/Arguments/Interfaces/IDamageEvent.cs b/LabApi/Events/Arguments/Interfaces/IDamageEvent.cs deleted file mode 100644 index 3dea313c..00000000 --- a/LabApi/Events/Arguments/Interfaces/IDamageEvent.cs +++ /dev/null @@ -1,14 +0,0 @@ -using PlayerStatsSystem; - -namespace LabApi.Events.Arguments.Interfaces; - -/// <summary> -/// Represents an event that involved a damage handler. -/// </summary> -public interface IDamageEvent -{ - /// <summary> - /// The damage handler that is involved in the event. - /// </summary> - public DamageHandlerBase? DamageHandler { get; } -} diff --git a/LabApi/Events/Arguments/Interfaces/IRespawnWaveEvent.cs b/LabApi/Events/Arguments/Interfaces/IRespawnWaveEvent.cs deleted file mode 100644 index 2ef197a8..00000000 --- a/LabApi/Events/Arguments/Interfaces/IRespawnWaveEvent.cs +++ /dev/null @@ -1,14 +0,0 @@ -using LabApi.Features.Wrappers; - -namespace LabApi.Events.Arguments.Interfaces; - -/// <summary> -/// Represents an event that involves a respawn wave. -/// </summary> -public interface IRespawnWaveEvent -{ - /// <summary> - /// The respawn wave that is involved in the event. - /// </summary> - public RespawnWave? Wave { get; } -} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerCancelledUsingItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerCancelledUsingItemEventArgs.cs index 5b795d28..ec2b16bd 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerCancelledUsingItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerCancelledUsingItemEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.CancelledUsingItem"/> event. /// </summary> -public class PlayerCancelledUsingItemEventArgs : EventArgs, IPlayerEvent, IUsableItemEvent +public class PlayerCancelledUsingItemEventArgs : EventArgs, IUsableItemEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerCancelledUsingItemEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerCancellingUsingItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerCancellingUsingItemEventArgs.cs index 66976cf2..60c16c64 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerCancellingUsingItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerCancellingUsingItemEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.CancellingUsingItem"/> event. /// </summary> -public class PlayerCancellingUsingItemEventArgs : EventArgs, IPlayerEvent, IUsableItemEvent, ICancellableEvent +public class PlayerCancellingUsingItemEventArgs : EventArgs, IUsableItemEvent, ICancellableEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerCancellingUsingItemEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangedRadioRangeEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedRadioRangeEventArgs.cs index 5dab65f4..92984e5b 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerChangedRadioRangeEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedRadioRangeEventArgs.cs @@ -9,7 +9,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.ChangedRadioRange"/> event. /// </summary> -public class PlayerChangedRadioRangeEventArgs : EventArgs, IPlayerEvent, IRadioItemEvent +public class PlayerChangedRadioRangeEventArgs : EventArgs, IRadioItemEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerChangedRadioRangeEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangingRadioRangeEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingRadioRangeEventArgs.cs index a6443d9b..0f79bfc5 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerChangingRadioRangeEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingRadioRangeEventArgs.cs @@ -9,7 +9,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.ChangingRadioRange"/> event. /// </summary> -public class PlayerChangingRadioRangeEventArgs : EventArgs, IPlayerEvent, IRadioItemEvent, ICancellableEvent +public class PlayerChangingRadioRangeEventArgs : EventArgs, IRadioItemEvent, ICancellableEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerChangingRadioRangeEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagedShootingTargetEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagedShootingTargetEventArgs.cs index ebdefb4f..cf0010f7 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagedShootingTargetEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagedShootingTargetEventArgs.cs @@ -9,7 +9,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.DamagedShootingTarget"/> event. /// </summary> -public class PlayerDamagedShootingTargetEventArgs : EventArgs, IPlayerEvent, IShootingTargetEvent, IDamageEvent +public class PlayerDamagedShootingTargetEventArgs : EventArgs, IPlayerEvent, IShootingTargetEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerDamagedShootingTargetEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagedWindowEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagedWindowEventArgs.cs index 04928b9e..2a67d768 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagedWindowEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagedWindowEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.DamagedWindow"/> event. /// </summary> -public class PlayerDamagedWindowEventArgs : EventArgs, IPlayerEvent, IDamageEvent +public class PlayerDamagedWindowEventArgs : EventArgs, IPlayerEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerDamagedWindowEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingShootingTargetEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingShootingTargetEventArgs.cs index 3a571809..1a25a160 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingShootingTargetEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingShootingTargetEventArgs.cs @@ -9,7 +9,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.DamagingShootingTarget"/> event. /// </summary> -public class PlayerDamagingShootingTargetEventArgs : EventArgs, IPlayerEvent, IShootingTargetEvent, IDamageEvent, ICancellableEvent +public class PlayerDamagingShootingTargetEventArgs : EventArgs, IPlayerEvent, IShootingTargetEvent, ICancellableEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerDamagingShootingTargetEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingWindowEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingWindowEventArgs.cs index 6053b36c..3758606e 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingWindowEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingWindowEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.DamagingWindow"/> event. /// </summary> -public class PlayerDamagingWindowEventArgs : EventArgs, IPlayerEvent, IDamageEvent, ICancellableEvent +public class PlayerDamagingWindowEventArgs : EventArgs, ICancellableEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerDamagingWindowEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDeactivatingGeneratorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDeactivatingGeneratorEventArgs.cs index 70ff0fdd..57bbf5b6 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDeactivatingGeneratorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDeactivatingGeneratorEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.DeactivatingGenerator"/> event. /// </summary> -public class PlayerDeactivatingGeneratorEventArgs : EventArgs, IPlayerEvent, IGeneratorEvent, ICancellableEvent +public class PlayerDeactivatingGeneratorEventArgs : EventArgs, IGeneratorEvent, ICancellableEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerDeactivatingGeneratorEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDeathEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDeathEventArgs.cs index f0de17e1..d58359eb 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDeathEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDeathEventArgs.cs @@ -10,7 +10,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.Death"/> event. /// </summary> -public class PlayerDeathEventArgs : EventArgs, IPlayerEvent, IDamageEvent +public class PlayerDeathEventArgs : EventArgs, IPlayerEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerDeathEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs index 058a64d0..dc5f3e4d 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.DroppingItem"/> event. /// </summary> -public class PlayerDroppingItemEventArgs : EventArgs, IPlayerEvent, ICancellableEvent, IItemEvent +public class PlayerDroppingItemEventArgs : EventArgs, ICancellableEvent, IItemEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerDroppingItemEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDryFiringWeaponEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDryFiringWeaponEventArgs.cs index ebfb6f6b..61d62ffe 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDryFiringWeaponEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDryFiringWeaponEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.DryFiringWeapon"/> event. /// </summary> -public class PlayerDryFiringWeaponEventArgs : EventArgs, IPlayerEvent, IFirearmItemEvent, ICancellableEvent +public class PlayerDryFiringWeaponEventArgs : EventArgs, IFirearmItemEvent, ICancellableEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerDryFiringWeaponEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDyingEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDyingEventArgs.cs index 9daba48d..70dafb23 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDyingEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDyingEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.Dying"/> event. /// </summary> -public class PlayerDyingEventArgs : EventArgs, IPlayerEvent, IDamageEvent, ICancellableEvent +public class PlayerDyingEventArgs : EventArgs, ICancellableEvent, IPlayerEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerDyingEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerEffectUpdatingEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerEffectUpdatingEventArgs.cs index 1b85b948..54c84d53 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerEffectUpdatingEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerEffectUpdatingEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.UpdatingEffect"/> event. /// </summary> -public class PlayerEffectUpdatingEventArgs : EventArgs, IPlayerEvent, ICancellableEvent +public class PlayerEffectUpdatingEventArgs : EventArgs, ICancellableEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerEffectUpdatingEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerFlippingCoinEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerFlippingCoinEventArgs.cs index 0821f5e3..84c1d6ad 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerFlippingCoinEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerFlippingCoinEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.FlippingCoin"/> event. /// </summary> -public class PlayerFlippingCoinEventArgs : EventArgs, IPlayerEvent, ICancellableEvent, ICoinItemEvent +public class PlayerFlippingCoinEventArgs : EventArgs, ICancellableEvent, ICoinItemEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerFlippingCoinEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerHurtEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerHurtEventArgs.cs index 044fd58c..1e1603a7 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerHurtEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerHurtEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.Hurt"/> event. /// </summary> -public class PlayerHurtEventArgs : EventArgs, IPlayerEvent, IDamageEvent +public class PlayerHurtEventArgs : EventArgs, IPlayerEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerHurtEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerHurtingEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerHurtingEventArgs.cs index 30b54a8b..b60f1e24 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerHurtingEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerHurtingEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.Hurting"/> event. /// </summary> -public class PlayerHurtingEventArgs : EventArgs, IPlayerEvent, IDamageEvent, ICancellableEvent +public class PlayerHurtingEventArgs : EventArgs, IPlayerEvent, ICancellableEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerHurtingEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingDoorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingDoorEventArgs.cs index f64b1fb0..012e450f 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingDoorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingDoorEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.InteractingDoor"/> event. /// </summary> -public class PlayerInteractingDoorEventArgs : EventArgs, IPlayerEvent, IDoorEvent, ICancellableEvent +public class PlayerInteractingDoorEventArgs : EventArgs, IDoorEvent, ICancellableEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerInteractingDoorEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBulletHole.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBulletHole.cs index f71337cc..0c9bab18 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBulletHole.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBulletHole.cs @@ -1,5 +1,4 @@ using Decals; -using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using System; using UnityEngine; @@ -9,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.PlacedBulletHole"/> event. /// </summary> -public class PlayerPlacedBulletHoleEventArgs : EventArgs, IPlayerEvent +public class PlayerPlacedBulletHoleEventArgs : EventArgs { /// <summary> /// Initializes a new instance of the <see cref="PlayerPlacedBulletHoleEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerReloadingWeaponEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerReloadingWeaponEventArgs.cs index 79b350f8..f98f9781 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerReloadingWeaponEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerReloadingWeaponEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.ReloadingWeapon"/> event. /// </summary> -public class PlayerReloadingWeaponEventArgs : EventArgs, IPlayerEvent, IFirearmItemEvent, ICancellableEvent +public class PlayerReloadingWeaponEventArgs : EventArgs, IFirearmItemEvent, ICancellableEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerReloadingWeaponEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSpawnedRagdollEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSpawnedRagdollEventArgs.cs index 29fd164d..7ccd0b9f 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSpawnedRagdollEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSpawnedRagdollEventArgs.cs @@ -9,7 +9,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.SpawnedRagdoll"/> event. /// </summary> -public class PlayerSpawnedRagdollEventArgs : EventArgs, IPlayerEvent, IRagdollEvent, IDamageEvent +public class PlayerSpawnedRagdollEventArgs : EventArgs, IPlayerEvent, IRagdollEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerSpawnedRagdollEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSpawningRagdollEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSpawningRagdollEventArgs.cs index 67857a6b..811263ee 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSpawningRagdollEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSpawningRagdollEventArgs.cs @@ -9,7 +9,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.SpawningRagdoll"/> event. /// </summary> -public class PlayerSpawningRagdollEventArgs : EventArgs, IPlayerEvent, IRagdollEvent, IDamageEvent, ICancellableEvent +public class PlayerSpawningRagdollEventArgs : EventArgs, IPlayerEvent, IRagdollEvent, ICancellableEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerSpawningRagdollEventArgs"/> class. diff --git a/LabApi/Events/Arguments/ServerEvents/CassieAnnouncedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/CassieAnnouncedEventArgs.cs index acfa7c80..2aff367f 100644 --- a/LabApi/Events/Arguments/ServerEvents/CassieAnnouncedEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/CassieAnnouncedEventArgs.cs @@ -25,7 +25,7 @@ public CassieAnnouncedEventArgs(string words, bool makeHold, bool makeNoise, boo } /// <summary> - /// Gets sentence which C.A.S.S.I.E. said. + /// Gets sentece which C.A.S.S.I.E. said. /// </summary> public string Words { get; } diff --git a/LabApi/Events/Arguments/ServerEvents/CassieAnnouncingEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/CassieAnnouncingEventArgs.cs index 457ecf6a..0ceb04ad 100644 --- a/LabApi/Events/Arguments/ServerEvents/CassieAnnouncingEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/CassieAnnouncingEventArgs.cs @@ -27,7 +27,7 @@ public CassieAnnouncingEventArgs(string words, bool makeHold, bool makeNoise, bo } /// <summary> - /// Gets or sets sentence which C.A.S.S.I.E. will say. + /// Gets or sets sentece which C.A.S.S.I.E. will say. /// </summary> public string Words { get; set; } diff --git a/LabApi/Events/Arguments/ServerEvents/ExplosionSpawnedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/ExplosionSpawnedEventArgs.cs index 260bce39..fe56ed15 100644 --- a/LabApi/Events/Arguments/ServerEvents/ExplosionSpawnedEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/ExplosionSpawnedEventArgs.cs @@ -4,52 +4,53 @@ using System; using UnityEngine; -namespace LabApi.Events.Arguments.ServerEvents; - -/// <summary> -/// Represents the arguments for the <see cref="Handlers.ServerEvents.ExplosionSpawned"/> event. -/// </summary> -public class ExplosionSpawnedEventArgs : EventArgs, IPlayerEvent +namespace LabApi.Events.Arguments.ServerEvents { /// <summary> - /// Initializes a new instance of the <see cref="ExplosionSpawnedEventArgs"/> class. + /// Represents the arguments for the <see cref="Handlers.ServerEvents.ExplosionSpawned"/> event. /// </summary> - /// <param name="player">The player which caused this explosion.</param> - /// <param name="position">The position of explosion.</param> - /// <param name="settingsReference">The projectile which caused explosion.</param> - /// <param name="explosionType">The type of this explosion.</param> - /// <param name="destroyDoors">Whether the explosion was allowed to destroy doors.</param> - public ExplosionSpawnedEventArgs(ReferenceHub? player, Vector3 position, ExplosionGrenade settingsReference, ExplosionType explosionType, bool destroyDoors) + public class ExplosionSpawnedEventArgs : EventArgs, IPlayerEvent { - Player = Player.Get(player); - Position = position; - Settings = settingsReference; - ExplosionType = explosionType; - DestroyDoors = destroyDoors; - } + /// <summary> + /// Initializes a new instance of the <see cref="ExplosionSpawnedEventArgs"/> class. + /// </summary> + /// <param name="player">The player which caused this explosion.</param> + /// <param name="position">The position of explosion.</param> + /// <param name="settingsReference">The projectile which caused explosion.</param> + /// <param name="explosionType">The type of this explosion.</param> + /// <param name="destroyDoors">Whether the explosion was allowed to destroy doors.</param> + public ExplosionSpawnedEventArgs(ReferenceHub? player, Vector3 position, ExplosionGrenade settingsReference, ExplosionType explosionType, bool destroyDoors) + { + Player = Player.Get(player); + Position = position; + Settings = settingsReference; + ExplosionType = explosionType; + DestroyDoors = destroyDoors; + } - /// <summary> - /// Gets the player which caused this explosion. - /// </summary> - public Player? Player { get; } + /// <summary> + /// Gets the player which caused this explosion. + /// </summary> + public Player? Player { get; } - /// <summary> - /// Gets the position of explosion. - /// </summary> - public Vector3 Position { get; } + /// <summary> + /// Gets the position of explosion. + /// </summary> + public Vector3 Position { get; } - /// <summary> - /// Gets the projectile which will cause explosion. - /// </summary> - public ExplosionGrenade Settings { get; } + /// <summary> + /// Gets the projectile which will cause explosion. + /// </summary> + public ExplosionGrenade Settings { get; } - /// <summary> - /// Gets the type of this explosion. - /// </summary> - public ExplosionType ExplosionType { get; } + /// <summary> + /// Gets the type of this explosion. + /// </summary> + public ExplosionType ExplosionType { get; } - /// <summary> - /// Gets whether the explosion should destroy doors. - /// </summary> - public bool DestroyDoors { get; } + /// <summary> + /// Gets whether the explosion should destroy doors. + /// </summary> + public bool DestroyDoors { get; } + } } diff --git a/LabApi/Events/Arguments/ServerEvents/ExplosionSpawningEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/ExplosionSpawningEventArgs.cs index cf05158c..29638552 100644 --- a/LabApi/Events/Arguments/ServerEvents/ExplosionSpawningEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/ExplosionSpawningEventArgs.cs @@ -4,57 +4,58 @@ using System; using UnityEngine; -namespace LabApi.Events.Arguments.ServerEvents; - -/// <summary> -/// Represents the arguments for the <see cref="Handlers.ServerEvents.ExplosionSpawning"/> event. -/// </summary> -public class ExplosionSpawningEventArgs : EventArgs, IPlayerEvent, ICancellableEvent +namespace LabApi.Events.Arguments.ServerEvents { /// <summary> - /// Initializes a new instance of the <see cref="ExplosionSpawningEventArgs"/> class. + /// Represents the arguments for the <see cref="Handlers.ServerEvents.ExplosionSpawning"/> event. /// </summary> - /// <param name="player">The player which caused this explosion.</param> - /// <param name="position">The position of explosion.</param> - /// <param name="settingsReference">The projectile which will cause the explosion.</param> - /// <param name="explosionType">The type of this explosion.</param> - /// <param name="destroyDoors">Whether the explosion should destroy doors.</param> - public ExplosionSpawningEventArgs(ReferenceHub? player, Vector3 position, ExplosionGrenade settingsReference, ExplosionType explosionType, bool destroyDoors) + public class ExplosionSpawningEventArgs : EventArgs, IPlayerEvent, ICancellableEvent { - Player = Player.Get(player); - Position = position; - Settings = settingsReference; - ExplosionType = explosionType; - DestroyDoors = destroyDoors; - - IsAllowed = true; + /// <summary> + /// Initializes a new instance of the <see cref="ExplosionSpawningEventArgs"/> class. + /// </summary> + /// <param name="player">The player which caused this explosion.</param> + /// <param name="position">The position of explosion.</param> + /// <param name="settingsReference">The projectile which will cause the explosion.</param> + /// <param name="explosionType">The type of this explosion.</param> + /// <param name="destroyDoors">Whether the explosion should destroy doors.</param> + public ExplosionSpawningEventArgs(ReferenceHub? player, Vector3 position, ExplosionGrenade settingsReference, ExplosionType explosionType, bool destroyDoors) + { + Player = Player.Get(player); + Position = position; + Settings = settingsReference; + ExplosionType = explosionType; + DestroyDoors = destroyDoors; + + IsAllowed = true; + } + + /// <summary> + /// Gets or sets the player which caused this explosion. + /// </summary> + public Player? Player { get; set; } + + /// <summary> + /// Gets or sets the position of explosion. + /// </summary> + public Vector3 Position { get; set; } + + /// <summary> + /// Gets or sets the projectile which will cause explosion. + /// </summary> + public ExplosionGrenade Settings { get; set; } + + /// <summary> + /// Gets or sets the type of this explosion. + /// </summary> + public ExplosionType ExplosionType { get; set; } + + /// <summary> + /// Gets or sets whether the explosion should destroy doors. + /// </summary> + public bool DestroyDoors { get; set; } + + /// <inheritdoc/> + public bool IsAllowed { get; set; } } - - /// <summary> - /// Gets or sets the player which caused this explosion. - /// </summary> - public Player? Player { get; set; } - - /// <summary> - /// Gets or sets the position of explosion. - /// </summary> - public Vector3 Position { get; set; } - - /// <summary> - /// Gets or sets the projectile which will cause explosion. - /// </summary> - public ExplosionGrenade Settings { get; set; } - - /// <summary> - /// Gets or sets the type of this explosion. - /// </summary> - public ExplosionType ExplosionType { get; set; } - - /// <summary> - /// Gets or sets whether the explosion should destroy doors. - /// </summary> - public bool DestroyDoors { get; set; } - - /// <inheritdoc/> - public bool IsAllowed { get; set; } } diff --git a/LabApi/Events/Arguments/ServerEvents/WaveRespawnedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/WaveRespawnedEventArgs.cs index 6eb9e131..8b930c55 100644 --- a/LabApi/Events/Arguments/ServerEvents/WaveRespawnedEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/WaveRespawnedEventArgs.cs @@ -1,4 +1,3 @@ -using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using Respawning.Waves; using System; @@ -9,7 +8,7 @@ namespace LabApi.Events.Arguments.ServerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.ServerEvents.WaveRespawned"/> event. /// </summary> -public class WaveRespawnedEventArgs : EventArgs, IRespawnWaveEvent +public class WaveRespawnedEventArgs : EventArgs { /// <summary> /// Initializes a new instance of the <see cref="WaveRespawnedEventArgs"/> class. diff --git a/LabApi/Events/Arguments/ServerEvents/WaveRespawningEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/WaveRespawningEventArgs.cs index 15221cbc..5a0f8683 100644 --- a/LabApi/Events/Arguments/ServerEvents/WaveRespawningEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/WaveRespawningEventArgs.cs @@ -11,7 +11,7 @@ namespace LabApi.Events.Arguments.ServerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.ServerEvents.WaveRespawning"/> event. /// </summary> -public class WaveRespawningEventArgs : EventArgs, IRespawnWaveEvent, ICancellableEvent +public class WaveRespawningEventArgs : EventArgs, ICancellableEvent { /// <summary> /// Initializes a new instance of the <see cref="WaveRespawningEventArgs"/> class. diff --git a/LabApi/Events/Arguments/ServerEvents/WaveTeamSelectedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/WaveTeamSelectedEventArgs.cs index 8544e4ce..3a833c6e 100644 --- a/LabApi/Events/Arguments/ServerEvents/WaveTeamSelectedEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/WaveTeamSelectedEventArgs.cs @@ -1,4 +1,3 @@ -using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using Respawning.Waves; using System; @@ -8,7 +7,7 @@ namespace LabApi.Events.Arguments.ServerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.ServerEvents.WaveTeamSelected"/> event. /// </summary> -public class WaveTeamSelectedEventArgs : EventArgs, IRespawnWaveEvent +public class WaveTeamSelectedEventArgs : EventArgs { /// <summary> /// Initializes a new instance of the <see cref="WaveTeamSelectedEventArgs"/> class. diff --git a/LabApi/Events/Arguments/ServerEvents/WaveTeamSelectingEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/WaveTeamSelectingEventArgs.cs index f44dd7aa..d3ba16e1 100644 --- a/LabApi/Events/Arguments/ServerEvents/WaveTeamSelectingEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/WaveTeamSelectingEventArgs.cs @@ -1,5 +1,4 @@ using LabApi.Events.Arguments.Interfaces; -using LabApi.Features.Wrappers; using Respawning; using Respawning.Waves; using System; @@ -9,7 +8,7 @@ namespace LabApi.Events.Arguments.ServerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.ServerEvents.WaveTeamSelecting"/> event. /// </summary> -public class WaveTeamSelectingEventArgs : EventArgs, IRespawnWaveEvent, ICancellableEvent +public class WaveTeamSelectingEventArgs : EventArgs, ICancellableEvent { /// <summary> /// Initializes a new instance of the <see cref="WaveTeamSelectingEventArgs"/> class. @@ -18,14 +17,14 @@ public class WaveTeamSelectingEventArgs : EventArgs, IRespawnWaveEvent, ICancell public WaveTeamSelectingEventArgs(SpawnableWaveBase wave) { IsAllowed = true; - Wave = RespawnWaves.Get(wave); + Wave = wave; } /// <summary> /// Gets or sets the spawnable wave. See <see cref="SpawnableWaveBase"/> and its subclasses.<br/> /// Use the <see cref="WaveManager.Waves"/> to set it to a different value. /// </summary> - public RespawnWave Wave { get; set; } + public SpawnableWaveBase Wave { get; set; } /// <inheritdoc /> public bool IsAllowed { get; set; } diff --git a/LabApi/Features/Enums/SpeakerToyMixerGroup.cs b/LabApi/Features/Enums/SpeakerToyMixerGroup.cs deleted file mode 100644 index 0d10c98e..00000000 --- a/LabApi/Features/Enums/SpeakerToyMixerGroup.cs +++ /dev/null @@ -1,84 +0,0 @@ -using LabApi.Features.Wrappers; - -namespace LabApi.Features.Enums; - -/// <summary> -/// Represents the different types of audio mixer groups that can be assigned to a <see cref="SpeakerToy"/>. -/// Audio mixers group starting with Sfx are effected by the player Sound effect volume while ones with Vc are effected by Voice chat volume. -/// </summary> -public enum SpeakerToyMixerGroup -{ - /// <summary> - /// Mixer group used for general sound effects audio. - /// No audio effects are applied in this group. - /// </summary> - SfxGeneral, - - /// <summary> - /// Mixer group used for CASSIE related broadcasts. - /// Same audio effects used by CASSIE are applied. - /// </summary> - SfxCassie, - - /// <summary> - /// Mixer group used for weapons/gun shots. - /// </summary> - SfxWeapons, - - /// <summary> - /// Mixer group used to apply reverb. - /// </summary> - SfxReverbNoDucking, - - /// <summary> - /// Mixer group used to apply reverb and audio ducking. - /// </summary> - SfxReverbDucking, - - /// <summary> - /// Mixer group used for the games backgroud music. - /// </summary> - SfxMusic, - - /// <summary> - /// Mixer group used for general voice chat audio. - /// No audio effects are applied in this group. - /// </summary> - VcGeneral, - - /// <summary> - /// Mixer group used for intercom voice broadcasts. - /// Same effects used by the intercom are applied. - /// </summary> - VcIntercom, - - /// <summary> - /// Mixer group used for radio voice chat. - /// Same effects used by radio char are applied. - /// </summary> - VcRadio, - - /// <summary> - /// One of the two mixer groups used by proximity chat. - /// This is the dry unfiltered part of the proximity voice. - /// </summary> - /// <remarks> - /// True proximity chat cannot be replicated by a speaker toy. - /// </remarks> - VcProximity, - - /// <summary> - /// One of the two mixer group used by proximity chat. - /// This is the wet reverberated part of the proximity voice. - /// </summary> - /// <remarks> - /// True proximity chat cannot be replicated by a speaker toy. - /// </remarks> - VcProximityReverb, - - /// <summary> - /// Mixer group used by SCP-079 speakers. - /// Same effects used by SCP-079 speakers are applied. - /// </summary> - VcScp079 -} \ No newline at end of file diff --git a/LabApi/Features/Wrappers/AdminToys/AdminToy.cs b/LabApi/Features/Wrappers/AdminToys/AdminToy.cs index 63326be9..507168bd 100644 --- a/LabApi/Features/Wrappers/AdminToys/AdminToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/AdminToy.cs @@ -130,7 +130,7 @@ public Vector3 Scale /// Gets or sets the parent of the admin toy. /// </summary> /// <remarks> - /// If the parent object contains a <see cref="NetworkIdentity"/> component or one of the objects higher up in the parents hierarchy has a <see cref="NetworkIdentity"/> component and it has been <see cref="NetworkServer.Spawn(GameObject, GameObject)"/> the parent is synced with the client. + /// If the parent object contains a <see cref="NetworkIdentity"/> component and has been <see cref="NetworkServer.Spawn(GameObject, GameObject)"/> the parent is synced with the client. /// <para> /// Can be used even if <see cref="IsStatic"/> is true. /// When changing parent the toys relative <see cref="Position"/>, <see cref="Rotation"/> and <see cref="Scale"/> are retained. diff --git a/LabApi/Features/Wrappers/AdminToys/SpeakerToy.cs b/LabApi/Features/Wrappers/AdminToys/SpeakerToy.cs index 9c024b71..78c280d5 100644 --- a/LabApi/Features/Wrappers/AdminToys/SpeakerToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/SpeakerToy.cs @@ -1,5 +1,4 @@ using LabApi.Features.Audio; -using LabApi.Features.Enums; using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; @@ -101,19 +100,6 @@ public float MaxDistance set => Base.NetworkMaxDistance = value; } - /// <summary> - /// Gets or sets the audio mixer group used as output by the speaker. - /// By default this is set to <see cref="SpeakerToyMixerGroup.SfxReverbDucking"/>. - /// </summary> - /// <remarks> - /// Each <see cref="SpeakerToyMixerGroup"/> has a different set of effects or is attenuated differently by the players audio settings. - /// </remarks> - public SpeakerToyMixerGroup OutputMixer - { - get => (SpeakerToyMixerGroup)Base.OutputMixerId; - set => Base.NetworkOutputMixerId = (byte)value; - } - /// <summary> /// Gets or sets the current sample position of the playback head. /// </summary> diff --git a/LabApi/Features/Wrappers/AdminToys/TextToy.cs b/LabApi/Features/Wrappers/AdminToys/TextToy.cs index fdb88fe3..f2469f5e 100644 --- a/LabApi/Features/Wrappers/AdminToys/TextToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/TextToy.cs @@ -64,18 +64,6 @@ public Vector2 DisplaySize set => Base.DisplaySize = value; } - /// <summary> - /// Gets or sets whether or not the text should render as apart of the UI. - /// </summary> - /// <remarks> - /// When rendering as apart of the UI, text is not effected by any post processing effects that can blur/distort it and it can render on top of the players view model if placed correctly. - /// </remarks> - public bool RenderAsUserInterface - { - get => Base.RenderAsUserInterface; - set => Base.RenderAsUserInterface = value; - } - /// <summary> /// Gets the arguments used while formatting the <see cref="TextFormat"/>.<br/> /// Missing arguments for <see cref="TextFormat"/> are not replaced and any extra arguments are ignored. From 3d91fdb8f9091e0cb87b7b0bdda691aacc4f79ce Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Sun, 29 Jun 2025 21:49:51 +0930 Subject: [PATCH 038/215] applied review changes --- LabApi/Features/Wrappers/Players/Player.cs | 23 +++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/LabApi/Features/Wrappers/Players/Player.cs b/LabApi/Features/Wrappers/Players/Player.cs index e12dcc02..ab1dd81e 100644 --- a/LabApi/Features/Wrappers/Players/Player.cs +++ b/LabApi/Features/Wrappers/Players/Player.cs @@ -162,7 +162,7 @@ internal Player(ReferenceHub referenceHub) /// <summary> /// Gets whether the player was destroyed. /// </summary> - public bool IsDestroyed => ReferenceHub == null; + public bool IsDestroyed => !ReferenceHub; /// <summary> /// Gets whether the player is the host or server. @@ -492,11 +492,6 @@ public Item? CurrentItem } } - /// <summary> - /// Gets the current <see cref="BodyArmorItem"/> being used. - /// </summary> - public BodyArmorItem? CurrentArmor => BodyArmorUtils.TryGetBodyArmor(Inventory, out BodyArmor baseArmor) ? BodyArmorItem.Get(baseArmor) : null; - /// <summary> /// Gets the player's currently active <see cref="StatusEffectBase">status effects</see>. /// </summary> @@ -1306,7 +1301,7 @@ public List<Pickup> DropAllItems() /// <returns><see langword="true"/> if found, otherwise <see langword="false"/>.</returns> public bool TryGetItem(ItemType type, [NotNullWhen(true)] out Item? item) { - if(Inventory.TryGetInventoryItem(type, out ItemBase itemBase)) + if (Inventory.TryGetInventoryItem(type, out ItemBase itemBase)) { item = Item.Get(itemBase); return true; @@ -1316,6 +1311,20 @@ public bool TryGetItem(ItemType type, [NotNullWhen(true)] out Item? item) return false; } + /// <summary> + /// Tries to get the current body armor being worn. + /// </summary> + /// <param name="bodyArmor">The found body armor or <see langword="null"/> if none is being worn.</param> + /// <returns><see langword="true"/> if body armor was found, otherwise <see langword="false"/>.</returns> + public bool TryGetBodyArmor([NotNullWhen(true)] out BodyArmorItem? bodyArmor) + { + bodyArmor = null; + if (BodyArmorUtils.TryGetBodyArmor(Inventory, out BodyArmor baseArmor)) + bodyArmor = BodyArmorItem.Get(baseArmor); + + return bodyArmor != null; + } + /// <summary> /// Drops ammo of the specified type from the player's inventory. /// </summary> From 9419eddc44a0ceba68f0623033e00a64274ffc28 Mon Sep 17 00:00:00 2001 From: brayden-dowson <88667957+brayden-dowson@users.noreply.github.com> Date: Thu, 3 Jul 2025 05:55:24 +0930 Subject: [PATCH 039/215] Remote admin events + Ragdoll spawning event fix + Acheivement events + Escape modding (#257) * init * escape rework * moved private fields * added achievements bool to server and removed receiving achievement event * fix --- .../LogAll/LogPlugin/MyCustomEventsHandler.cs | 55 +++++++++ .../PlayerEvents/PlayerEscapedEventArgs.cs | 9 +- .../PlayerEvents/PlayerEscapingEventArgs.cs | 9 +- .../PlayerRaPlayerListAddedPlayerEventArgs.cs | 43 +++++++ ...PlayerRaPlayerListAddingPlayerEventArgs.cs | 79 +++++++++++++ .../PlayerReceivedAchievementEventArgs.cs | 34 ++++++ .../PlayerRequestedCustomRaInfoEventArgs.cs | 108 ++++++++++++++++++ .../PlayerRequestedRaPlayerInfoEventArgs.cs | 76 ++++++++++++ .../PlayerRequestedRaPlayerListEventArgs.cs | 36 ++++++ .../PlayerRequestedRaPlayersInfoEventArgs.cs | 81 +++++++++++++ .../PlayerRequestingRaPlayerInfoEventArgs.cs | 69 +++++++++++ .../PlayerRequestingRaPlayerListEventArgs.cs | 70 ++++++++++++ .../PlayerRequestingRaPlayersInfoEventArgs.cs | 73 ++++++++++++ .../PlayerSpawningRagdollEventArgs.cs | 14 ++- .../Handlers/PlayerEvents.EventHandlers.cs | 49 ++++++++ LabApi/Features/Wrappers/Facility/Map.cs | 34 +++++- LabApi/Features/Wrappers/Players/Server.cs | 20 +++- 17 files changed, 849 insertions(+), 10 deletions(-) create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerRaPlayerListAddedPlayerEventArgs.cs create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerRaPlayerListAddingPlayerEventArgs.cs create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerReceivedAchievementEventArgs.cs create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerRequestedCustomRaInfoEventArgs.cs create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerRequestedRaPlayerInfoEventArgs.cs create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerRequestedRaPlayerListEventArgs.cs create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerRequestedRaPlayersInfoEventArgs.cs create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerRequestingRaPlayerInfoEventArgs.cs create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerRequestingRaPlayerListEventArgs.cs create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerRequestingRaPlayersInfoEventArgs.cs diff --git a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs index 25d0f741..10180899 100644 --- a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs +++ b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs @@ -468,6 +468,61 @@ public override void OnPlayerUpdatedEffect(PlayerEffectUpdatedEventArgs ev) Logger.Info($"{nameof(OnPlayerUpdatedEffect)} triggered by {ev.Player.UserId}"); } + public override void OnPlayerRaPlayerListAddedPlayer(PlayerRaPlayerListAddedPlayerEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerRaPlayerListAddedPlayer)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerRaPlayerListAddingPlayer(PlayerRaPlayerListAddingPlayerEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerRaPlayerListAddingPlayer)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerReceivedAchievement(PlayerReceivedAchievementEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerReceivedAchievement)} triggered by {ev.Player?.UserId ?? "unknown"}"); + } + + public override void OnPlayerReceivingAchievement(PlayerReceivingAchievementEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerReceivingAchievement)} triggered by {ev.Player?.UserId ?? "unknown"}"); + } + + public override void OnPlayerRequestedCustomRaInfo(PlayerRequestedCustomRaInfoEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerRequestedCustomRaInfo)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerRequestedRaPlayerInfo(PlayerRequestedRaPlayerInfoEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerRequestedRaPlayerInfo)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerRequestedRaPlayerList(PlayerRequestedRaPlayerListEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerRequestedRaPlayerList)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerRequestedRaPlayersInfo(PlayerRequestedRaPlayersInfoEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerRequestedRaPlayersInfo)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerRequestingRaPlayerInfo(PlayerRequestingRaPlayerInfoEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerRequestingRaPlayerInfo)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerRequestingRaPlayerList(PlayerRequestingRaPlayerListEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerRequestingRaPlayerList)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerRequestingRaPlayersInfo(PlayerRequestingRaPlayersInfoEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerRequestingRaPlayersInfo)} triggered by {ev.Player.UserId}"); + } + //public override void OnPlayerReceivingVoiceMessage(PlayerReceivingVoiceMessageEventArgs ev) //{ // Logger.Info($"{nameof(OnPlayerReceivingVoiceMessage)} triggered by {ev.Player.UserId}"); diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerEscapedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerEscapedEventArgs.cs index bd427268..0d9268ec 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerEscapedEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerEscapedEventArgs.cs @@ -2,6 +2,7 @@ using LabApi.Features.Wrappers; using PlayerRoles; using System; +using UnityEngine; using static Escape; namespace LabApi.Events.Arguments.PlayerEvents; @@ -17,11 +18,12 @@ public class PlayerEscapedEventArgs : EventArgs, IPlayerEvent /// <param name="player">The player who escaped.</param> /// <param name="newRole">The new role.</param> /// <param name="escapeScenarioType">The scenario of the escape.</param> - public PlayerEscapedEventArgs(ReferenceHub player, RoleTypeId newRole, EscapeScenarioType escapeScenarioType) + public PlayerEscapedEventArgs(ReferenceHub player, RoleTypeId newRole, EscapeScenarioType escapeScenarioType, Bounds escapeZone) { Player = Player.Get(player); NewRole = newRole; EscapeScenarioType = escapeScenarioType; + EscapeZone = escapeZone; } /// <summary> @@ -38,4 +40,9 @@ public PlayerEscapedEventArgs(ReferenceHub player, RoleTypeId newRole, EscapeSce /// Escape scenario of the player. /// </summary> public EscapeScenarioType EscapeScenarioType { get; } + + /// <summary> + /// The bounds of the escape zone that was triggered. + /// </summary> + public Bounds EscapeZone { get; } } \ No newline at end of file diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerEscapingEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerEscapingEventArgs.cs index 1634f83f..52e3dae7 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerEscapingEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerEscapingEventArgs.cs @@ -2,6 +2,7 @@ using LabApi.Features.Wrappers; using PlayerRoles; using System; +using UnityEngine; using static Escape; namespace LabApi.Events.Arguments.PlayerEvents; @@ -17,12 +18,13 @@ public class PlayerEscapingEventArgs : EventArgs, IPlayerEvent, ICancellableEven /// <param name="player">The player who is escaping.</param> /// <param name="newRole">The new role that is set after escape.</param> /// <param name="escapeScenario">The scenario of the escape.</param> - public PlayerEscapingEventArgs(ReferenceHub player, RoleTypeId newRole, EscapeScenarioType escapeScenario) + public PlayerEscapingEventArgs(ReferenceHub player, RoleTypeId newRole, EscapeScenarioType escapeScenario, Bounds escapeZone) { IsAllowed = true; Player = Player.Get(player); NewRole = newRole; EscapeScenario = escapeScenario; + EscapeZone = escapeZone; } /// <summary> @@ -40,6 +42,11 @@ public PlayerEscapingEventArgs(ReferenceHub player, RoleTypeId newRole, EscapeSc /// </summary> public EscapeScenarioType EscapeScenario { get; set; } + /// <summary> + /// The bounds of the escape zone that was triggered. + /// </summary> + public Bounds EscapeZone { get; } + /// <inheritdoc /> public bool IsAllowed { get; set; } } \ No newline at end of file diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerRaPlayerListAddedPlayerEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerRaPlayerListAddedPlayerEventArgs.cs new file mode 100644 index 00000000..ecc2bda7 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerRaPlayerListAddedPlayerEventArgs.cs @@ -0,0 +1,43 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using System.Text; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.RaPlayerListAddedPlayer"/> event. +/// </summary> +public class PlayerRaPlayerListAddedPlayerEventArgs : EventArgs, IPlayerEvent, ITargetEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="PlayerRaPlayerListAddedPlayerEventArgs"/> class. + /// </summary> + /// <param name="requesterHub">The <see cref="CommandSender"/> instance of the player that made the request for the RA player list.</param> + /// <param name="targetHub">The <see cref="ReferenceHub"/> component of the player that is being added to the RA player list.</param> + /// <param name="builder">The <see cref="StringBuilder"/> used to build the RA player list item.</param> + public PlayerRaPlayerListAddedPlayerEventArgs(CommandSender requesterHub, ReferenceHub targetHub, StringBuilder builder) + { + Player = Player.Get(requesterHub)!; + Target = Player.Get(targetHub); + TargetBuilder = builder; + } + + /// <summary> + /// The player that requested the RA player list. + /// </summary> + public Player Player { get; } + + /// <summary> + /// The player that was added to the RA player list. + /// </summary> + public Player Target { get; } + + /// <summary> + /// The <see cref="StringBuilder"/> used to construct the RA player list item for the <see cref="Target"/>. + /// </summary> + /// <remarks> + /// String builder is not empty in this event and contains the RA list item for the <see cref="Target"/>. + /// </remarks> + public StringBuilder TargetBuilder { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerRaPlayerListAddingPlayerEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerRaPlayerListAddingPlayerEventArgs.cs new file mode 100644 index 00000000..c719f603 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerRaPlayerListAddingPlayerEventArgs.cs @@ -0,0 +1,79 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using System.Text; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.RaPlayerListAddingPlayer"/> event. +/// </summary> +public class PlayerRaPlayerListAddingPlayerEventArgs : EventArgs, IPlayerEvent, ITargetEvent, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="PlayerRaPlayerListAddingPlayerEventArgs"/> class. + /// </summary> + /// <param name="commandSender">The <see cref="CommandSender"/> instance of the player that made the request for the RA player list.</param> + /// <param name="targetHub">The <see cref="ReferenceHub"/> component of the player that is being added to the RA player list.</param> + /// <param name="builder">The <see cref="StringBuilder"/> used to build the RA player list item.</param> + /// <param name="prefix">The prefix string for the RA list item.</param> + /// <param name="inOverwatch">Whether to include the overwatch icon in the list item.</param> + /// <param name="isMuted">Whether to include the is muted icon and link in the list item.</param> + /// <param name="body">The body string for the Ra list item.</param> + public PlayerRaPlayerListAddingPlayerEventArgs(CommandSender commandSender, ReferenceHub targetHub, + StringBuilder builder, string prefix, bool inOverwatch, bool isMuted, string body) + { + Player = Player.Get(commandSender)!; + Target = Player.Get(targetHub); + TargetBuilder = builder; + Prefix = prefix; + InOverwatch = inOverwatch; + IsMuted = isMuted; + Body = body; + IsAllowed = true; + } + + /// <summary> + /// The player that requested the RA player list. + /// </summary> + public Player Player { get; } + + /// <summary> + /// The player being added to the RA player list. + /// </summary> + public Player Target { get; } + + /// <summary> + /// The <see cref="StringBuilder"/> used to construct the RA player list item for the <see cref="Target"/>. + /// </summary> + /// <remarks> + /// String builder is empty in this event. + /// </remarks> + public StringBuilder TargetBuilder { get; } + + /// <summary> + /// Gets or sets the RA player list item prefix. + /// Can contain a RA badge and/or link for whether the <see cref="Target"/> is one of either a Dummy, has RemoteAdminGlobalAccess, is NorthwoodStaff, or has RemoteAdmin. + /// Otherwise this is <see cref="string.Empty"/>. + /// </summary> + public string Prefix { get; set; } + + /// <summary> + /// Gets or sets whether the <see cref="Target"/> appears to be in overwatch on the RA player list. + /// </summary> + public bool InOverwatch { get; set; } + + /// <summary> + /// Gets or sets whether the <see cref="Target"/> appears to be muted on the RA player list. + /// </summary> + public bool IsMuted { get; set; } + + /// <summary> + /// Gets or sets the RA player list item body. + /// Contains the color tags, identifier as the <see cref="Player.PlayerId"/> and <see cref="NicknameSync.CombinedName"/> of the <see cref="Target"/>. + /// </summary> + public string Body { get; set; } + + /// <inheritdoc /> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerReceivedAchievementEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerReceivedAchievementEventArgs.cs new file mode 100644 index 00000000..0f9fcdd2 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerReceivedAchievementEventArgs.cs @@ -0,0 +1,34 @@ +using Achievements; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using Mirror; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the argument for the <see cref="Handlers.PlayerEvents.ReceivedAchievement"/> event. +/// </summary> +public class PlayerReceivedAchievementEventArgs : EventArgs, IPlayerEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="PlayerReceivedAchievementEventArgs"/> class. + /// </summary> + /// <param name="identity">The <see cref="NetworkIdentity"/> component of the player.</param> + /// <param name="name">The <see cref="AchievementName"/> being granted.</param> + public PlayerReceivedAchievementEventArgs(NetworkIdentity identity, AchievementName name) + { + Player = Player.Get(identity); + Achievement = name; + } + + /// <summary> + /// The player that getting the achievement. + /// </summary> + public Player? Player { get; } + + /// <summary> + /// The <see cref="AchievementName"/> of the achievement. + /// </summary> + public AchievementName Achievement { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedCustomRaInfoEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedCustomRaInfoEventArgs.cs new file mode 100644 index 00000000..7d21506a --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedCustomRaInfoEventArgs.cs @@ -0,0 +1,108 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.RequestedCustomRaInfo"/> event. +/// </summary> +public class PlayerRequestedCustomRaInfoEventArgs : EventArgs, IPlayerEvent +{ + /// <summary> + /// Max number of clipboard links that can be created with <see cref="SetClipboardText(string, string, byte)"/>. + /// </summary> + public const int MaxClipboardCount = 3; + + /// <summary> + /// Initializes a new instance of the <see cref="PlayerRequestedCustomRaInfoEventArgs"/> class. + /// </summary> + /// <param name="commandSender">The <see cref="CommandSender"/> instance of the player making the request.</param> + /// <param name="selectionArgs">The request arguments.</param> + /// <param name="isSensitiveInfo">Whether the info being requested is sensitive.</param> + /// <param name="infoBuilder">The <see cref="StringBuilder"/> use to build the response.</param> + public PlayerRequestedCustomRaInfoEventArgs(CommandSender commandSender, ArraySegment<string> selectionArgs, + bool isSensitiveInfo, StringBuilder infoBuilder) + { + Player = Player.Get(commandSender)!; + SelectedIdentifiers = selectionArgs.First().Split("."); + IsSensitiveInfo = isSensitiveInfo; + InfoBuilder = infoBuilder; + } + + /// <summary> + /// The player that made the request. + /// </summary> + public Player Player { get; } + + /// <summary> + /// Array of identifiers selected by the player. + /// Identifiers come from items in the RA player list that have been placed by plugins <see cref="Handlers.PlayerEvents.RequestingRaPlayerList"/>. + /// </summary> + public string[] SelectedIdentifiers { get; } + + /// <summary> + /// Gets whether the <see cref="Player"/> requested sensitive info. + /// </summary> + public bool IsSensitiveInfo { get; } + + /// <summary> + /// Gets the <see cref="StringBuilder"/> used to construct the response message. + /// </summary> + public StringBuilder InfoBuilder { get; } + + private string[]? clipboardTexts = null; + + /// <summary> + /// Creates a clipboard link for the RA. + /// </summary> + /// <remarks> + /// Usage <c>ev.InfoBuilder.Append(ev.SetClipboardText("Click Me", "Text to copy to clipboard on click", 0))</c> + /// </remarks> + /// <param name="linkText">Text to display as the link.</param> + /// <param name="clipboardText">Text to copy to the clipboard when clicking on the link.</param> + /// <param name="id">The id of the clipboard, must be between 0 and <see cref="MaxClipboardCount"/>.</param> + /// <returns>The formated clipboard link text.</returns> + public string SetClipboardText(string linkText, string clipboardText, byte id) + { + if (id >= MaxClipboardCount) + throw new ArgumentOutOfRangeException(nameof(id), id, $"id must be between 0 and {MaxClipboardCount}"); + + clipboardTexts ??= new string[MaxClipboardCount]; + clipboardTexts[id] = clipboardText; + + return $"<link={LinkIdForClipboardId(id)}>{linkText}</link>"; + } + + /// <summary> + /// Tries to get clipboard text for the specific id. + /// </summary> + /// <param name="id">The id associated with the clipboard text.</param> + /// <param name="text">The found text, otherwise <see langword="null"/>.</param> + /// <returns><see langword="true"/> if set and not empty, otherwise <see langword="false"/>.</returns> + /// <exception cref="ArgumentOutOfRangeException"></exception> + public bool TryGetClipboardText(byte id, [NotNullWhen(true)] out string? text) + { + if (id >= MaxClipboardCount) + throw new ArgumentOutOfRangeException(nameof(id), id, $"id must be between 0 and {MaxClipboardCount}"); + + text = null; + + if (clipboardTexts == null) + return false; + + text = clipboardTexts[id]; + return !string.IsNullOrEmpty(text); + } + + private string LinkIdForClipboardId(byte id) => id switch + { + 0 => "CP_ID", + 1 => "CP_IP", + 2 => "CP_USERID", + _ => throw new ArgumentOutOfRangeException(nameof(id), id, $"id must be between 0 and {MaxClipboardCount}") + }; +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedRaPlayerInfoEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedRaPlayerInfoEventArgs.cs new file mode 100644 index 00000000..6320199b --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedRaPlayerInfoEventArgs.cs @@ -0,0 +1,76 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using System.Text; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.RequestedRaPlayerInfo"/> event. +/// </summary> +public class PlayerRequestedRaPlayerInfoEventArgs : EventArgs, IPlayerEvent, ITargetEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="PlayerRequestedRaPlayerInfoEventArgs"/> class. + /// </summary> + /// <param name="commandSender">The <see cref="CommandSender"/> instance of the player making the request.</param> + /// <param name="targetHub">The <see cref="ReferenceHub"/> component of the selected target.</param> + /// <param name="isSensitiveInfo">Whether the info being requested is sensitive.</param> + /// <param name="hasUserIdPerms">Whether the player has perms to view the user id of the target.</param> + /// <param name="infoBuilder">The <see cref="StringBuilder"/> used to construct the response message.</param> + /// <param name="idBuilder">The <see cref="StringBuilder"/> used to construct the clipboard text of the targets player id.</param> + /// <param name="ipBuilder">The <see cref="StringBuilder"/> used to construct the clipboard text of the targets ip address.</param> + /// <param name="userIdBuilder">The <see cref="StringBuilder"/> used to construct the clipboard text of the targets user id.</param> + public PlayerRequestedRaPlayerInfoEventArgs(CommandSender commandSender, ReferenceHub targetHub, bool isSensitiveInfo, + bool hasUserIdPerms, StringBuilder infoBuilder, StringBuilder idBuilder, StringBuilder ipBuilder, StringBuilder userIdBuilder) + { + Player = Player.Get(commandSender)!; + Target = Player.Get(targetHub); + IsSensitiveInfo = isSensitiveInfo; + HasUserIdPerms = hasUserIdPerms; + InfoBuilder = infoBuilder; + PlayerIdBuilder = idBuilder; + IpBuilder = ipBuilder; + UserIdBuilder = userIdBuilder; + } + + /// <summary> + /// The player that made the request. + /// </summary> + public Player Player { get; } + + /// <summary> + /// The target player selected. + /// </summary> + public Player Target { get; } + + /// <summary> + /// Whether the <see cref="Player"/> requested sensitive info. + /// </summary> + public bool IsSensitiveInfo { get; } + + /// <summary> + /// Whether the <see cref="Player"/> has permission to view the user id of the <see cref="Target"/>. + /// </summary> + public bool HasUserIdPerms { get; } + + /// <summary> + /// The <see cref="StringBuilder"/> used to construct the response message. + /// </summary> + public StringBuilder InfoBuilder { get; } + + /// <summary> + /// The <see cref="StringBuilder"/> used to construct the clipboard text of the targets player id. + /// </summary> + public StringBuilder PlayerIdBuilder { get; } + + /// <summary> + /// The <see cref="StringBuilder"/> used to construct the clipboard text of the targets ip address. + /// </summary> + public StringBuilder IpBuilder { get; } + + /// <summary> + /// The <see cref="StringBuilder"/> used to construct the clipboard text of the targets user id. + /// </summary> + public StringBuilder UserIdBuilder { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedRaPlayerListEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedRaPlayerListEventArgs.cs new file mode 100644 index 00000000..319ad882 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedRaPlayerListEventArgs.cs @@ -0,0 +1,36 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using System.Text; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.RequestedRaPlayerList"/> event. +/// </summary> +public class PlayerRequestedRaPlayerListEventArgs : EventArgs, IPlayerEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="PlayerRequestedRaPlayerListEventArgs"/> class. + /// </summary> + /// <param name="commandSender">The <see cref="CommandSender"/> instance of the player that made the request for the RA player list.</param> + /// <param name="builder">The <see cref="StringBuilder"/> used to build the RA player list.</param> + public PlayerRequestedRaPlayerListEventArgs(CommandSender commandSender, StringBuilder builder) + { + Player = Player.Get(commandSender)!; + ListBuilder = builder; + } + + /// <summary> + /// The player that requested the RA player list. + /// </summary> + public Player Player { get; } + + /// <summary> + /// The <see cref="StringBuilder"/> used to construct the RA player list. + /// </summary> + /// <remarks> + /// String builder is not empty in this event and contains the RA list. + /// </remarks> + public StringBuilder ListBuilder { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedRaPlayersInfoEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedRaPlayersInfoEventArgs.cs new file mode 100644 index 00000000..376549d3 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedRaPlayersInfoEventArgs.cs @@ -0,0 +1,81 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.RequestedRaPlayersInfo"/> event. +/// </summary> +public class PlayerRequestedRaPlayersInfoEventArgs : EventArgs, IPlayerEvent +{ + private IEnumerable<ReferenceHub> _targets; + + /// <summary> + /// Initializes a new instance of the <see cref="PlayerRequestedRaPlayersInfoEventArgs"/> class. + /// </summary> + /// <param name="commandSender">The <see cref="CommandSender"/> instance of the player making the request.</param> + /// <param name="targets">The reference hub components of the targets selected in the request.</param> + /// <param name="isSensitiveInfo">Whether the info being requested is sensitive.</param> + /// <param name="hasUserIdPerms">Whether the player has perms to view the user ids of the targets.</param> + /// <param name="infoBuilder">The <see cref="StringBuilder"/> used to build the response.</param> + /// <param name="idBuilder">The <see cref="StringBuilder"/> used to build the clipboard text for the targets ids.</param> + /// <param name="ipBuilder">The <see cref="StringBuilder"/> used to build the clipboard text for the targets IPs.</param> + /// <param name="userIdBuilder">The <see cref="StringBuilder"/> used to build the clipboard text for the targets user ids.</param> + public PlayerRequestedRaPlayersInfoEventArgs(CommandSender commandSender, IEnumerable<ReferenceHub> targets, + bool isSensitiveInfo, bool hasUserIdPerms, StringBuilder infoBuilder, StringBuilder idBuilder, + StringBuilder ipBuilder, StringBuilder userIdBuilder) + { + Player = Player.Get(commandSender)!; + IsSensitiveInfo = isSensitiveInfo; + HasUserIdPerms = hasUserIdPerms; + InfoBuilder = infoBuilder; + PlayerIdBuilder = idBuilder; + IpBuilder = ipBuilder; + UserIdBuilder = userIdBuilder; + _targets = targets; + } + + /// <summary> + /// The player that made the request. + /// </summary> + public Player Player { get; } + + /// <summary> + /// The target players selected. + /// </summary> + public IEnumerable<Player> Targets => _targets.Select(Player.Get)!; + + /// <summary> + /// Gets whether the <see cref="Player"/> requested sensitive info. + /// </summary> + public bool IsSensitiveInfo { get; } + + /// <summary> + /// Gets whether the <see cref="Player"/> has perms to view the <see cref="Player.UserId"/> of the <see cref="Targets"/>. + /// </summary> + public bool HasUserIdPerms { get; } + + /// <summary> + /// Gets the <see cref="StringBuilder"/> used to construct the response message. + /// </summary> + public StringBuilder InfoBuilder { get; } + + /// <summary> + /// Gets the <see cref="StringBuilder"/> used to construct the clipboard text for the <see cref="Targets"/> <see cref="Player.PlayerId"/>. + /// </summary> + public StringBuilder PlayerIdBuilder { get; } + + /// <summary> + /// Gets the <see cref="StringBuilder"/> used to construct the clipboard text for the <see cref="Targets"/> <see cref="Player.IpAddress"/>. + /// </summary> + public StringBuilder IpBuilder { get; } + + /// <summary> + /// Gets the <see cref="StringBuilder"/> used to construct the clipboard text for the <see cref="Targets"/> <see cref="Player.UserId"/>. + /// </summary> + public StringBuilder UserIdBuilder { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerRequestingRaPlayerInfoEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestingRaPlayerInfoEventArgs.cs new file mode 100644 index 00000000..e36d23e3 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestingRaPlayerInfoEventArgs.cs @@ -0,0 +1,69 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using System.Text; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.RequestingRaPlayerInfo"/> event. +/// </summary> +public class PlayerRequestingRaPlayerInfoEventArgs : EventArgs, IPlayerEvent, ITargetEvent, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="PlayerRequestingRaPlayerInfoEventArgs"/> class. + /// </summary> + /// <param name="commandSender">THe <see cref="CommandSender"/> instance of the player making the request.</param> + /// <param name="targetHub">The <see cref="ReferenceHub"/> component of the target player.</param> + /// <param name="isSensitiveInfo">Whether the info being requested is sensitive.</param> + /// <param name="hasSensitiveInfoPerms">Whether the player has perms to view sensitive info.</param> + /// <param name="hasUserIdPerms">Whether the player has perms to view the targets user id.</param> + /// <param name="infoBuilder">The <see cref="StringBuilder"/> used to construct the response message.</param> + public PlayerRequestingRaPlayerInfoEventArgs(CommandSender commandSender, ReferenceHub targetHub, + bool isSensitiveInfo, bool hasSensitiveInfoPerms, bool hasUserIdPerms, StringBuilder infoBuilder) + { + Player = Player.Get(commandSender)!; + Target = Player.Get(targetHub); + IsSensitiveInfo = isSensitiveInfo; + HasSensitiveInfoPerms = hasSensitiveInfoPerms; + HasUserIdPerms = hasUserIdPerms; + InfoBuilder = infoBuilder; + IsAllowed = true; + } + + /// <summary> + /// The player than made the request. + /// </summary> + public Player Player { get; } + + /// <summary> + /// The target player selected. + /// </summary> + public Player Target { get; } + + /// <summary> + /// Gets or sets whether the player is requesting sensitive info. + /// </summary> + public bool IsSensitiveInfo { get; set; } + + /// <summary> + /// Gets or sets whether the player has permissions to view sensitive info. + /// </summary> + /// <remarks> + /// If <see cref="IsSensitiveInfo"/> is <see langword="true"/> and this is <see langword="false"/> no response is sent. + /// </remarks> + public bool HasSensitiveInfoPerms { get; set; } + + /// <summary> + /// Gets or sets whether the player has permission to view the <see cref="Target"/> <see cref="Player.UserId"/>. + /// </summary> + public bool HasUserIdPerms { get; set; } + + /// <summary> + /// The <see cref="StringBuilder"/> used to construct the response message. + /// </summary> + public StringBuilder InfoBuilder { get; } + + /// <inheritdoc /> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerRequestingRaPlayerListEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestingRaPlayerListEventArgs.cs new file mode 100644 index 00000000..74e9fd57 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestingRaPlayerListEventArgs.cs @@ -0,0 +1,70 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using System.Text; +using static RemoteAdmin.Communication.RaPlayerList; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.RequestingRaPlayerList"/> event. +/// </summary> +public class PlayerRequestingRaPlayerListEventArgs : EventArgs, IPlayerEvent, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="PlayerRequestingRaPlayerListEventArgs"/> class. + /// </summary> + /// <param name="commandSender">The <see cref="CommandSender"/> instance of the player that made the request for the RA player list.</param> + /// <param name="builder">The <see cref="StringBuilder"/> used to build the RA player list.</param> + /// <param name="isDescending">Whether to sort players by descending order.</param> + /// <param name="sorting">The <see cref="PlayerSorting"/> mode to use.</param> + /// <param name="viewHiddenLocalBadges">Whether the requester can view hidden local RA badges or not.</param> + /// <param name="viewHiddenGlobalBadges">Whether the requester can view hidden global RA badges or not.</param> + public PlayerRequestingRaPlayerListEventArgs(CommandSender commandSender, StringBuilder builder, bool isDescending, + PlayerSorting sorting, bool viewHiddenLocalBadges, bool viewHiddenGlobalBadges) + { + Player = Player.Get(commandSender)!; + ListBuilder = builder; + IsDescending = isDescending; + Sorting = sorting; + ViewHiddenLocalBadges = viewHiddenLocalBadges; + ViewHiddenGlobalBadges = viewHiddenGlobalBadges; + IsAllowed = true; + } + + /// <summary> + /// The player that requested the RA player list. + /// </summary> + public Player Player { get; } + + /// <summary> + /// The <see cref="StringBuilder"/> used to construct the RA player list. + /// </summary> + /// <remarks> + /// String builder is empty in this event. + /// </remarks> + public StringBuilder ListBuilder { get; } + + /// <summary> + /// Gets or set whether to sort players by descending order. + /// </summary> + public bool IsDescending { get; set; } + + /// <summary> + /// Gets or sets the <see cref="PlayerSorting"/> used. + /// </summary> + public PlayerSorting Sorting { get; set; } + + /// <summary> + /// Gets or sets whether the <see cref="Player"/> can view hidden local RA badges. + /// </summary> + public bool ViewHiddenLocalBadges { get; set; } + + /// <summary> + /// Gets or sets whether the <see cref="Player"/> can view hidden global RA badges. + /// </summary> + public bool ViewHiddenGlobalBadges { get; set; } + + /// <inheritdoc /> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerRequestingRaPlayersInfoEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestingRaPlayersInfoEventArgs.cs new file mode 100644 index 00000000..5b41587d --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestingRaPlayersInfoEventArgs.cs @@ -0,0 +1,73 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.RequestingRaPlayersInfo"/> event. +/// </summary> +public class PlayerRequestingRaPlayersInfoEventArgs : EventArgs, IPlayerEvent, ICancellableEvent +{ + private IEnumerable<ReferenceHub> _targets; + + /// <summary> + /// Initializes a new instance of the <see cref="PlayerRequestingRaPlayersInfoEventArgs"/> class. + /// </summary> + /// <param name="commandSender">The <see cref="CommandSender"/> instance of the player making the request.</param> + /// <param name="targets">The reference hub components of the targets selected by the player.</param> + /// <param name="isSensitiveInfo">Whether the player requested sensitive info.</param> + /// <param name="hasSensitiveInfoPerms">Whether the player has perms to view sensitive info.</param> + /// <param name="hasUserIdPerms">Whether the player has perms to view the user ids of the targets.</param> + /// <param name="infoBuilder">The <see cref="StringBuilder"/> used to construct the response message.</param> + public PlayerRequestingRaPlayersInfoEventArgs(CommandSender commandSender, IEnumerable<ReferenceHub> targets, + bool isSensitiveInfo, bool hasSensitiveInfoPerms, bool hasUserIdPerms, StringBuilder infoBuilder) + { + Player = Player.Get(commandSender)!; + IsSensitiveInfo = isSensitiveInfo; + HasSensitiveInfoPerms = hasSensitiveInfoPerms; + HasUserIdPerms = hasUserIdPerms; + InfoBuilder = infoBuilder; + IsAllowed = true; + _targets = targets; + } + + /// <summary> + /// The player that made the request. + /// </summary> + public Player Player { get; } + + /// <summary> + /// The target players selected. + /// </summary> + public IEnumerable<Player> Targets => _targets.Select(Player.Get)!; + + /// <summary> + /// Gets or sets whether the <see cref="Player"/> requested sensitive info. + /// </summary> + public bool IsSensitiveInfo { get; set; } + + /// <summary> + /// Gets or sets whether the player has permissions to view sensitive info. + /// </summary> + /// <remarks> + /// If <see cref="IsSensitiveInfo"/> is <see langword="true"/> and this is <see langword="false"/> no response is sent. + /// </remarks> + public bool HasSensitiveInfoPerms { get; set; } + + /// <summary> + /// Gets or sets whether the <see cref="Player"/> has permission to view the <see cref="Player.UserId"/> of the <see cref="Targets"/>. + /// </summary> + public bool HasUserIdPerms { get; set; } + + /// <summary> + /// Gets the <see cref="StringBuilder"/> used to construct the response message. + /// </summary> + public StringBuilder InfoBuilder { get; } + + /// <inheritdoc /> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSpawningRagdollEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSpawningRagdollEventArgs.cs index 811263ee..82ae672c 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSpawningRagdollEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSpawningRagdollEventArgs.cs @@ -9,7 +9,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.SpawningRagdoll"/> event. /// </summary> -public class PlayerSpawningRagdollEventArgs : EventArgs, IPlayerEvent, IRagdollEvent, ICancellableEvent +public class PlayerSpawningRagdollEventArgs : EventArgs, IPlayerEvent, ICancellableEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerSpawningRagdollEventArgs"/> class. @@ -21,7 +21,7 @@ public PlayerSpawningRagdollEventArgs(ReferenceHub player, BasicRagdoll ragdoll, { IsAllowed = true; Player = Player.Get(player); - Ragdoll = Ragdoll.Get(ragdoll); + RagdollPrefab = Ragdoll.Get(ragdoll); DamageHandler = damageHandler; } @@ -31,9 +31,15 @@ public PlayerSpawningRagdollEventArgs(ReferenceHub player, BasicRagdoll ragdoll, public Player Player { get; } /// <summary> - /// Gets the ragdoll which being spawned. + /// Gets the ragdoll prefab which will be used to instantiate the ragdoll. /// </summary> - public Ragdoll Ragdoll { get; } + [Obsolete($"use {nameof(RagdollPrefab)} instead.")] + public Ragdoll Ragdoll => RagdollPrefab; + + /// <summary> + /// Gets the ragdoll prefab which will be used to instantiate the ragdoll. + /// </summary> + public Ragdoll RagdollPrefab { get; } /// <summary> /// Gets the damage handler that caused the death of the player. diff --git a/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs b/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs index da4cf4e0..1bb99fa1 100644 --- a/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs +++ b/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs @@ -123,6 +123,50 @@ public static partial class PlayerEvents /// </summary> public static event LabEventHandler<PlayerToggledNoclipEventArgs>? ToggledNoclip; + /// <summary> + /// Gets called when the player is requesting the remote admin player list. + /// </summary> + public static event LabEventHandler<PlayerRequestingRaPlayerListEventArgs>? RequestingRaPlayerList; + + /// <summary> + /// Gets called when the player had requested the remote admin player list. + /// </summary> + public static event LabEventHandler<PlayerRequestedRaPlayerListEventArgs>? RequestedRaPlayerList; + + /// <summary> + /// Gets called when adding a target player to the remote admin player list while processing the request for the player. + /// </summary> + public static event LabEventHandler<PlayerRaPlayerListAddingPlayerEventArgs>? RaPlayerListAddingPlayer; + + /// <summary> + /// Gets called when a target player was added to the remote admin player list while processing the request for the player. + /// </summary> + public static event LabEventHandler<PlayerRaPlayerListAddedPlayerEventArgs>? RaPlayerListAddedPlayer; + + /// <summary> + /// Gets called when a player requested info for an unknown target in the remote admin. + /// </summary> + public static event LabEventHandler<PlayerRequestedCustomRaInfoEventArgs>? RequestedCustomRaInfo; + + /// <summary> + /// Gets called when a player is requesting info for multiple players in the remote admin. + /// </summary> + public static event LabEventHandler<PlayerRequestingRaPlayersInfoEventArgs>? RequestingRaPlayersInfo; + + /// <summary> + /// Gets called when a player had requested info for multiple players in the remote admin. + /// </summary> + public static event LabEventHandler<PlayerRequestedRaPlayersInfoEventArgs>? RequestedRaPlayersInfo; + + /// <summary> + /// Gets called when a player is requesting info for a target player in the remote admin. + /// </summary> + public static event LabEventHandler<PlayerRequestingRaPlayerInfoEventArgs>? RequestingRaPlayerInfo; + + /// <summary> + /// Gets called when a player had requested info for a target player in the remote admin. + /// </summary> + public static event LabEventHandler<PlayerRequestedRaPlayerInfoEventArgs>? RequestedRaPlayerInfo; #endregion @@ -740,6 +784,11 @@ public static partial class PlayerEvents /// </summary> public static event LabEventHandler<PlayerUnlockedWarheadButtonEventArgs>? UnlockedWarheadButton; + /// <summary> + /// Gets called when the player has meet the requirements of an achievement. + /// </summary> + public static event LabEventHandler<PlayerReceivedAchievementEventArgs>? ReceivedAchievement; + #endregion #region Spectating diff --git a/LabApi/Features/Wrappers/Facility/Map.cs b/LabApi/Features/Wrappers/Facility/Map.cs index 67a0cd18..c85765a1 100644 --- a/LabApi/Features/Wrappers/Facility/Map.cs +++ b/LabApi/Features/Wrappers/Facility/Map.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Linq; +using UnityEngine; namespace LabApi.Features.Wrappers; @@ -61,12 +62,39 @@ public static class Map /// </summary> public static IReadOnlyCollection<Ragdoll> Ragdolls => Ragdoll.List; + /// <summary> + /// Represents the bounds for the default escape zone on surface. + /// </summary> + /// <remarks> + /// By default this is included in the <see cref="EscapeZones"/> list. + /// </remarks> + public static Bounds DefaultEscapeZone = Escape.DefaultEscapeZone; + + /// <summary> + /// A list of all bounds used as escape zones. + /// </summary> + /// <remarks> + /// By default only the <see cref="DefaultEscapeZone"/> is included in the list. + /// </remarks> + public static List<Bounds> EscapeZones => Escape.EscapeZones; - #region Get Random /// <summary> - /// Gets a random <see cref="Room"/>. + /// Adds another bounds to be used as an escape zone to the <see cref="EscapeZones"/> list. /// </summary> - /// <returns>The random room if there were any rooms otherwise null.</returns> + /// <param name="escapeZone">The bounds of the new escape zone.</param> + public static void AddEscapeZone(Bounds escapeZone) => EscapeZones.Add(escapeZone); + + /// <summary> + /// Removes an existing bounds from the <see cref="EscapeZones"/> list. + /// </summary> + /// <param name="escapeZone">The bounds of the escape zone to remove.</param> + public static void RemoveEscapeZone(Bounds escapeZone) => EscapeZones.Remove(escapeZone); + + #region Get Random + /// <summary> + /// Gets a random <see cref="Room"/>. + /// </summary> + /// <returns>The random room if there were any rooms otherwise null.</returns> public static Room? GetRandomRoom() { return Rooms.Count != 0 ? Rooms.ElementAt(UnityEngine.Random.Range(0, Rooms.Count)) : null; diff --git a/LabApi/Features/Wrappers/Players/Server.cs b/LabApi/Features/Wrappers/Players/Server.cs index 3639e8d1..3a497c39 100644 --- a/LabApi/Features/Wrappers/Players/Server.cs +++ b/LabApi/Features/Wrappers/Players/Server.cs @@ -1,4 +1,5 @@ -using CommandSystem; +using Achievements; +using CommandSystem; using CustomPlayerEffects; using Generators; using InventorySystem.Configs; @@ -126,6 +127,23 @@ public static bool FriendlyFire } } + /// <summary> + /// Gets or sets a value indicating whether achievement granting is enabled. + /// </summary> + public static bool AchievementsEnabled + { + get => !AchievementManager.AchievementsDisabled; + set + { + if (AchievementManager.AchievementsDisabled != value) + return; + + AchievementManager.AchievementsDisabled = !value; + ServerConfigSynchronizer.Singleton.RefreshMainBools(); + ServerConfigSynchronizer.OnRefreshed?.Invoke(); + } + } + /// <summary> /// Gets or sets the server name as seen on the server list. /// </summary> From 771bc5ff408e3449bc3e6ad2feefd464120809b1 Mon Sep 17 00:00:00 2001 From: David <david.sebesta@post.cz> Date: Wed, 2 Jul 2025 22:27:05 +0200 Subject: [PATCH 040/215] Misc Changes and Improvements (#249) * Made CustomHandlersManager public as of someone's request Added IDisposable to AudioTransmitter, auto disposed when no controller uses it anymore Added PriorityQueue as .net 4.8 doesnt have it Static delegate optimalizations Docs fixes Fixed RespawnTokens Pocket dimension added GetCaughPosition Room Added AdjacentRooms and Path finder Server added SendAdminChatMessage Added Quaternion converter to yaml configs * Silly path reconstruction moment * Fix adjency between HCZ-EZ Fix admin message * Remove unused namespaces * Reverted opus disposal * Docs fix & suggestions * Update LabApi/Features/Wrappers/Facility/Rooms/PocketDimension/PocketDimension.cs Co-authored-by: brayden-dowson <88667957+brayden-dowson@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Jesus QC <69375249+Jesus-QC@users.noreply.github.com> * spacing * Better queue Linq extensions Adjacency optimalization * Fix doc * Fix doc 2 * Suggestions * Revert breaking change * Room to RoomIdentifier --------- Co-authored-by: brayden-dowson <88667957+brayden-dowson@users.noreply.github.com> Co-authored-by: Jesus QC <69375249+Jesus-QC@users.noreply.github.com> --- .../CustomHandlers/CustomHandlersManager.cs | 2 +- LabApi/Features/Audio/AudioTransmitter.cs | 5 +- LabApi/Features/Extensions/LinqExtensions.cs | 59 ++++++ LabApi/Features/Extensions/PriorityQueue.cs | 108 ++++++++++ .../Features/Extensions/PriorityQueuePool.cs | 37 ++++ LabApi/Features/Extensions/RoleExtensions.cs | 1 - .../Commands/PluginPermissionsCommand.cs | 2 +- LabApi/Features/Stores/CustomDataStore.cs | 8 +- .../Features/Wrappers/AdminToys/SpeakerToy.cs | 2 +- LabApi/Features/Wrappers/AdminToys/TextToy.cs | 1 + .../Features/Wrappers/Facility/Doors/Door.cs | 2 +- LabApi/Features/Wrappers/Facility/Elevator.cs | 5 + .../Facility/Hazards/TantrumHazard.cs | 2 +- .../Facility/Respawning/Waves/RespawnWave.cs | 3 + .../Rooms/PocketDimension/PocketDimension.cs | 21 +- .../Features/Wrappers/Facility/Rooms/Room.cs | 184 ++++++++++++++++-- .../Wrappers/Facility/Rooms/Scp914/Scp914.cs | 6 +- LabApi/Features/Wrappers/Facility/Warhead.cs | 1 - LabApi/Features/Wrappers/Players/Server.cs | 42 +++- .../CustomQuaternionConverter.cs | 70 +++++++ .../CustomConverters/CustomVectorConverter.cs | 3 - .../Loader/Features/Yaml/YamlConfigParser.cs | 2 + 22 files changed, 522 insertions(+), 44 deletions(-) create mode 100644 LabApi/Features/Extensions/LinqExtensions.cs create mode 100644 LabApi/Features/Extensions/PriorityQueue.cs create mode 100644 LabApi/Features/Extensions/PriorityQueuePool.cs create mode 100644 LabApi/Loader/Features/Yaml/CustomConverters/CustomQuaternionConverter.cs diff --git a/LabApi/Events/CustomHandlers/CustomHandlersManager.cs b/LabApi/Events/CustomHandlers/CustomHandlersManager.cs index ba3c7326..ea493357 100644 --- a/LabApi/Events/CustomHandlers/CustomHandlersManager.cs +++ b/LabApi/Events/CustomHandlers/CustomHandlersManager.cs @@ -46,7 +46,7 @@ public static void UnregisterEventsHandler<T>(T handler) /// <summary> /// Checks if the event is overriden and subscribes the handler to the event if it is. /// </summary> - private static void CheckEvent<T>(T handler, Type handlerType, string methodDelegate, Type eventType, string eventName) + public static void CheckEvent<T>(T handler, Type handlerType, string methodDelegate, Type eventType, string eventName) where T : CustomEventsHandler { // We first get the method from the handler. diff --git a/LabApi/Features/Audio/AudioTransmitter.cs b/LabApi/Features/Audio/AudioTransmitter.cs index b90f5801..4dbad2ea 100644 --- a/LabApi/Features/Audio/AudioTransmitter.cs +++ b/LabApi/Features/Audio/AudioTransmitter.cs @@ -22,6 +22,8 @@ namespace LabApi.Features.Audio; /// </remarks> public class AudioTransmitter { + private const float GainCorrectionFactor = 1.41421356237f; + private static readonly float[] EmptyData = new float[FrameSize]; private static readonly float[] TempSampleData = new float[FrameSize]; @@ -191,7 +193,6 @@ public void Stop() private IEnumerator<float> Transmit() { - float root2 = MathF.Sqrt(2.0f); targetTime = NetworkTime.time; while (!AudioClipSamples.IsEmpty()) { @@ -226,7 +227,7 @@ private IEnumerator<float> Transmit() // Client sided bug causes output to be 3db quieter than expected // so we correct for that here for (int i = 0; i < TempSampleData.Length; i++) - TempSampleData[i] *= root2; + TempSampleData[i] *= GainCorrectionFactor; int length = opusEncoder.Encode(TempSampleData, TempEncodedData, FrameSize); if (length > 2) diff --git a/LabApi/Features/Extensions/LinqExtensions.cs b/LabApi/Features/Extensions/LinqExtensions.cs new file mode 100644 index 00000000..37a31fd2 --- /dev/null +++ b/LabApi/Features/Extensions/LinqExtensions.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace LabApi.Features.Extensions; + +/// <summary> +/// Extensions for Linq. +/// </summary> +public static class LinqExtensions +{ + /// <summary> + /// Finds smallest value by a specified key. + /// If 2 or more occurances have the same minimum value then the first one in the collection is returned. + /// </summary> + /// <typeparam name="T">The type to compare and select.</typeparam> + /// <typeparam name="K">The value to compare the keys.</typeparam> + /// <param name="enumerable">The enumerable collection.</param> + /// <param name="selectFunc">The selection function.</param> + /// <returns>Minimum value or <see langword="null"/> if the collection is empty.</returns> + public static T? MinBy<T, K>(this IEnumerable<T> enumerable, Func<T, K> selectFunc) where T : class where K : IComparable + { + if (!enumerable.Any()) + return null; + + T? currentMin = enumerable.First(); + foreach (T member in enumerable) + { + if (selectFunc(member).CompareTo(selectFunc(currentMin)) < 0) + currentMin = member; + } + + return currentMin; + } + + /// <summary> + /// Finds largest value by a specified key. + /// If 2 or more occurances have the same minimum value then the first one in the collection is returned. + /// </summary> + /// <typeparam name="T">The type to compare and select.</typeparam> + /// <typeparam name="K">The value to compare the keys.</typeparam> + /// <param name="enumerable">The enumerable collection.</param> + /// <param name="selectFunc">The selection function.</param> + /// <returns>Maximum value or <see langword="null"/> if the collection is empty.</returns> + public static T? MaxBy<T, K>(this IEnumerable<T> enumerable, Func<T, K> selectFunc) where T : class where K : IComparable + { + if (!enumerable.Any()) + return null; + + T? currentMin = enumerable.First(); + foreach (T member in enumerable) + { + if (selectFunc(member).CompareTo(selectFunc(currentMin)) > 0) + currentMin = member; + } + + return currentMin; + } +} diff --git a/LabApi/Features/Extensions/PriorityQueue.cs b/LabApi/Features/Extensions/PriorityQueue.cs new file mode 100644 index 00000000..5b81f3a8 --- /dev/null +++ b/LabApi/Features/Extensions/PriorityQueue.cs @@ -0,0 +1,108 @@ +using System; +using System.Collections.Generic; + +namespace LabApi.Features.Extensions; + +/// <summary> +/// Priority queue class. +/// </summary> +/// <typeparam name="T">Data type to store in the queue.</typeparam> +public class PriorityQueue<T> +{ + /// <summary> + /// Gets the number of items currently in the queue. + /// </summary> + public int Count => _elements.Count; + + private readonly List<ValueTuple<int, T>> _elements; + + /// <summary> + /// Initializes a new instance of the <see cref="PriorityQueue{T}"/> class. + /// </summary> + public PriorityQueue() + { + _elements = new List<ValueTuple<int, T>>(); + } + + /// <summary> + /// Adds an item to the priority queue with the specified priority. + /// Smaller numbers indicate higher priority. + /// </summary> + /// <param name="item">The item to add.</param> + /// <param name="priority">The priority of the item.</param> + public void Enqueue(T item, int priority) + { + ValueTuple<int, T> newItem = new ValueTuple<int, T>(priority, item); + _elements.Add(newItem); + HeapifyUp(_elements.Count - 1); + } + /// <summary> + /// Removes and returns the item with the highest priority (smallest priority value) from the queue. + /// </summary> + /// <returns>The item with the highest priority.</returns> + /// <exception cref="InvalidOperationException">Thrown if the queue is empty.</exception> + public T Dequeue() + { + if (Count == 0) + throw new InvalidOperationException("The queue is empty."); + + T bestItem = _elements[0].Item2; + int lastIndex = _elements.Count - 1; + + _elements[0] = _elements[lastIndex]; + _elements.RemoveAt(lastIndex); + + if (Count > 0) + HeapifyDown(0); + + return bestItem; + } + /// <summary> + /// Clears all items from the queue. + /// </summary> + public void Clear() + { + _elements.Clear(); + } + + private void HeapifyUp(int index) + { + int parentIndex = (index - 1) / 2; + while (index > 0 && _elements[index].Item1 < _elements[parentIndex].Item1) + { + Swap(index, parentIndex); + index = parentIndex; + parentIndex = (index - 1) / 2; + } + } + + private void HeapifyDown(int index) + { + int leftChildIndex; + int rightChildIndex; + int smallestChildIndex; + while (true) + { + leftChildIndex = (2 * index) + 1; + rightChildIndex = (2 * index) + 2; + smallestChildIndex = index; + + if (leftChildIndex < Count && _elements[leftChildIndex].Item1 < _elements[smallestChildIndex].Item1) + smallestChildIndex = leftChildIndex; + + if (rightChildIndex < Count && _elements[rightChildIndex].Item1 < _elements[smallestChildIndex].Item1) + smallestChildIndex = rightChildIndex; + + if (smallestChildIndex == index) + break; + + Swap(index, smallestChildIndex); + index = smallestChildIndex; + } + } + + private void Swap(int index1, int index2) + { + (_elements[index1], _elements[index2]) = (_elements[index2], _elements[index1]); + } +} \ No newline at end of file diff --git a/LabApi/Features/Extensions/PriorityQueuePool.cs b/LabApi/Features/Extensions/PriorityQueuePool.cs new file mode 100644 index 00000000..00ecd3f8 --- /dev/null +++ b/LabApi/Features/Extensions/PriorityQueuePool.cs @@ -0,0 +1,37 @@ +using System.Collections.Concurrent; +using NorthwoodLib.Pools; + +namespace LabApi.Features.Extensions; + +/// <summary> +/// Pool for <see cref="PriorityQueue{T}"/> +/// </summary> +/// <typeparam name="T">Type of the queue.</typeparam> +public sealed class PriorityQueuePool<T> : IPool<PriorityQueue<T>> +{ + /// <summary> + /// Gets a shared <see cref="PriorityQueue{T}"/> instance. + /// </summary> + public static readonly PriorityQueuePool<T> Shared = new(); + + private readonly ConcurrentQueue<PriorityQueue<T>> _pool = new(); + + /// <summary> + /// Gives a pooled <see cref="PriorityQueue{T}"/> or creates a new one if the pool is empty. + /// </summary> + /// <returns>A <see cref="PriorityQueue{T}"/> instance from the pool.</returns> + public PriorityQueue<T> Rent() + { + return _pool.TryDequeue(out PriorityQueue<T> set) ? set : new PriorityQueue<T>(); + } + + /// <summary> + /// Returns a <see cref="PriorityQueue{T}"/> to the pool for reuse. + /// </summary> + /// <param name="queue">The <see cref="PriorityQueue{T}"/> to return to the pool.</param> + public void Return(PriorityQueue<T> queue) + { + queue.Clear(); + _pool.Enqueue(queue); + } +} diff --git a/LabApi/Features/Extensions/RoleExtensions.cs b/LabApi/Features/Extensions/RoleExtensions.cs index d7cf9ed1..e148d3c9 100644 --- a/LabApi/Features/Extensions/RoleExtensions.cs +++ b/LabApi/Features/Extensions/RoleExtensions.cs @@ -1,5 +1,4 @@ using PlayerRoles; -using UnityEngine; namespace LabApi.Features.Extensions; diff --git a/LabApi/Features/Permissions/Commands/PluginPermissionsCommand.cs b/LabApi/Features/Permissions/Commands/PluginPermissionsCommand.cs index a38e4747..dd36d9dd 100644 --- a/LabApi/Features/Permissions/Commands/PluginPermissionsCommand.cs +++ b/LabApi/Features/Permissions/Commands/PluginPermissionsCommand.cs @@ -35,7 +35,7 @@ public bool Execute(ArraySegment<string> arguments, ICommandSender sender, [Unsc continue; } - response = perms.Aggregate(response, (current, perm) => current + $"+ {perm}\n"); + response = perms.Aggregate(response, static (current, perm) => current + $"+ {perm}\n"); } return true; diff --git a/LabApi/Features/Stores/CustomDataStore.cs b/LabApi/Features/Stores/CustomDataStore.cs index 8677c738..e27ad23d 100644 --- a/LabApi/Features/Stores/CustomDataStore.cs +++ b/LabApi/Features/Stores/CustomDataStore.cs @@ -11,7 +11,7 @@ namespace LabApi.Features.Stores; /// </summary> public abstract class CustomDataStore { - private static readonly Dictionary<Type, Dictionary<Player, CustomDataStore>> StoreInstances = new (); + private static readonly Dictionary<Type, Dictionary<Player, CustomDataStore>> StoreInstances = new(); /// <summary> /// Gets the <see cref="Player"/> that this instance is associated with. @@ -90,8 +90,8 @@ internal static void Destroy<TStore>(Player player) /// <typeparam name="TStore">The type of the <see cref="CustomDataStore"/>.</typeparam> internal static void DestroyAll<TStore>() { - List<CustomDataStore>? storesToRemove = ListPool<CustomDataStore>.Shared.Rent(StoreInstances.SelectMany(entry => - entry.Value.Where(playerStore => playerStore.Value.GetType() == typeof(TStore)).Select(playerStore => playerStore.Value))); + List<CustomDataStore>? storesToRemove = ListPool<CustomDataStore>.Shared.Rent(StoreInstances.SelectMany(static entry => + entry.Value.Where(static playerStore => playerStore.Value.GetType() == typeof(TStore)).Select(playerStore => playerStore.Value))); foreach (CustomDataStore? store in storesToRemove) store.Destroy(); @@ -105,7 +105,7 @@ internal static void DestroyAll<TStore>() internal void Destroy() { OnInstanceDestroyed(); - StoreInstances[this.GetType()].Remove(Owner); + StoreInstances[GetType()].Remove(Owner); } private void InternalOnInstanceCreated() => OnInstanceCreated(); diff --git a/LabApi/Features/Wrappers/AdminToys/SpeakerToy.cs b/LabApi/Features/Wrappers/AdminToys/SpeakerToy.cs index 78c280d5..8e6dc5df 100644 --- a/LabApi/Features/Wrappers/AdminToys/SpeakerToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/SpeakerToy.cs @@ -305,7 +305,7 @@ public static bool TryGet(BaseSpeakerToy? baseSpeakerToy, [NotNullWhen(true)] ou /// If one does not exists, a new one is created for the id. /// </summary> /// <param name="controllerId">The <see cref="ControllerId"/> for the transmitter.</param> - /// <returns></returns> + /// <returns>Cached transmitter.</returns> public static AudioTransmitter GetTransmitter(byte controllerId) { if (!TransmitterByControllerId.TryGetValue(controllerId, out AudioTransmitter transmitter)) diff --git a/LabApi/Features/Wrappers/AdminToys/TextToy.cs b/LabApi/Features/Wrappers/AdminToys/TextToy.cs index f2469f5e..392d1643 100644 --- a/LabApi/Features/Wrappers/AdminToys/TextToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/TextToy.cs @@ -29,6 +29,7 @@ public class TextToy : AdminToy internal TextToy(BaseTextToy baseToy) : base(baseToy) { Base = baseToy; + Dictionary.Add(baseToy, this); } /// <summary> diff --git a/LabApi/Features/Wrappers/Facility/Doors/Door.cs b/LabApi/Features/Wrappers/Facility/Doors/Door.cs index 6e2c6ff5..961937a9 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/Door.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/Door.cs @@ -106,7 +106,7 @@ protected Door(DoorVariant doorVariant) if (doorNameDictionary.TryGetValue(nametag.GetName, out DoorName doorName)) DoorName = doorName; else - Logger.Warn($"Missing DoorName enum value for door name tag {nametag.GetName}"); + Logger.InternalWarn($"Missing DoorName enum value for door name tag {nametag.GetName}"); } } diff --git a/LabApi/Features/Wrappers/Facility/Elevator.cs b/LabApi/Features/Wrappers/Facility/Elevator.cs index eadc26d4..91c67439 100644 --- a/LabApi/Features/Wrappers/Facility/Elevator.cs +++ b/LabApi/Features/Wrappers/Facility/Elevator.cs @@ -65,6 +65,11 @@ internal static void Initialize() /// </summary> public ElevatorDoor NextDestination => ElevatorDoor.Get(Base.NextDestinationDoor); + /// <summary> + /// Gets all rooms this elevator can move to. + /// </summary> + public IEnumerable<Room> Rooms => Base.FloorDoors.SelectMany(door => door.Rooms.Select(Room.Get)); + /// <summary> /// Gets the destination floor index this elevator will head towards once activated. /// </summary> diff --git a/LabApi/Features/Wrappers/Facility/Hazards/TantrumHazard.cs b/LabApi/Features/Wrappers/Facility/Hazards/TantrumHazard.cs index f0973f27..21430d7d 100644 --- a/LabApi/Features/Wrappers/Facility/Hazards/TantrumHazard.cs +++ b/LabApi/Features/Wrappers/Facility/Hazards/TantrumHazard.cs @@ -95,7 +95,7 @@ internal override void OnRemove() /// Gets the hazard wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="TantrumEnvironmentalHazard"/> was not <see langword="null"/>. /// </summary> /// <param name="hazard">The <see cref="Base"/> of the hazard.</param> - /// <returns>The requested hazard or <see langword="null"/></returns> + /// <returns>The requested hazard or <see langword="null"/>.</returns> [return: NotNullIfNotNull(nameof(hazard))] public static TantrumHazard? Get(TantrumEnvironmentalHazard? hazard) { diff --git a/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs b/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs index db8b61c8..52246ae7 100644 --- a/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs +++ b/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs @@ -102,6 +102,9 @@ public float TimeLeft /// <summary> /// Gets or sets the time this wave's timer is paused. /// </summary> + /// <remarks> + /// Currently the wave timer pauses only at about 10% left. + /// </remarks> public float PausedTime { get => Base.Timer.PauseTimeLeft; diff --git a/LabApi/Features/Wrappers/Facility/Rooms/PocketDimension/PocketDimension.cs b/LabApi/Features/Wrappers/Facility/Rooms/PocketDimension/PocketDimension.cs index db00d949..3c4839d0 100644 --- a/LabApi/Features/Wrappers/Facility/Rooms/PocketDimension/PocketDimension.cs +++ b/LabApi/Features/Wrappers/Facility/Rooms/PocketDimension/PocketDimension.cs @@ -68,8 +68,8 @@ public static float MaxPocketItemTriggerDelay /// An internal constructor to prevent external instantiation. /// </summary> /// <param name="room">The room identifier for the pocket dimension.</param> - internal PocketDimension(RoomIdentifier room) - : base(room) + internal PocketDimension(RoomIdentifier room) + : base(room) { if (CanCache) Instance = this; @@ -97,6 +97,21 @@ internal override void OnRemoved() /// <returns>True if inside otherwise false.</returns> public static bool IsPlayerInside(Player player) => player.HasEffect<PocketCorroding>(); + /// <summary> + /// Gets the position at which the <paramref name="player"/> was caught. + /// </summary> + /// <param name="player">The player.</param> + /// <returns>Returns caught position, also returns <see cref="Vector3.zero"/> if the player is not in <see cref="PocketDimension"/>.</returns> + public static Vector3 GetCaughtPosition(Player player) + { + PocketCorroding? effect = player.GetEffect<PocketCorroding>(); + + if (effect != null && effect.Intensity > 0) + return effect.CapturePosition.Position; + + return Vector3.zero; + } + /// <summary> /// Force a player to exit the pocket dimension. /// </summary> @@ -167,7 +182,7 @@ public static void AddExitPosesForZone(FacilityZone zone, IEnumerable<Pose> pose /// <param name="zone">The zone to remove exits from.</param> public static void RemoveAllExitPosesForZone(FacilityZone zone) => Scp106PocketExitFinder.PosesForZoneCache[zone] = []; - + /// <summary> /// Removes the specified <see cref="Pose">poses</see> from use as exits for the pocket dimension. /// </summary> diff --git a/LabApi/Features/Wrappers/Facility/Rooms/Room.cs b/LabApi/Features/Wrappers/Facility/Rooms/Room.cs index 0f9b2011..261675d1 100644 --- a/LabApi/Features/Wrappers/Facility/Rooms/Room.cs +++ b/LabApi/Features/Wrappers/Facility/Rooms/Room.cs @@ -1,10 +1,13 @@ using Generators; using Interactables.Interobjects.DoorUtils; +using LabApi.Features.Extensions; using MapGeneration; +using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using UnityEngine; +using UnityEngine.Pool; namespace LabApi.Features.Wrappers; @@ -26,7 +29,7 @@ internal static void Initialize() /// <summary> /// Contains all the cached rooms in the game, accessible through their <see cref="RoomIdentifier"/>. /// </summary> - private static Dictionary<RoomIdentifier, Room> Dictionary { get; } = []; + public static Dictionary<RoomIdentifier, Room> Dictionary { get; } = []; /// <summary> /// A reference to all <see cref="Room"/> instances currently in the game. @@ -51,6 +54,8 @@ internal Room(RoomIdentifier roomIdentifier) internal virtual void OnRemoved() { Dictionary.Remove(Base); + _adjacentRooms = null; + _connectedRooms = null; } /// <summary> @@ -84,25 +89,78 @@ internal virtual void OnRemoved() public HashSet<RoomIdentifier> ConnectedRooms => Base.ConnectedRooms; /// <summary> - /// Gets the doors that are a part of this room. TODO: Cache in base game code? + /// Gets the room's adjacent rooms where the player can traverse to. + /// Includes rooms that can be traversed to via elevator. + /// </summary> + public IReadOnlyCollection<Room> AdjacentRooms + { + get + { + if (_adjacentRooms != null) + return _adjacentRooms; + + List<Room> rooms = [.. ConnectedRooms.Select(Get)]; + + // Check if the room has elevator + Elevator? target = null; + foreach (Elevator elevator in Elevator.List) + { + if (elevator.Rooms.Contains(this)) + target = elevator; + } + + // Add rooms that are on other floors of this elevator + if (target != null) + { + foreach (Room room in target.Rooms) + { + if (room == this) + continue; + + rooms.Add(room); + } + } + + //Hcz-Ez checkpoints + if (Name == RoomName.HczCheckpointToEntranceZone) + { + FacilityZone targetZone = Zone == FacilityZone.HeavyContainment ? FacilityZone.Entrance : FacilityZone.HeavyContainment; + + Room? match = List + .Where(n => n.Name == RoomName.HczCheckpointToEntranceZone && n.Zone == targetZone) + .MinBy(n => (n.Position - Position).sqrMagnitude); + + if (match != null) + rooms.Add(match); + } + + _adjacentRooms = rooms.AsReadOnly(); + return _adjacentRooms; + } + } + + /// <summary> + /// Gets the doors that are a part of this room. /// </summary> public IEnumerable<Door> Doors { get { - return DoorVariant.DoorsByRoom.TryGetValue(Base, out HashSet<DoorVariant> doors) ? doors.Where(x => x != null).Select(x => Door.Get(x!)) : []; + return DoorVariant.DoorsByRoom.TryGetValue(Base, out HashSet<DoorVariant> doors) ? doors.Where(static x => x != null).Select(static x => Door.Get(x!)) : []; } } /// <summary> - /// Gets the first light controller for this room.<br></br> - /// <note>Please see <see cref="AllLightControllers"/> if you wish to modify all lights in this room.</note> + /// Gets the first light controller for this room.<br/> + /// <note> + /// Use <see cref="AllLightControllers"/> if you wish to modify all lights in this room. + /// </note> /// </summary> public LightsController? LightController => Base.LightControllers.Count > 0 ? LightsController.Get(Base.LightControllers[0]) : null; /// <summary> /// Gets all light controllers for this specified room.<br/> - /// Some rooms such as 049, warhead and etc may have multiple light controllers as they are split by the elevator. + /// Some rooms such as 049, warhead and such may have multiple light controllers as they are split by the elevator. /// </summary> public IEnumerable<LightsController> AllLightControllers => Base.LightControllers.Select(LightsController.Get); @@ -141,12 +199,109 @@ public override string ToString() { return $"[{GetType().Name}: Name={Name}, Shape={Shape}, Zone={Zone}]"; } - + /// <summary> /// Gets whether the room wrapper is allowed to be cached. /// </summary> protected bool CanCache => !IsDestroyed; + private HashSet<Room>? _connectedRooms; + + private IReadOnlyCollection<Room>? _adjacentRooms; + + /// <summary> + /// Gets the closest <see cref="LightsController"/> to the specified player. + /// </summary> + /// <param name="player">The player to check the closest light controller for.</param> + /// <returns>The closest light controller. May return <see langword="null"/> if player is not alive or is not in any room.</returns> + public LightsController? GetClosestLightController(Player player) + { + RoomLightController rlc = Base.GetClosestLightController(player.ReferenceHub); + return rlc == null ? null : LightsController.Get(rlc); + } + + /// <summary> + /// Gets path from <paramref name="start"/> to <paramref name="end"/>.<br/> + /// Path is found via <see href="https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm">Dijkstra's algorithm</see>. Path still works between zones (including via elevators) as it uses <see cref="AdjacentRooms"/>.<br/> + /// If no path is found, an empty list is returned. + /// </summary> + /// <param name="start">The starting room.</param> + /// <param name="end">The ending room.</param> + /// <param name="weightFunction">The weight function to calculate cost to the next room. Can be change if you prefer to go around tesla gates and such.</param> + /// <returns>A pooled list containing rooms from <paramref name="start"/> to <paramref name="end"/> (including these rooms).</returns> + public static List<Room> FindPath(Room start, Room end, Func<Room, int> weightFunction) + { + List<Room> path = NorthwoodLib.Pools.ListPool<Room>.Shared.Rent(); + + if (start == null || end == null || start == end) + return path; + + Dictionary<Room, Room?> previous = DictionaryPool<Room, Room?>.Get(); + Dictionary<Room, int> distances = DictionaryPool<Room, int>.Get(); + HashSet<Room> visited = NorthwoodLib.Pools.HashSetPool<Room>.Shared.Rent(); + PriorityQueue<Room> queue = PriorityQueuePool<Room>.Shared.Rent(); + + // Standard dijakstra + foreach (Room room in List) + { + distances[room] = int.MaxValue; + previous[room] = null; + } + + distances[start] = 0; + queue.Enqueue(start, 0); + + while (queue.Count > 0) + { + Room current = queue.Dequeue(); + + if (visited.Contains(current)) + continue; + + visited.Add(current); + + if (current == end) + break; + + foreach (Room neighbor in current.AdjacentRooms) + { + if (visited.Contains(neighbor)) + continue; + + int newDistance = distances[current] + weightFunction(neighbor); + if (newDistance < distances[neighbor]) + { + distances[neighbor] = newDistance; + previous[neighbor] = current; + queue.Enqueue(neighbor, newDistance); + } + } + } + + Room? step = end; + + // Reconstruct the path from start to end room + while (step != null) + { + path.Insert(0, step); + step = previous[step]; + } + + // If only entry is the end room, clear the path as it wasnt found + if (path.Count == 1 && path[0] == end) + path.Clear(); + + DictionaryPool<Room, Room?>.Release(previous); + DictionaryPool<Room, int>.Release(distances); + NorthwoodLib.Pools.HashSetPool<Room>.Shared.Return(visited); + PriorityQueuePool<Room>.Shared.Return(queue); + + return path; + } + + /// <inheritdoc cref="FindPath(Room, Room, Func{Room, int})"/> + public static List<Room> FindPath(Room start, Room end) => FindPath(start, end, static (room) => 1); + /// <summary> /// Gets the room wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist. /// </summary> @@ -196,17 +351,6 @@ public static IEnumerable<Room> Get(FacilityZone facilityZone) => public static IEnumerable<Room> Get(IEnumerable<RoomIdentifier> roomIdentifiers) => roomIdentifiers.Select(Get); - /// <summary> - /// Gets the closest <see cref="LightsController"/> to the specified player. - /// </summary> - /// <param name="player">The player to check the closest light controller for.</param> - /// <returns>The closest light controller. May return <see langword="null"/> if player is not alive or is not in any room.</returns> - public LightsController? GetClosestLightController(Player player) - { - RoomLightController rlc = Base.GetClosestLightController(player.ReferenceHub); - return rlc == null ? null : LightsController.Get(rlc); - } - /// <summary> /// Tries to get the room at the specified position. /// </summary> @@ -258,7 +402,7 @@ private static void AddRoom(RoomIdentifier roomIdentifier) if (!Dictionary.ContainsKey(roomIdentifier)) _ = CreateRoomWrapper(roomIdentifier); } - catch (System.Exception e) + catch (Exception e) { Console.Logger.InternalError($"Failed to handle room creation with error: {e}"); } @@ -275,7 +419,7 @@ private static void RemoveRoom(RoomIdentifier roomIdentifier) if (Dictionary.TryGetValue(roomIdentifier, out Room room)) room.OnRemoved(); } - catch (System.Exception e) + catch (Exception e) { Console.Logger.InternalError($"Failed to handle item destruction with error: {e}"); } diff --git a/LabApi/Features/Wrappers/Facility/Rooms/Scp914/Scp914.cs b/LabApi/Features/Wrappers/Facility/Rooms/Scp914/Scp914.cs index 8bef23d2..9410cde1 100644 --- a/LabApi/Features/Wrappers/Facility/Rooms/Scp914/Scp914.cs +++ b/LabApi/Features/Wrappers/Facility/Rooms/Scp914/Scp914.cs @@ -20,7 +20,7 @@ public class Scp914 : Room /// Gets the current <see cref="Scp914"/> instance. /// </summary> /// <remarks> - /// May be null if the map has not been generated yet or was previously destroyed. + /// May be <see langword="null"/> if the map has not been generated yet or was previously destroyed. /// </remarks> public static Scp914? Instance { get; private set; } @@ -195,7 +195,7 @@ public static float DoorOpenDelay /// Interact with the SCP-914 machine. /// </summary> /// <param name="interactCode">The type of interaction.</param> - /// <param name="player">The <see cref="Player"/> that triggered the interaction or null if not specified.</param> + /// <param name="player">The <see cref="Player"/> that triggered the interaction or <see langword="null"/> if not specified.</param> /// <remarks> /// Interacting will also trigger SCP-914 related events. /// If you would not like to trigger events use <see cref="KnobSetting"/> and <see cref="IsUpgrading"/> instead. @@ -218,7 +218,7 @@ public static void PlaySound(Scp914Sound sound) /// Gets the <see cref="IScp914ItemProcessor"/> for the specified type. /// </summary> /// <param name="type">The <see cref="ItemType"/> to get the associated <see cref="IScp914ItemProcessor"/>.</param> - /// <returns>The associated <see cref="IScp914ItemProcessor"/> for the <see cref="ItemType"/> if found, otherwise null.</returns> + /// <returns>The associated <see cref="IScp914ItemProcessor"/> for the <see cref="ItemType"/> if found, otherwise <see langword="null"/>.</returns> /// <remarks> /// If the item processor is a base game <see cref="Scp914ItemProcessor"/>, <see cref="IScp914ItemProcessor"/> will be a <see cref="BaseGameItemProcessor"/>. /// </remarks> diff --git a/LabApi/Features/Wrappers/Facility/Warhead.cs b/LabApi/Features/Wrappers/Facility/Warhead.cs index 5a0eca5d..5f06b8d1 100644 --- a/LabApi/Features/Wrappers/Facility/Warhead.cs +++ b/LabApi/Features/Wrappers/Facility/Warhead.cs @@ -1,7 +1,6 @@ using GameCore; using Generators; using LabApi.Events.Handlers; -using MapGeneration; using Mirror; using System; using System.Collections.Generic; diff --git a/LabApi/Features/Wrappers/Players/Server.cs b/LabApi/Features/Wrappers/Players/Server.cs index 3a497c39..aee9fd1a 100644 --- a/LabApi/Features/Wrappers/Players/Server.cs +++ b/LabApi/Features/Wrappers/Players/Server.cs @@ -1,4 +1,5 @@ using Achievements; +using CentralAuth; using CommandSystem; using CustomPlayerEffects; using Generators; @@ -11,6 +12,8 @@ using RoundRestarting; using System; using System.Collections.Generic; +using System.Linq; +using System.Text; using UnityEngine; using static BanHandler; @@ -361,7 +364,7 @@ public static bool IsPlayerBanned(string value) /// <summary> /// Gets all banned players. /// </summary> - /// <returns>List of all banned players.</returns> + /// <returns>A pooled list of all banned players.</returns> public static List<BanDetails> GetAllBannedPlayers() { List<BanDetails> bans = ListPool<BanDetails>.Shared.Rent(); @@ -374,7 +377,7 @@ public static List<BanDetails> GetAllBannedPlayers() /// Gets all banned players by ban type. /// </summary> /// <param name="banType">The type of ban.</param> - /// <returns>List of specified ban types.</returns> + /// <returns>A pooled list of specified ban types.</returns> public static List<BanDetails> GetAllBannedPlayers(BanType banType) => GetBans(banType); #endregion @@ -446,6 +449,41 @@ public static void SendBroadcast(Player player, string message, ushort duration, Broadcast.Singleton.TargetAddElement(player.Connection, message, duration, type); } + /// <summary> + /// Sends the admin chat messages to all players with <see cref="PlayerPermissions.AdminChat"/> permissions. + /// </summary> + /// <param name="message">The message to send.</param> + /// <param name="isSilent">Whether the message should not appear in broadcast.</param> + public static void SendAdminChatMessage(string message, bool isSilent = false) => SendAdminChatMessage(Player.ReadyList.Where(static n => n.UserGroup != null && PermissionsHandler.IsPermitted(n.UserGroup.Permissions, PlayerPermissions.AdminChat)), message, isSilent); + + /// <summary> + /// Sends admin chat message to all specified players. + /// </summary> + /// <param name="targetPlayers">The target players.</param> + /// <param name="message">The message to send.</param> + /// <param name="isSilent">Whether the message should not appear in broadcast.</param> + public static void SendAdminChatMessage(IEnumerable<Player> targetPlayers, string message, bool isSilent = false) + { + StringBuilder sb = StringBuilderPool.Shared.Rent(); + + sb.Append(Host.NetworkId); + sb.Append('!'); + + if (isSilent) + sb.Append("@@"); + + sb.Append(message); + + string toSend = StringBuilderPool.Shared.ToStringReturn(sb); + foreach (Player player in targetPlayers) + { + if (!player.IsPlayer || !player.IsReady) + continue; + + player.ReferenceHub.encryptedChannelManager.TrySendMessageToClient(toSend, EncryptedChannelManager.EncryptedChannel.AdminChat); + } + } + /// <summary> /// Clears broadcast's for all players. /// </summary> diff --git a/LabApi/Loader/Features/Yaml/CustomConverters/CustomQuaternionConverter.cs b/LabApi/Loader/Features/Yaml/CustomConverters/CustomQuaternionConverter.cs new file mode 100644 index 00000000..07413660 --- /dev/null +++ b/LabApi/Loader/Features/Yaml/CustomConverters/CustomQuaternionConverter.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using YamlDotNet.Serialization; +using UnityEngine; +using System.Globalization; +using UnityEngine.Pool; +using YamlDotNet.Core.Events; +using YamlDotNet.Core; +using LabApi.Loader.Features.Yaml.Extensions; + +namespace LabApi.Loader.Features.Yaml.CustomConverters; + +/// <summary> +/// A custom class for serializing/deserializing <see cref="Quaternion"/> as euler angles. +/// </summary> +public class CustomQuaternionConverter : IYamlTypeConverter +{ + /// <inheritdoc/> + public object? ReadYaml(IParser parser, Type type) + { + parser.Consume<MappingStart>(); + + Dictionary<string, float> storedValues = DictionaryPool<string, float>.Get(); + + try + { + for (int i = 0; i <= 2; i++) + { + if (!parser.TryReadMapping(out string key, out string val)) + throw new ArgumentException($"Unable to parse {nameof(Quaternion)}, no component at index {i} provided"); + + if (!(key is "x" or "y" or "z")) + throw new ArgumentException($"Unable to parse {nameof(Quaternion)}, invalid component name {key}. Only 'x', 'y' and 'z' euler angles are allowed"); + + storedValues[key] = float.Parse(val, CultureInfo.InvariantCulture); + } + parser.Consume<MappingEnd>(); + + Quaternion value = Quaternion.Euler(storedValues["x"], storedValues["y"], storedValues["z"]); + return value; + } + catch (ArgumentException) + { + throw; + } + finally + { + DictionaryPool<string, float>.Release(storedValues); + } + } + + /// <inheritdoc/> + public void WriteYaml(IEmitter emitter, object? value, Type type) + { + Vector3 rotation = ((Quaternion)value).eulerAngles; + emitter.Emit(new MappingStart(AnchorName.Empty, TagName.Empty, isImplicit: true, MappingStyle.Block)); + + emitter.EmitMapping("x", rotation.x.ToString(CultureInfo.InvariantCulture)); + emitter.EmitMapping("y", rotation.y.ToString(CultureInfo.InvariantCulture)); + emitter.EmitMapping("z", rotation.z.ToString(CultureInfo.InvariantCulture)); + + emitter.Emit(new MappingEnd()); + } + + /// <inheritdoc/> + public bool Accepts(Type type) + { + return type == typeof(Quaternion); + } +} diff --git a/LabApi/Loader/Features/Yaml/CustomConverters/CustomVectorConverter.cs b/LabApi/Loader/Features/Yaml/CustomConverters/CustomVectorConverter.cs index 59dcb3a2..e509d9f9 100644 --- a/LabApi/Loader/Features/Yaml/CustomConverters/CustomVectorConverter.cs +++ b/LabApi/Loader/Features/Yaml/CustomConverters/CustomVectorConverter.cs @@ -31,15 +31,12 @@ public class CustomVectorConverter : IYamlTypeConverter if (!parser.TryReadMapping(out string key, out string val)) throw new ArgumentException($"Unable to parse Vector, no component at index {idx} provided"); - if (!(key is "x" or "y" or "z" or "w")) throw new ArgumentException($"Unable to parse Vector, invalid component name {key}. Only 'x' 'y' 'z' and 'w' are allowed"); - if (storedValues.ContainsKey(key)) throw new ArgumentException($"Unable to parse Vector, duplicate component {key}"); - storedValues[key] = float.Parse(val, CultureInfo.InvariantCulture); idx++; } diff --git a/LabApi/Loader/Features/Yaml/YamlConfigParser.cs b/LabApi/Loader/Features/Yaml/YamlConfigParser.cs index 8b6f58ee..af5405dd 100644 --- a/LabApi/Loader/Features/Yaml/YamlConfigParser.cs +++ b/LabApi/Loader/Features/Yaml/YamlConfigParser.cs @@ -23,6 +23,7 @@ public static class YamlConfigParser .WithTypeConverter(new CustomVectorConverter()) .WithTypeConverter(new CustomColor32Converter()) .WithTypeConverter(new CustomColorConverter()) + .WithTypeConverter(new CustomQuaternionConverter()) .Build(); /// <summary> @@ -34,5 +35,6 @@ public static class YamlConfigParser .WithTypeConverter(new CustomVectorConverter()) .WithTypeConverter(new CustomColor32Converter()) .WithTypeConverter(new CustomColorConverter()) + .WithTypeConverter(new CustomQuaternionConverter()) .Build(); } From 708e2d0fa5ce9a89665b39f342e5002fb0026fe6 Mon Sep 17 00:00:00 2001 From: jesusqc <contact@jesusqc.es> Date: Wed, 2 Jul 2025 23:57:53 +0200 Subject: [PATCH 041/215] merge master --- LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs | 5 ----- LabApi/Features/Wrappers/Items/Usable/Scp1576Item.cs | 3 ++- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs index 10180899..d6868c0d 100644 --- a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs +++ b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs @@ -483,11 +483,6 @@ public override void OnPlayerReceivedAchievement(PlayerReceivedAchievementEventA Logger.Info($"{nameof(OnPlayerReceivedAchievement)} triggered by {ev.Player?.UserId ?? "unknown"}"); } - public override void OnPlayerReceivingAchievement(PlayerReceivingAchievementEventArgs ev) - { - Logger.Info($"{nameof(OnPlayerReceivingAchievement)} triggered by {ev.Player?.UserId ?? "unknown"}"); - } - public override void OnPlayerRequestedCustomRaInfo(PlayerRequestedCustomRaInfoEventArgs ev) { Logger.Info($"{nameof(OnPlayerRequestedCustomRaInfo)} triggered by {ev.Player.UserId}"); diff --git a/LabApi/Features/Wrappers/Items/Usable/Scp1576Item.cs b/LabApi/Features/Wrappers/Items/Usable/Scp1576Item.cs index 61b5a49a..4e3fedc0 100644 --- a/LabApi/Features/Wrappers/Items/Usable/Scp1576Item.cs +++ b/LabApi/Features/Wrappers/Items/Usable/Scp1576Item.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; +using CustomPlayerEffects; using BaseScp1576Item = InventorySystem.Items.Usables.Scp1576.Scp1576Item; namespace LabApi.Features.Wrappers; @@ -23,7 +24,7 @@ public class Scp1576Item : UsableItem /// <summary> /// The set of players who are able to transmit their voice to spectators using Scp1576. /// </summary> - public static IEnumerable<Player> TransmitterList => BaseScp1576Item.ValidatedTransmitters.Select(x => Player.Get(x)); + public static IEnumerable<Player> TransmitterList => Player.List.Where(player => player.HasEffect<Scp1576>()); /// <summary> /// The set of players who are able to receive hear spectators talking through Scp1576. From 9dc92c2986bc9f7c5dbf73ceb116b18badbc843b Mon Sep 17 00:00:00 2001 From: David <david.sebesta@post.cz> Date: Sun, 6 Jul 2025 22:27:18 +0200 Subject: [PATCH 042/215] Fix Cache (#268) * Added isActiveAndEnabled check to wrapper CanCache property * cherry pick riptide's stuff Can cache to missing things * Removed IsPrefab from hazard & structure --------- Co-authored-by: brayden-dowson <brayden.dowson@gmail.com> --- .../Features/Wrappers/AdminToys/AdminToy.cs | 20 +++++++++++++------ .../Features/Wrappers/AdminToys/CameraToy.cs | 6 ++++-- .../Wrappers/AdminToys/CapybaraToy.cs | 7 +++++-- .../Wrappers/AdminToys/InteractableToy.cs | 8 +++++--- .../Wrappers/AdminToys/LightSourceToy.cs | 6 ++++-- .../Wrappers/AdminToys/PrimitiveObjectToy.cs | 6 ++++-- .../Wrappers/AdminToys/ShootingTargetToy.cs | 8 +++++--- .../Features/Wrappers/AdminToys/SpeakerToy.cs | 6 ++++-- LabApi/Features/Wrappers/AdminToys/TextToy.cs | 7 +++++-- .../Wrappers/Facility/Doors/BreakableDoor.cs | 4 +++- .../Wrappers/Facility/Doors/BulkheadDoor.cs | 4 +++- .../Wrappers/Facility/Doors/CheckpointDoor.cs | 4 +++- .../Features/Wrappers/Facility/Doors/Door.cs | 16 +++++++++++++-- .../Wrappers/Facility/Doors/ElevatorDoor.cs | 4 +++- .../Features/Wrappers/Facility/Doors/Gate.cs | 4 +++- .../Facility/Doors/NonInteractableDoor.cs | 4 +++- .../Wrappers/Facility/Doors/Timed173Gate.cs | 4 +++- .../Facility/Hazards/AmnesticCloudHazard.cs | 4 +++- .../Facility/Hazards/DecayableHazard.cs | 4 +++- .../Wrappers/Facility/Hazards/Hazard.cs | 9 ++++++++- .../Facility/Hazards/SinkholeHazard.cs | 4 +++- .../Facility/Hazards/TantrumHazard.cs | 3 ++- .../Features/Wrappers/Facility/Rooms/Room.cs | 2 +- .../Structures/ExperimentalWeaponLocker.cs | 4 +++- .../Wrappers/Facility/Structures/Generator.cs | 7 +++++-- .../Facility/Structures/LargeLocker.cs | 3 ++- .../Wrappers/Facility/Structures/Locker.cs | 8 +++++--- .../Facility/Structures/LockerChamber.cs | 4 +++- .../Facility/Structures/MicroPedestal.cs | 4 +++- .../Facility/Structures/PedestalLocker.cs | 4 +++- .../Facility/Structures/RifleRackLocker.cs | 3 ++- .../Facility/Structures/StandardLocker.cs | 3 ++- .../Wrappers/Facility/Structures/Structure.cs | 9 ++++++++- .../Facility/Structures/WallCabinet.cs | 4 +++- .../Facility/Structures/Workstation.cs | 3 +++ LabApi/Features/Wrappers/Items/Item.cs | 2 +- LabApi/Features/Wrappers/Pickups/Pickup.cs | 2 +- LabApi/Features/Wrappers/Players/Ragdoll.cs | 15 +++++++++++++- 38 files changed, 163 insertions(+), 56 deletions(-) diff --git a/LabApi/Features/Wrappers/AdminToys/AdminToy.cs b/LabApi/Features/Wrappers/AdminToys/AdminToy.cs index 507168bd..7e4ce983 100644 --- a/LabApi/Features/Wrappers/AdminToys/AdminToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/AdminToy.cs @@ -1,5 +1,6 @@ using AdminToys; using Generators; +using MapGeneration; using Mirror; using System; using System.Collections.Generic; @@ -53,8 +54,10 @@ internal static void Initialize() /// <param name="adminToyBase">The base object.</param> protected AdminToy(AdminToyBase adminToyBase) { - Dictionary.Add(adminToyBase, this); Base = adminToyBase; + + if (CanCache) + Dictionary.Add(adminToyBase, this); } /// <summary> @@ -64,6 +67,11 @@ internal virtual void OnRemove() { } + /// <summary> + /// Whether to cache this wrapper. + /// </summary> + protected bool CanCache => !IsDestroyed && Base.isActiveAndEnabled; + /// <summary> /// The <see cref="AdminToyBase">base</see> object. /// </summary> @@ -92,7 +100,7 @@ internal virtual void OnRemove() /// Position is relative to its parent if it has one, otherwise its the world position. /// </summary> /// <remarks> - /// If <see cref="IsStatic"/> is true client wont update its position. + /// If <see cref="IsStatic"/> is <see langword="true"/> client wont update its position. /// </remarks> public Vector3 Position { @@ -105,7 +113,7 @@ public Vector3 Position /// Rotation is relative to its parent if it has one, otherwise its the world rotation. /// </summary> /// <remarks> - /// If <see cref="IsStatic"/> is true client wont update its rotation. + /// If <see cref="IsStatic"/> is <see langword="true"/> client wont update its rotation. /// </remarks> public Quaternion Rotation { @@ -118,7 +126,7 @@ public Quaternion Rotation /// Scale is relative to its parent if it has one, otherwise its the world scale. /// </summary> /// <remarks> - /// If <see cref="IsStatic"/> is true client wont update its scale. + /// If <see cref="IsStatic"/> is <see langword="true"/> client wont update its scale. /// </remarks> public Vector3 Scale { @@ -132,7 +140,7 @@ public Vector3 Scale /// <remarks> /// If the parent object contains a <see cref="NetworkIdentity"/> component and has been <see cref="NetworkServer.Spawn(GameObject, GameObject)"/> the parent is synced with the client. /// <para> - /// Can be used even if <see cref="IsStatic"/> is true. + /// Can be used even if <see cref="IsStatic"/> is <see langword="true"/>. /// When changing parent the toys relative <see cref="Position"/>, <see cref="Rotation"/> and <see cref="Scale"/> are retained. /// Note that if the parent has <see cref="NetworkServer.Destroy"/> called on it this object automatically has <see cref="NetworkServer.Destroy"/> called on itself. /// To prevent destruction make sure you unparent it before that happens. @@ -166,7 +174,7 @@ public byte MovementSmoothing /// </summary> /// <remarks> /// A static admin toy will not process <see cref="Position"/>, <see cref="Rotation"/> or <see cref="Scale"/> on both server and client drastically increasing performance. - /// <see cref="Parent"/> can still be used even if static is true. + /// <see cref="Parent"/> can still be used even if static is <see langword="true"/>. /// </remarks> public bool IsStatic { diff --git a/LabApi/Features/Wrappers/AdminToys/CameraToy.cs b/LabApi/Features/Wrappers/AdminToys/CameraToy.cs index 6e996156..92af8fa4 100644 --- a/LabApi/Features/Wrappers/AdminToys/CameraToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/CameraToy.cs @@ -24,11 +24,13 @@ public class CameraToy : AdminToy /// An internal constructor to prevent external instantiation. /// </summary> /// <param name="baseCameraToy">The base <see cref="Scp079CameraToy"/> object.</param> - internal CameraToy(Scp079CameraToy baseCameraToy) + internal CameraToy(Scp079CameraToy baseCameraToy) : base(baseCameraToy) { - Dictionary.Add(baseCameraToy, this); Base = baseCameraToy; + + if (CanCache) + Dictionary.Add(baseCameraToy, this); } /// <summary> diff --git a/LabApi/Features/Wrappers/AdminToys/CapybaraToy.cs b/LabApi/Features/Wrappers/AdminToys/CapybaraToy.cs index 28630112..ae38b80d 100644 --- a/LabApi/Features/Wrappers/AdminToys/CapybaraToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/CapybaraToy.cs @@ -24,10 +24,13 @@ public class CapybaraToy : AdminToy /// An internal constructor to prevent external instantiation. /// </summary> /// <param name="baseCapybaraToy">The base <see cref="BaseCapybaraToy"/> object.</param> - internal CapybaraToy(BaseCapybaraToy baseCapybaraToy) : base(baseCapybaraToy) + internal CapybaraToy(BaseCapybaraToy baseCapybaraToy) + : base(baseCapybaraToy) { - Dictionary.Add(baseCapybaraToy, this); Base = baseCapybaraToy; + + if (CanCache) + Dictionary.Add(baseCapybaraToy, this); } /// <summary> diff --git a/LabApi/Features/Wrappers/AdminToys/InteractableToy.cs b/LabApi/Features/Wrappers/AdminToys/InteractableToy.cs index 6a1d7e24..0bc5381a 100644 --- a/LabApi/Features/Wrappers/AdminToys/InteractableToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/InteractableToy.cs @@ -25,11 +25,13 @@ public class InteractableToy : AdminToy /// An internal constructor to prevent external instantiation. /// </summary> /// <param name="baseInteractableToy">The base <see cref="InvisibleInteractableToy"/> object.</param> - internal InteractableToy(InvisibleInteractableToy baseInteractableToy) - :base(baseInteractableToy) + internal InteractableToy(InvisibleInteractableToy baseInteractableToy) + : base(baseInteractableToy) { - Dictionary.Add(baseInteractableToy, this); Base = baseInteractableToy; + + if (CanCache) + Dictionary.Add(baseInteractableToy, this); } /// <summary> diff --git a/LabApi/Features/Wrappers/AdminToys/LightSourceToy.cs b/LabApi/Features/Wrappers/AdminToys/LightSourceToy.cs index b428c2fa..8a0f4c78 100644 --- a/LabApi/Features/Wrappers/AdminToys/LightSourceToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/LightSourceToy.cs @@ -24,11 +24,13 @@ public class LightSourceToy : AdminToy /// An internal constructor to prevent external instantiation. /// </summary> /// <param name="baseLightSourceToy">The base <see cref="BaseLightSourceToy"/> object.</param> - internal LightSourceToy(BaseLightSourceToy baseLightSourceToy) + internal LightSourceToy(BaseLightSourceToy baseLightSourceToy) : base(baseLightSourceToy) { - Dictionary.Add(baseLightSourceToy, this); Base = baseLightSourceToy; + + if (CanCache) + Dictionary.Add(baseLightSourceToy, this); } /// <summary> diff --git a/LabApi/Features/Wrappers/AdminToys/PrimitiveObjectToy.cs b/LabApi/Features/Wrappers/AdminToys/PrimitiveObjectToy.cs index 62196bf9..cfc78642 100644 --- a/LabApi/Features/Wrappers/AdminToys/PrimitiveObjectToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/PrimitiveObjectToy.cs @@ -25,11 +25,13 @@ public class PrimitiveObjectToy : AdminToy /// An internal constructor to prevent external instantiation. /// </summary> /// <param name="basePrimitiveObjectToy">The base <see cref="BasePrimitiveObjectToy"/> object.</param> - internal PrimitiveObjectToy(BasePrimitiveObjectToy basePrimitiveObjectToy) + internal PrimitiveObjectToy(BasePrimitiveObjectToy basePrimitiveObjectToy) : base(basePrimitiveObjectToy) { - Dictionary.Add(basePrimitiveObjectToy, this); Base = basePrimitiveObjectToy; + + if (CanCache) + Dictionary.Add(basePrimitiveObjectToy, this); } /// <summary> diff --git a/LabApi/Features/Wrappers/AdminToys/ShootingTargetToy.cs b/LabApi/Features/Wrappers/AdminToys/ShootingTargetToy.cs index 4699f031..2fd18ac7 100644 --- a/LabApi/Features/Wrappers/AdminToys/ShootingTargetToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/ShootingTargetToy.cs @@ -24,13 +24,15 @@ public class ShootingTargetToy : AdminToy /// An internal constructor to prevent external instantiation. /// </summary> /// <param name="shootingTarget">The base <see cref="ShootingTarget"/> object.</param> - internal ShootingTargetToy(ShootingTarget shootingTarget) + internal ShootingTargetToy(ShootingTarget shootingTarget) : base(shootingTarget) { - Dictionary.Add(shootingTarget, this); Base = shootingTarget; + + if (CanCache) + Dictionary.Add(shootingTarget, this); } - + /// <summary> /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> diff --git a/LabApi/Features/Wrappers/AdminToys/SpeakerToy.cs b/LabApi/Features/Wrappers/AdminToys/SpeakerToy.cs index 8e6dc5df..ccd557a1 100644 --- a/LabApi/Features/Wrappers/AdminToys/SpeakerToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/SpeakerToy.cs @@ -30,11 +30,13 @@ public class SpeakerToy : AdminToy /// An internal constructor to prevent external instantiation. /// </summary> /// <param name="baseSpeakerToy">The base <see cref="BaseSpeakerToy"/> object.</param> - internal SpeakerToy(BaseSpeakerToy baseSpeakerToy) + internal SpeakerToy(BaseSpeakerToy baseSpeakerToy) : base(baseSpeakerToy) { - Dictionary.Add(baseSpeakerToy, this); Base = baseSpeakerToy; + + if (CanCache) + Dictionary.Add(baseSpeakerToy, this); } /// <summary> diff --git a/LabApi/Features/Wrappers/AdminToys/TextToy.cs b/LabApi/Features/Wrappers/AdminToys/TextToy.cs index 392d1643..0ae7714e 100644 --- a/LabApi/Features/Wrappers/AdminToys/TextToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/TextToy.cs @@ -26,10 +26,13 @@ public class TextToy : AdminToy /// An internal constructor to prevent external instantiation. /// </summary> /// <param name="baseToy">The base <see cref="BaseTextToy"/> object.</param> - internal TextToy(BaseTextToy baseToy) : base(baseToy) + internal TextToy(BaseTextToy baseToy) + : base(baseToy) { Base = baseToy; - Dictionary.Add(baseToy, this); + + if (CanCache) + Dictionary.Add(baseToy, this); } /// <summary> diff --git a/LabApi/Features/Wrappers/Facility/Doors/BreakableDoor.cs b/LabApi/Features/Wrappers/Facility/Doors/BreakableDoor.cs index 03d0d0f3..08bbba34 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/BreakableDoor.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/BreakableDoor.cs @@ -27,8 +27,10 @@ public class BreakableDoor : Door internal BreakableDoor(BaseBreakableDoor baseBreakableDoor) : base(baseBreakableDoor) { - Dictionary.Add(baseBreakableDoor, this); Base = baseBreakableDoor; + + if (CanCache) + Dictionary.Add(baseBreakableDoor, this); } /// <summary> diff --git a/LabApi/Features/Wrappers/Facility/Doors/BulkheadDoor.cs b/LabApi/Features/Wrappers/Facility/Doors/BulkheadDoor.cs index e9d46f47..e85765de 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/BulkheadDoor.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/BulkheadDoor.cs @@ -27,11 +27,13 @@ public class BulkheadDoor : Gate internal BulkheadDoor(PryableDoor pryableDoor) : base(pryableDoor) { - Dictionary.Add(pryableDoor, this); Base = pryableDoor; DoorCrusherExtension extension = pryableDoor.gameObject.GetComponent<DoorCrusherExtension>(); if (extension != null) Crusher = new DoorCrusher(extension); + + if (CanCache) + Dictionary.Add(pryableDoor, this); } /// <summary> diff --git a/LabApi/Features/Wrappers/Facility/Doors/CheckpointDoor.cs b/LabApi/Features/Wrappers/Facility/Doors/CheckpointDoor.cs index 4eeff4bd..ad970c42 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/CheckpointDoor.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/CheckpointDoor.cs @@ -29,12 +29,14 @@ public class CheckpointDoor : Door internal CheckpointDoor(BaseCheckpointDoor baseCheckpointDoor) : base(baseCheckpointDoor) { - Dictionary.Add(baseCheckpointDoor, this); Base = baseCheckpointDoor; SubDoors = new Door[baseCheckpointDoor.SubDoors.Length]; for (int i = 0; i < baseCheckpointDoor.SubDoors.Length; i++) SubDoors[i] = Get(baseCheckpointDoor.SubDoors[i]); + + if (CanCache) + Dictionary.Add(baseCheckpointDoor, this); } /// <summary> diff --git a/LabApi/Features/Wrappers/Facility/Doors/Door.cs b/LabApi/Features/Wrappers/Facility/Doors/Door.cs index 961937a9..98dca4a0 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/Door.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/Door.cs @@ -98,9 +98,11 @@ internal static void Initialize() /// <param name="doorVariant">The <see cref="DoorVariant"/> of the door.</param> protected Door(DoorVariant doorVariant) { - Dictionary.Add(doorVariant, this); Base = doorVariant; + if (CanCache) + Dictionary.Add(doorVariant, this); + if (doorVariant.TryGetComponent(out DoorNametagExtension nametag) && !string.IsNullOrEmpty(nametag.GetName)) { if (doorNameDictionary.TryGetValue(nametag.GetName, out DoorName doorName)) @@ -118,13 +120,23 @@ internal virtual void OnRemove() Dictionary.Remove(Base); } + /// <summary> + /// Whether the door has been destroyed, see <see cref="UnityEngine.Object.DestroyObject(UnityEngine.Object)"/>. + /// </summary> + public bool IsDestroyed => Base == null; + + /// <summary> + /// Whether the wrapper can be cached. + /// </summary> + protected bool CanCache => !IsDestroyed && Base.isActiveAndEnabled; + /// <summary> /// The base object. /// </summary> public DoorVariant Base { get; } /// <summary> - /// Gets the <see cref="Enums.DoorName"/> of the door. + /// Gets the <see cref="Enums.DoorName"/> of the door.s /// </summary> /// <remarks> /// Is the enum version of <see cref="NameTag"/>. diff --git a/LabApi/Features/Wrappers/Facility/Doors/ElevatorDoor.cs b/LabApi/Features/Wrappers/Facility/Doors/ElevatorDoor.cs index b0e586b8..5b34eb14 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/ElevatorDoor.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/ElevatorDoor.cs @@ -28,8 +28,10 @@ public class ElevatorDoor : Door internal ElevatorDoor(BaseElevatorDoor baseElevatorDoor) : base(baseElevatorDoor) { - Dictionary.Add(baseElevatorDoor, this); Base = baseElevatorDoor; + + if (CanCache) + Dictionary.Add(baseElevatorDoor, this); } /// <summary> diff --git a/LabApi/Features/Wrappers/Facility/Doors/Gate.cs b/LabApi/Features/Wrappers/Facility/Doors/Gate.cs index da0e144c..d05b5ad8 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/Gate.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/Gate.cs @@ -26,8 +26,10 @@ public class Gate : Door internal Gate(PryableDoor pryableDoor) : base(pryableDoor) { - Dictionary.Add(pryableDoor, this); Base = pryableDoor; + + if (CanCache) + Dictionary.Add(pryableDoor, this); } /// <summary> diff --git a/LabApi/Features/Wrappers/Facility/Doors/NonInteractableDoor.cs b/LabApi/Features/Wrappers/Facility/Doors/NonInteractableDoor.cs index 632e7a03..f2006c33 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/NonInteractableDoor.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/NonInteractableDoor.cs @@ -26,8 +26,10 @@ public class NonInteractableDoor : Door internal NonInteractableDoor(BasicNonInteractableDoor basicNonInteractableDoor) : base(basicNonInteractableDoor) { - Dictionary.Add(basicNonInteractableDoor, this); Base = basicNonInteractableDoor; + + if (CanCache) + Dictionary.Add(basicNonInteractableDoor, this); } /// <summary> diff --git a/LabApi/Features/Wrappers/Facility/Doors/Timed173Gate.cs b/LabApi/Features/Wrappers/Facility/Doors/Timed173Gate.cs index 1c9f63ee..6384f570 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/Timed173Gate.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/Timed173Gate.cs @@ -30,8 +30,10 @@ public class Timed173Gate : Gate internal Timed173Gate(Timed173PryableDoor timed173PryableDoor) : base(timed173PryableDoor) { - Dictionary.Add(timed173PryableDoor, this); Base = timed173PryableDoor; + + if (CanCache) + Dictionary.Add(timed173PryableDoor, this); } /// <summary> diff --git a/LabApi/Features/Wrappers/Facility/Hazards/AmnesticCloudHazard.cs b/LabApi/Features/Wrappers/Facility/Hazards/AmnesticCloudHazard.cs index 85686f90..b23cafd3 100644 --- a/LabApi/Features/Wrappers/Facility/Hazards/AmnesticCloudHazard.cs +++ b/LabApi/Features/Wrappers/Facility/Hazards/AmnesticCloudHazard.cs @@ -100,7 +100,9 @@ internal AmnesticCloudHazard(Scp939AmnesticCloudInstance hazard) : base(hazard) { Base = hazard; - Dictionary.Add(hazard, this); + + if (CanCache) + Dictionary.Add(hazard, this); } /// <summary> diff --git a/LabApi/Features/Wrappers/Facility/Hazards/DecayableHazard.cs b/LabApi/Features/Wrappers/Facility/Hazards/DecayableHazard.cs index 9f16f9a1..b78d6eff 100644 --- a/LabApi/Features/Wrappers/Facility/Hazards/DecayableHazard.cs +++ b/LabApi/Features/Wrappers/Facility/Hazards/DecayableHazard.cs @@ -62,7 +62,9 @@ protected DecayableHazard(TemporaryHazard hazard) : base(hazard) { Base = hazard; - Dictionary.Add(hazard, this); + + if (CanCache) + Dictionary.Add(hazard, this); } /// <summary> diff --git a/LabApi/Features/Wrappers/Facility/Hazards/Hazard.cs b/LabApi/Features/Wrappers/Facility/Hazards/Hazard.cs index 70a2ff5a..91a39baf 100644 --- a/LabApi/Features/Wrappers/Facility/Hazards/Hazard.cs +++ b/LabApi/Features/Wrappers/Facility/Hazards/Hazard.cs @@ -47,6 +47,11 @@ public class Hazard /// </summary> public IEnumerable<Player> AffectedPlayers => Base.AffectedPlayers.Select(n => Player.Get(n)); + /// <summary> + /// Whether to cache the wrapper. + /// </summary> + protected bool CanCache => !IsDestroyed && Base.isActiveAndEnabled; + /// <summary> /// Gets or sets the maximum distance players have to be at, for this hazard to affect them. /// </summary> @@ -109,7 +114,9 @@ public virtual Vector3 SourcePosition protected Hazard(EnvironmentalHazard hazard) { Base = hazard; - Dictionary.Add(hazard, this); + + if (CanCache) + Dictionary.Add(hazard, this); } /// <summary> diff --git a/LabApi/Features/Wrappers/Facility/Hazards/SinkholeHazard.cs b/LabApi/Features/Wrappers/Facility/Hazards/SinkholeHazard.cs index 3264a331..d77c9a80 100644 --- a/LabApi/Features/Wrappers/Facility/Hazards/SinkholeHazard.cs +++ b/LabApi/Features/Wrappers/Facility/Hazards/SinkholeHazard.cs @@ -40,7 +40,9 @@ internal SinkholeHazard(SinkholeEnvironmentalHazard hazard) : base(hazard) { Base = hazard; - Dictionary.Add(hazard, this); + + if (CanCache) + Dictionary.Add(hazard, this); } /// <summary> diff --git a/LabApi/Features/Wrappers/Facility/Hazards/TantrumHazard.cs b/LabApi/Features/Wrappers/Facility/Hazards/TantrumHazard.cs index 21430d7d..4f9ed6b5 100644 --- a/LabApi/Features/Wrappers/Facility/Hazards/TantrumHazard.cs +++ b/LabApi/Features/Wrappers/Facility/Hazards/TantrumHazard.cs @@ -61,7 +61,8 @@ internal TantrumHazard(TantrumEnvironmentalHazard hazard) { Base = hazard; - Dictionary.Add(hazard, this); + if (CanCache) + Dictionary.Add(hazard, this); } /// <summary> diff --git a/LabApi/Features/Wrappers/Facility/Rooms/Room.cs b/LabApi/Features/Wrappers/Facility/Rooms/Room.cs index 261675d1..6967b25b 100644 --- a/LabApi/Features/Wrappers/Facility/Rooms/Room.cs +++ b/LabApi/Features/Wrappers/Facility/Rooms/Room.cs @@ -203,7 +203,7 @@ public override string ToString() /// <summary> /// Gets whether the room wrapper is allowed to be cached. /// </summary> - protected bool CanCache => !IsDestroyed; + protected bool CanCache => !IsDestroyed && Base.isActiveAndEnabled; private HashSet<Room>? _connectedRooms; diff --git a/LabApi/Features/Wrappers/Facility/Structures/ExperimentalWeaponLocker.cs b/LabApi/Features/Wrappers/Facility/Structures/ExperimentalWeaponLocker.cs index c0f1425a..4311f7d0 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/ExperimentalWeaponLocker.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/ExperimentalWeaponLocker.cs @@ -31,7 +31,9 @@ internal ExperimentalWeaponLocker(BaseExperimentalWeaponLocker baseExperimentalW : base(baseExperimentalWeaponLocker) { Base = baseExperimentalWeaponLocker; - Dictionary.Add(baseExperimentalWeaponLocker, this); + + if (CanCache) + Dictionary.Add(baseExperimentalWeaponLocker, this); } /// <summary> diff --git a/LabApi/Features/Wrappers/Facility/Structures/Generator.cs b/LabApi/Features/Wrappers/Facility/Structures/Generator.cs index 017d68a4..c807f641 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/Generator.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/Generator.cs @@ -35,10 +35,13 @@ public class Generator : Structure internal Generator(Scp079Generator generator) : base(generator) { - Dictionary.Add(generator, this); Base = generator; - TryRegisterByRoom(); + if (CanCache) + { + Dictionary.Add(generator, this); + TryRegisterByRoom(); + } } /// <summary> diff --git a/LabApi/Features/Wrappers/Facility/Structures/LargeLocker.cs b/LabApi/Features/Wrappers/Facility/Structures/LargeLocker.cs index ecd5e3db..e64e6d68 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/LargeLocker.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/LargeLocker.cs @@ -25,7 +25,8 @@ public class LargeLocker : Locker internal LargeLocker(BaseLocker baseLocker) : base(baseLocker) { - Dictionary.Add(baseLocker, this); + if (CanCache) + Dictionary.Add(baseLocker, this); } /// <summary> diff --git a/LabApi/Features/Wrappers/Facility/Structures/Locker.cs b/LabApi/Features/Wrappers/Facility/Structures/Locker.cs index 8e584392..647f6d20 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/Locker.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/Locker.cs @@ -31,9 +31,11 @@ public class Locker : Structure internal Locker(BaseLocker baseLocker) : base(baseLocker) { - Dictionary.Add(baseLocker, this); Base = baseLocker; - Chambers = baseLocker.Chambers.Select(x => LockerChamber.Get(x)).ToArray(); + Chambers = baseLocker.Chambers.Select(static x => LockerChamber.Get(x)).ToArray(); + + if (CanCache) + Dictionary.Add(baseLocker, this); } /// <summary> @@ -118,7 +120,7 @@ public void AddLockerLoot(ItemType type, int remainingUses, int probabilityPoint RemainingUses = remainingUses, ProbabilityPoints = probabilityPoints, MinPerChamber = minPerChamber, - MaxPerChamber= maxPerChamber + MaxPerChamber = maxPerChamber }; Base.Loot = [.. Base.Loot, loot]; diff --git a/LabApi/Features/Wrappers/Facility/Structures/LockerChamber.cs b/LabApi/Features/Wrappers/Facility/Structures/LockerChamber.cs index 13aa667e..80f5e08a 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/LockerChamber.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/LockerChamber.cs @@ -29,10 +29,12 @@ public class LockerChamber /// <param name="id">The id of the chamber inside the locker.</param> internal LockerChamber(BaseLockerChamber baseLockerChamber, Locker locker, byte id) { - Dictionary.Add(baseLockerChamber, this); Base = baseLockerChamber; Locker = locker; Id = id; + + if (locker.CanCache) + Dictionary.Add(baseLockerChamber, this); } /// <summary> diff --git a/LabApi/Features/Wrappers/Facility/Structures/MicroPedestal.cs b/LabApi/Features/Wrappers/Facility/Structures/MicroPedestal.cs index 46ea3352..96ba5b06 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/MicroPedestal.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/MicroPedestal.cs @@ -25,8 +25,10 @@ public class MicroPedestal : Locker /// <param name="pedestal">The base <see cref="Base"/> object.</param> internal MicroPedestal(MicroHIDPedestal pedestal) : base(pedestal) { - Dictionary.Add(pedestal, this); Base = pedestal; + + if (CanCache) + Dictionary.Add(pedestal, this); } /// <summary> diff --git a/LabApi/Features/Wrappers/Facility/Structures/PedestalLocker.cs b/LabApi/Features/Wrappers/Facility/Structures/PedestalLocker.cs index af416467..f7307e17 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/PedestalLocker.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/PedestalLocker.cs @@ -30,7 +30,9 @@ internal PedestalLocker(PedestalScpLocker pedestalScpLocker) : base(pedestalScpLocker) { Base = pedestalScpLocker; - Dictionary.Add(pedestalScpLocker, this); + + if (CanCache) + Dictionary.Add(pedestalScpLocker, this); } /// <summary> diff --git a/LabApi/Features/Wrappers/Facility/Structures/RifleRackLocker.cs b/LabApi/Features/Wrappers/Facility/Structures/RifleRackLocker.cs index faa743d9..af09bdea 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/RifleRackLocker.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/RifleRackLocker.cs @@ -26,7 +26,8 @@ public class RifleRackLocker : Locker internal RifleRackLocker(BaseLocker baseLocker) :base(baseLocker) { - Dictionary.Add(baseLocker, this); + if (CanCache) + Dictionary.Add(baseLocker, this); } /// <summary> diff --git a/LabApi/Features/Wrappers/Facility/Structures/StandardLocker.cs b/LabApi/Features/Wrappers/Facility/Structures/StandardLocker.cs index b8ada6fc..3c893892 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/StandardLocker.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/StandardLocker.cs @@ -25,7 +25,8 @@ public class StandardLocker : Locker internal StandardLocker(BaseLocker baseLocker) : base(baseLocker) { - Dictionary.Add(baseLocker, this); + if (CanCache) + Dictionary.Add(baseLocker, this); } /// <summary> diff --git a/LabApi/Features/Wrappers/Facility/Structures/Structure.cs b/LabApi/Features/Wrappers/Facility/Structures/Structure.cs index 69b9b543..7e10c1ab 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/Structure.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/Structure.cs @@ -62,9 +62,11 @@ internal static void Initialize() /// <param name="spawnableStructure">The base <see cref="SpawnableStructure"/> object.</param> internal Structure(SpawnableStructure spawnableStructure) { - Dictionary.Add(spawnableStructure, this); Base = spawnableStructure; StructurePositionSync = Base.gameObject.GetComponent<StructurePositionSync>(); + + if (CanCache) + Dictionary.Add(spawnableStructure, this); } /// <summary> @@ -75,6 +77,11 @@ internal virtual void OnRemove() Dictionary.Remove(Base); } + /// <summary> + /// Whether to cache the wrapper. + /// </summary> + protected internal bool CanCache => !IsDestroyed && Base.isActiveAndEnabled; + /// <summary> /// The base <see cref="SpawnableStructure"/> object. /// </summary> diff --git a/LabApi/Features/Wrappers/Facility/Structures/WallCabinet.cs b/LabApi/Features/Wrappers/Facility/Structures/WallCabinet.cs index f22ab7e6..ab26423f 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/WallCabinet.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/WallCabinet.cs @@ -1,4 +1,5 @@ using Interactables.Interobjects.DoorUtils; +using MapGeneration.Distributors; using System.Collections.Generic; using BaseLocker = MapGeneration.Distributors.Locker; @@ -26,7 +27,8 @@ public class WallCabinet : Locker internal WallCabinet(BaseLocker baseLocker) : base(baseLocker) { - Dictionary.Add(baseLocker, this); + if (CanCache) + Dictionary.Add(baseLocker, this); } /// <summary> diff --git a/LabApi/Features/Wrappers/Facility/Structures/Workstation.cs b/LabApi/Features/Wrappers/Facility/Structures/Workstation.cs index e947221f..4d8b952e 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/Workstation.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/Workstation.cs @@ -30,6 +30,9 @@ public class Workstation : Structure internal Workstation(SpawnableStructure spawnableStructure) : base(spawnableStructure) { BaseController = spawnableStructure.GetComponent<WorkstationController>(); + + if (CanCache) + Dictionary.Add(spawnableStructure, this); } /// <summary> diff --git a/LabApi/Features/Wrappers/Items/Item.cs b/LabApi/Features/Wrappers/Items/Item.cs index d327bf8d..088c79f6 100644 --- a/LabApi/Features/Wrappers/Items/Item.cs +++ b/LabApi/Features/Wrappers/Items/Item.cs @@ -210,7 +210,7 @@ public ItemThrowSettings ThrowSettings /// <summary> /// Gets whether the item wrapper is allowed to be cached. /// </summary> - protected bool CanCache => !IsDestroyed && !IsPrefab && Serial != 0; + protected bool CanCache => !IsDestroyed && !IsPrefab && Serial != 0 && Base.isActiveAndEnabled; /// <summary> /// A private constructor to prevent external instantiation. diff --git a/LabApi/Features/Wrappers/Pickups/Pickup.cs b/LabApi/Features/Wrappers/Pickups/Pickup.cs index 855044a1..7836090a 100644 --- a/LabApi/Features/Wrappers/Pickups/Pickup.cs +++ b/LabApi/Features/Wrappers/Pickups/Pickup.cs @@ -217,7 +217,7 @@ public Quaternion Rotation /// <summary> /// Gets whether the item wrapper is allowed to be cached. /// </summary> - protected bool CanCache => !IsDestroyed && !IsPrefab; + protected bool CanCache => !IsDestroyed && !IsPrefab && Base.isActiveAndEnabled; /// <summary> /// A protected constructor to prevent external instantiation. diff --git a/LabApi/Features/Wrappers/Players/Ragdoll.cs b/LabApi/Features/Wrappers/Players/Ragdoll.cs index 3494bb97..12f39027 100644 --- a/LabApi/Features/Wrappers/Players/Ragdoll.cs +++ b/LabApi/Features/Wrappers/Players/Ragdoll.cs @@ -32,7 +32,9 @@ public class Ragdoll private Ragdoll(BasicRagdoll ragdoll) { Base = ragdoll; - Dictionary.TryAdd(ragdoll, this); + + if (CanCache) + Dictionary.TryAdd(ragdoll, this); } /// <summary> @@ -40,6 +42,11 @@ private Ragdoll(BasicRagdoll ragdoll) /// </summary> public BasicRagdoll Base { get; private set; } + /// <summary> + /// Gets whether the base room instance was destroyed. + /// </summary> + public bool IsDestroyed => Base == null; + /// <summary> /// Gets or sets the role info of the ragdoll. /// <para>This does NOT change the ragdoll visually.</para> @@ -127,6 +134,12 @@ public bool IsConsumed } } + /// <summary> + /// Whether to cache this wrapper. + /// </summary> + protected bool CanCache => !IsDestroyed && Base.isActiveAndEnabled; + + /// <summary> /// Gets whether the ragdoll is revivable by SCP-049 player. /// </summary> From b57069aec7c1fab8df137af7acca96b756bf4f50 Mon Sep 17 00:00:00 2001 From: brayden-dowson <88667957+brayden-dowson@users.noreply.github.com> Date: Tue, 8 Jul 2025 01:07:46 +0930 Subject: [PATCH 043/215] Adds reload plugin config command (#255) * init * applied suggestions * merge conflicts * tabs to spaces --------- Co-authored-by: jesusqc <contact@jesusqc.es> --- .../Commands/Extensions/CommandExtensions.cs | 38 ++++++++++++ .../Features/Commands/LabApiParentCommand.cs | 29 +++++++++ .../Commands/PluginPermissionsCommand.cs | 15 ++--- .../Commands/Reload/ConfigsCommand.cs | 62 +++++++++++++++++++ .../Commands/Reload/ReloadParentCommand.cs | 29 +++++++++ 5 files changed, 166 insertions(+), 7 deletions(-) create mode 100644 LabApi/Loader/Features/Commands/Extensions/CommandExtensions.cs create mode 100644 LabApi/Loader/Features/Commands/LabApiParentCommand.cs rename LabApi/{Features/Permissions => Loader/Features}/Commands/PluginPermissionsCommand.cs (71%) create mode 100644 LabApi/Loader/Features/Commands/Reload/ConfigsCommand.cs create mode 100644 LabApi/Loader/Features/Commands/Reload/ReloadParentCommand.cs diff --git a/LabApi/Loader/Features/Commands/Extensions/CommandExtensions.cs b/LabApi/Loader/Features/Commands/Extensions/CommandExtensions.cs new file mode 100644 index 00000000..f6de6789 --- /dev/null +++ b/LabApi/Loader/Features/Commands/Extensions/CommandExtensions.cs @@ -0,0 +1,38 @@ +using CommandSystem; +using NorthwoodLib.Pools; +using System; +using System.Text; + +namespace LabApi.Loader.Features.Commands.Extensions; + +/// <summary> +/// Extension class for LabAPI commands. +/// </summary> +public static class CommandExtensions +{ + /// <summary> + /// Responds to a parent command execution by listing out all sub commands, and/or printing an invalid arg message if any invalid args were provided. + /// </summary> + /// <param name="parent">The parent command instance.</param> + /// <param name="arguments">The arguments passed to the parent command.</param> + /// <param name="response">The output response.</param> + /// <returns><see langword="true"/> if there were no arguments, otherwise <see langword="false"/>.</returns> + public static bool ListSubCommands(ParentCommand parent, ArraySegment<string> arguments, out string response) + { + StringBuilder sb = StringBuilderPool.Shared.Rent(); + + sb.AppendLine(arguments.Count > 0 + ? $"'{arguments.At(0)}' was not a valid sub command." + : "You must specify a subcommand when executing this command."); + + sb.AppendLine("Valid subcommands:"); + + foreach (ICommand subCommand in parent.AllCommands) + { + sb.AppendLine($" {subCommand.Command} - {subCommand.Description} Aliases [{string.Join(" ", subCommand.Aliases)}]"); + } + + response = StringBuilderPool.Shared.ToStringReturn(sb); + return arguments.Count == 0; + } +} diff --git a/LabApi/Loader/Features/Commands/LabApiParentCommand.cs b/LabApi/Loader/Features/Commands/LabApiParentCommand.cs new file mode 100644 index 00000000..5852db75 --- /dev/null +++ b/LabApi/Loader/Features/Commands/LabApiParentCommand.cs @@ -0,0 +1,29 @@ +using CommandSystem; +using System; +using static LabApi.Loader.Features.Commands.Extensions.CommandExtensions; + +namespace LabApi.Loader.Features.Commands; + +/// <summary> +/// LabAPI parent command used for all LabAPI related subcommands. +/// </summary> +[CommandHandler(typeof(RemoteAdminCommandHandler))] +[CommandHandler(typeof(GameConsoleCommandHandler))] +public class LabApiParentCommand : ParentCommand +{ + /// <inheritdoc /> + public override string Command => "labapi"; + + /// <inheritdoc /> + public override string[] Aliases => ["lab"]; + + /// <inheritdoc /> + public override string Description => "Parent command for all LabAPI subcommands."; + + /// <inheritdoc /> + public override void LoadGeneratedCommands() { } + + /// <inheritdoc /> + protected override bool ExecuteParent(ArraySegment<string> arguments, ICommandSender sender, out string response) + => ListSubCommands(this, arguments, out response); +} diff --git a/LabApi/Features/Permissions/Commands/PluginPermissionsCommand.cs b/LabApi/Loader/Features/Commands/PluginPermissionsCommand.cs similarity index 71% rename from LabApi/Features/Permissions/Commands/PluginPermissionsCommand.cs rename to LabApi/Loader/Features/Commands/PluginPermissionsCommand.cs index dd36d9dd..9d0f92bd 100644 --- a/LabApi/Features/Permissions/Commands/PluginPermissionsCommand.cs +++ b/LabApi/Loader/Features/Commands/PluginPermissionsCommand.cs @@ -1,29 +1,30 @@ +using CommandSystem; +using LabApi.Features.Permissions; using System; using System.Diagnostics.CodeAnalysis; using System.Linq; -using CommandSystem; -namespace LabApi.Features.Permissions.Commands; +namespace LabApi.Loader.Features.Commands; /// <summary> /// Represents a command that allows players to view their plugin permissions. /// </summary> -[CommandHandler(typeof(RemoteAdminCommandHandler))] +[CommandHandler(typeof(LabApiParentCommand))] public class PluginPermissionsCommand : ICommand { /// <inheritdoc cref="ICommand.Command"/> - public string Command { get; } = "pluginpermissions"; + public string Command { get; } = "permissions"; /// <inheritdoc cref="ICommand.Aliases"/> - public string[] Aliases { get; } = ["pp", "pluginperms"]; + public string[] Aliases { get; } = ["p", "perms"]; /// <inheritdoc cref="ICommand.Description"/> - public string Description { get; } = "Views your plugin permissions."; + public string Description { get; } = "Shows your LabAPI plugin permissions."; /// <inheritdoc cref="ICommand.Execute"/> public bool Execute(ArraySegment<string> arguments, ICommandSender sender, [UnscopedRef] out string response) { - response = "You have the following plugin permissions:\n"; + response = "You have the following LabAPI plugin permissions:\n"; foreach ((Type provider, string[] perms) in sender.GetPermissionsByProvider()) { diff --git a/LabApi/Loader/Features/Commands/Reload/ConfigsCommand.cs b/LabApi/Loader/Features/Commands/Reload/ConfigsCommand.cs new file mode 100644 index 00000000..693232e8 --- /dev/null +++ b/LabApi/Loader/Features/Commands/Reload/ConfigsCommand.cs @@ -0,0 +1,62 @@ +using CommandSystem; +using LabApi.Loader.Features.Plugins; +using NorthwoodLib.Pools; +using System; +using System.Text; + +namespace LabApi.Loader.Features.Commands.Reload; + +/// <summary> +/// Represents a command used to reload all plugin configs. +/// </summary> +[CommandHandler(typeof(ReloadParentCommand))] +public class ConfigsCommand : ICommand +{ + /// <inheritdoc /> + public string Command => "configs"; + + /// <inheritdoc /> + public string[] Aliases => ["c", "cfg"]; + + /// <inheritdoc /> + public string Description => "Reloads configs for all LabAPI plugins."; + + /// <inheritdoc /> + public bool Execute(ArraySegment<string> arguments, ICommandSender sender, out string response) + { + if (!sender.CheckPermission(PlayerPermissions.ServerConfigs, out response)) + return false; + + int pluginCount = PluginLoader.Plugins.Count; + if (pluginCount == 0) + { + response = "No LabAPI plugins installed to reload configs for."; + return false; + } + + StringBuilder sb = StringBuilderPool.Shared.Rent(); + sb.AppendLine($"Reloading configs for {pluginCount} plugin{(pluginCount == 1 ? "" : "s")}"); + + int successCount = 0; + bool success = true; + foreach (Plugin plugin in PluginLoader.Plugins.Keys) + { + try + { + plugin.LoadConfigs(); + successCount++; + } + catch (Exception ex) + { + sb.AppendLine($"Failed to reload configs for plugin {plugin} with Exception:\n{ex}"); + success = false; + } + } + + sb.AppendLine($"Successfully reloaded configs for {(successCount == PluginLoader.Plugins.Count ? "all" : $"{successCount}/{PluginLoader.Plugins.Count}")} plugins."); + response = sb.ToString(); + StringBuilderPool.Shared.Return(sb); + + return success; + } +} diff --git a/LabApi/Loader/Features/Commands/Reload/ReloadParentCommand.cs b/LabApi/Loader/Features/Commands/Reload/ReloadParentCommand.cs new file mode 100644 index 00000000..643d5a5d --- /dev/null +++ b/LabApi/Loader/Features/Commands/Reload/ReloadParentCommand.cs @@ -0,0 +1,29 @@ +using CommandSystem; +using System; + +using static LabApi.Loader.Features.Commands.Extensions.CommandExtensions; + +namespace LabApi.Loader.Features.Commands.Reload; + +/// <summary> +/// Reload parent command used for all LabAPI reload related sub commands. +/// </summary> +[CommandHandler(typeof(LabApiParentCommand))] +public class ReloadParentCommand : ParentCommand +{ + /// <inheritdoc /> + public override string Command => "reload"; + + /// <inheritdoc /> + public override string[] Aliases => ["r", "rl"]; + + /// <inheritdoc /> + public override string Description => "Parent command for all reloading related sub commands."; + + /// <inheritdoc /> + public override void LoadGeneratedCommands() { } + + /// <inheritdoc /> + protected override bool ExecuteParent(ArraySegment<string> arguments, ICommandSender sender, out string response) + => ListSubCommands(this, arguments, out response); +} From 0c5427229e1f69382f54ffcc71a3b2484c2362cd Mon Sep 17 00:00:00 2001 From: jesusqc <contact@jesusqc.es> Date: Mon, 7 Jul 2025 17:59:08 +0200 Subject: [PATCH 044/215] fetch master --- LabApi/Features/Wrappers/Facility/Decontamination.cs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Decontamination.cs b/LabApi/Features/Wrappers/Facility/Decontamination.cs index e752786f..d28b258e 100644 --- a/LabApi/Features/Wrappers/Facility/Decontamination.cs +++ b/LabApi/Features/Wrappers/Facility/Decontamination.cs @@ -13,16 +13,7 @@ public static class Decontamination public static DecontaminationStatus Status { get => Singleton.DecontaminationOverride; - set - { - if (value == DecontaminationStatus.Forced) - { - Singleton.ForceDecontamination(); - return; - } - - Singleton.DecontaminationOverride = value; - } + set => Singleton.DecontaminationOverride = value; } /// <summary> From 333333357cdeb19c560aa5847db8efa47d57e75b Mon Sep 17 00:00:00 2001 From: brayden-dowson <88667957+brayden-dowson@users.noreply.github.com> Date: Sat, 12 Jul 2025 07:12:11 +0930 Subject: [PATCH 045/215] More Events (#254) * more events * Added MoveVector to IScp914ItemProcessor and deleted unused IItemProcessor interface * renamed UseItemCompleting to ItemUsageEffectsApplying * Apply suggestions from code review Co-authored-by: Jesus QC <69375249+Jesus-QC@users.noreply.github.com> --------- Co-authored-by: Jesus QC <69375249+Jesus-QC@users.noreply.github.com> --- .../LogAll/LogPlugin/MyCustomEventsHandler.cs | 46 ++++++++++++++ .../Interfaces/Items/IJailbirdEvent.cs | 17 ++++++ .../PlayerChangedBadgeVisibilityEventArgs.cs | 39 ++++++++++++ .../PlayerChangingBadgeVisibilityEventArgs.cs | 43 +++++++++++++ ...PlayerItemUsageEffectsApplyingEventArgs.cs | 42 +++++++++++++ ...PlayerProcessedJailbirdMessageEventArgs.cs | 43 +++++++++++++ ...layerProcessingJailbirdMessageEventArgs.cs | 60 +++++++++++++++++++ .../Scp3114StrangleAbortedEventArgs.cs | 32 ++++++++++ .../Scp3114StrangleAbortingEventArgs.cs | 36 +++++++++++ .../Scp3114StrangleStartedEventArgs.cs | 32 ++++++++++ .../Scp3114StrangleStartingEventArgs.cs | 36 +++++++++++ .../Handlers/PlayerEvents.EventHandlers.cs | 29 +++++++++ .../Handlers/Scp3114Events.EventHandlers.cs | 29 +++++++++ .../Interfaces/IScp914ItemProcessor.cs | 9 +++ .../Facility/Rooms/Scp914/IItemProcessor.cs | 36 ----------- 15 files changed, 493 insertions(+), 36 deletions(-) create mode 100644 LabApi/Events/Arguments/Interfaces/Items/IJailbirdEvent.cs create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerChangedBadgeVisibilityEventArgs.cs create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerChangingBadgeVisibilityEventArgs.cs create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerItemUsageEffectsApplyingEventArgs.cs create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerProcessedJailbirdMessageEventArgs.cs create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerProcessingJailbirdMessageEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp3114Events/Scp3114StrangleAbortedEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp3114Events/Scp3114StrangleAbortingEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp3114Events/Scp3114StrangleStartedEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp3114Events/Scp3114StrangleStartingEventArgs.cs create mode 100644 LabApi/Events/Handlers/Scp3114Events.EventHandlers.cs delete mode 100644 LabApi/Features/Wrappers/Facility/Rooms/Scp914/IItemProcessor.cs diff --git a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs index d6868c0d..1d2a65f4 100644 --- a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs +++ b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs @@ -7,6 +7,7 @@ using LabApi.Events.Arguments.Scp096Events; using LabApi.Events.Arguments.Scp106Events; using LabApi.Events.Arguments.Scp173Events; +using LabApi.Events.Arguments.Scp3114Events; using LabApi.Events.Arguments.Scp914Events; using LabApi.Events.Arguments.Scp939Events; using LabApi.Events.Arguments.ServerEvents; @@ -98,6 +99,16 @@ public override void OnPlayerChangedNickname(PlayerChangedNicknameEventArgs ev) Logger.Info($"{nameof(OnPlayerChangedNickname)} triggered by {ev.Player.UserId}"); } + public override void OnPlayerChangingBadgeVisibility(PlayerChangingBadgeVisibilityEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerChangingBadgeVisibility)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerChangedBadgeVisibility(PlayerChangedBadgeVisibilityEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerChangedBadgeVisibility)} triggered by {ev.Player.UserId}"); + } + public override void OnPlayerChangingRadioRange(PlayerChangingRadioRangeEventArgs ev) { Logger.Info($"{nameof(OnPlayerChangingRadioRange)} triggered by {ev.Player.UserId}"); @@ -458,6 +469,16 @@ public override void OnPlayerPreAuthenticated(PlayerPreAuthenticatedEventArgs ev Logger.Info($"{nameof(OnPlayerPreAuthenticated)} triggered by {ev.UserId}"); } + public override void OnPlayerProcessingJailbirdMessage(PlayerProcessingJailbirdMessageEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerProcessingJailbirdMessage)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerProcessedJailbirdMessage(PlayerProcessedJailbirdMessageEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerProcessedJailbirdMessage)} triggered by {ev.Player.UserId}"); + } + public override void OnPlayerUpdatingEffect(PlayerEffectUpdatingEventArgs ev) { Logger.Info($"{nameof(OnPlayerUpdatingEffect)} triggered by {ev.Player.UserId}"); @@ -753,6 +774,11 @@ public override void OnPlayerUsedItem(PlayerUsedItemEventArgs ev) Logger.Info($"{nameof(OnPlayerUsedItem)} triggered by {ev.Player.UserId}"); } + public override void OnPlayerItemUsageEffectsApplying(PlayerItemUsageEffectsApplyingEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerItemUsageEffectsApplying)} triggered by {ev.Player.UserId}"); + } + public override void OnPlayerTogglingNoclip(PlayerTogglingNoclipEventArgs ev) { Logger.Info($"{nameof(OnPlayerTogglingNoclip)} triggered by {ev.Player.UserId}"); @@ -1123,6 +1149,26 @@ public override void OnScp173PlayedSound(Scp173PlayedSoundEventArgs ev) Logger.Info($"{nameof(OnScp173PlayedSound)} triggered by {ev.Player.UserId}"); } + public override void OnScp3114StrangleAborting(Scp3114StrangleAbortingEventArgs ev) + { + Logger.Info($"{nameof(OnScp3114StrangleAborting)} triggered by {ev.Player.UserId}"); + } + + public override void OnScp3114StrangleAborted(Scp3114StrangleAbortedEventArgs ev) + { + Logger.Info($"{nameof(OnScp3114StrangleAborted)} triggered by {ev.Player.UserId}"); + } + + public override void OnScp3114StrangleStarting(Scp3114StrangleStartingEventArgs ev) + { + Logger.Info($"{nameof(OnScp3114StrangleStarting)} triggered by {ev.Player.UserId}"); + } + + public override void OnScp3114StrangleStarted(Scp3114StrangleStartedEventArgs ev) + { + Logger.Info($"{nameof(OnScp3114StrangleStarted)} triggered by {ev.Player.UserId}"); + } + public override void OnScp914Activating(Scp914ActivatingEventArgs ev) { Logger.Info($"{nameof(OnScp914Activating)} triggered by {ev.Player.UserId}"); diff --git a/LabApi/Events/Arguments/Interfaces/Items/IJailbirdEvent.cs b/LabApi/Events/Arguments/Interfaces/Items/IJailbirdEvent.cs new file mode 100644 index 00000000..8684233c --- /dev/null +++ b/LabApi/Events/Arguments/Interfaces/Items/IJailbirdEvent.cs @@ -0,0 +1,17 @@ +using LabApi.Features.Wrappers; + +namespace LabApi.Events.Arguments.Interfaces.Items; + +/// <summary> +/// Represents an event that involves a jailbird item. +/// </summary> +public interface IJailbirdEvent : IItemEvent +{ + /// <inheritdoc /> + Item? IItemEvent.Item => JailbirdItem; + + /// <summary> + /// The jailbird item that is involved in the event. + /// </summary> + public JailbirdItem? JailbirdItem { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangedBadgeVisibilityEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedBadgeVisibilityEventArgs.cs new file mode 100644 index 00000000..e472ef42 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedBadgeVisibilityEventArgs.cs @@ -0,0 +1,39 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.ChangedBadgeVisibility"/> event. +/// </summary> +public class PlayerChangedBadgeVisibilityEventArgs : EventArgs, IPlayerEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="PlayerChangedBadgeVisibilityEventArgs"/> class. + /// </summary> + /// <param name="hub">The <see cref="ReferenceHub"/> component of the player that changed their badge visibility.</param> + /// <param name="isGlobal">Whether the badge is a global badge.</param> + /// <param name="newVisibility">The new visibility state.</param> + public PlayerChangedBadgeVisibilityEventArgs(ReferenceHub hub, bool isGlobal, bool newVisibility) + { + Player = Player.Get(hub); + IsGlobalBadge = isGlobal; + NewVisibility = newVisibility; + } + + /// <summary> + /// The player that changed their badge visibility. + /// </summary> + public Player Player { get; } + + /// <summary> + /// <see langword="true"/> if the badge is a global badge, otherwise it is a local badge. + /// </summary> + public bool IsGlobalBadge { get; } + + /// <summary> + /// Whether the badge is now visible. + /// </summary> + public bool NewVisibility { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangingBadgeVisibilityEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingBadgeVisibilityEventArgs.cs new file mode 100644 index 00000000..6fb7ee1e --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingBadgeVisibilityEventArgs.cs @@ -0,0 +1,43 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.ChangingBadgeVisibility"/> event. +/// </summary> +public class PlayerChangingBadgeVisibilityEventArgs : EventArgs, IPlayerEvent, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="PlayerChangingBadgeVisibilityEventArgs"/> class. + /// </summary> + /// <param name="hub">The <see cref="ReferenceHub"/> component of the player that is changing their badge visibility.</param> + /// <param name="isGlobal">Whether the badge is a global badge.</param> + /// <param name="newVisibility">The new visibility state.</param> + public PlayerChangingBadgeVisibilityEventArgs(ReferenceHub hub, bool isGlobal, bool newVisibility) + { + Player = Player.Get(hub); + IsGlobalBadge = isGlobal; + NewVisibility = newVisibility; + IsAllowed = true; + } + + /// <summary> + /// The player that is changing their badge visibility. + /// </summary> + public Player Player { get; } + + /// <summary> + /// <see langword="true"/> if the badge is a global badge, otherwise it is a local badge. + /// </summary> + public bool IsGlobalBadge { get; } + + /// <summary> + /// Whether the badge will be visible. + /// </summary> + public bool NewVisibility { get; } + + /// <inheritdoc /> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerItemUsageEffectsApplyingEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerItemUsageEffectsApplyingEventArgs.cs new file mode 100644 index 00000000..32cf63c4 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerItemUsageEffectsApplyingEventArgs.cs @@ -0,0 +1,42 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using BaseUsableItem = InventorySystem.Items.Usables.UsableItem; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.ItemUsageEffectsApplying"/> event. +/// </summary> +public class PlayerItemUsageEffectsApplyingEventArgs : EventArgs, IPlayerEvent, IUsableItemEvent, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="PlayerItemUsageEffectsApplyingEventArgs"/> class. + /// </summary> + /// <param name="hub">The <see cref="ReferenceHub"/> component of the player using the item.</param> + /// <param name="item">The item that is being used.</param> + public PlayerItemUsageEffectsApplyingEventArgs(ReferenceHub hub, BaseUsableItem item) + { + IsAllowed = true; + Player = Player.Get(hub); + UsableItem = UsableItem.Get(item); + } + + /// <summary> + /// Gets the player using the item. + /// </summary> + public Player Player { get; } + + /// <summary> + /// Gets the item that is being used. + /// </summary> + public UsableItem UsableItem { get; } + + /// <summary> + /// Get or sets whether or not to continue the using item process when the event is canceled. + /// </summary> + public bool ContinueProcess { get; set; } + + /// <inheritdoc /> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerProcessedJailbirdMessageEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerProcessedJailbirdMessageEventArgs.cs new file mode 100644 index 00000000..39c692bd --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerProcessedJailbirdMessageEventArgs.cs @@ -0,0 +1,43 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Events.Arguments.Interfaces.Items; +using LabApi.Features.Wrappers; +using System; +using BaseJailbirdItem = InventorySystem.Items.Jailbird.JailbirdItem; +using JailbirdMessageType = InventorySystem.Items.Jailbird.JailbirdMessageType; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.ProcessedJailbirdMessage"/> event. +/// </summary> +public class PlayerProcessedJailbirdMessageEventArgs : EventArgs, IPlayerEvent, IJailbirdEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="PlayerProcessedJailbirdMessageEventArgs"/> class. + /// </summary> + /// <param name="hub">The <see cref="ReferenceHub"/> component of the player that owns the jailbird.</param> + /// <param name="jailbird">Jailbird the message is for.</param> + /// <param name="msg">The message sent by the player for the jailbird.</param> + public PlayerProcessedJailbirdMessageEventArgs(ReferenceHub hub, BaseJailbirdItem jailbird, JailbirdMessageType msg) + { + Player = Player.Get(hub); + JailbirdItem = JailbirdItem.Get(jailbird); + Message = msg; + } + + /// <summary> + /// The owner of the jailbird. + /// </summary> + public Player Player { get; } + + /// <summary> + /// The jailbird item. + /// </summary> + public JailbirdItem JailbirdItem { get; } + + + /// <summary> + /// The <see cref="JailbirdMessageType"/> processed. + /// </summary> + public JailbirdMessageType Message { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerProcessingJailbirdMessageEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerProcessingJailbirdMessageEventArgs.cs new file mode 100644 index 00000000..4e05e939 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerProcessingJailbirdMessageEventArgs.cs @@ -0,0 +1,60 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Events.Arguments.Interfaces.Items; +using LabApi.Features.Wrappers; +using System; +using BaseJailbirdItem = InventorySystem.Items.Jailbird.JailbirdItem; +using JailbirdMessageType = InventorySystem.Items.Jailbird.JailbirdMessageType; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.ProcessingJailbirdMessage"/> event. +/// </summary> +public class PlayerProcessingJailbirdMessageEventArgs : EventArgs, IPlayerEvent, IJailbirdEvent, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="PlayerProcessingJailbirdMessageEventArgs"/> class. + /// </summary> + /// <param name="hub">The <see cref="ReferenceHub"/> component of the player that owns the jailbird.</param> + /// <param name="jailbird">Jailbird the message is for.</param> + /// <param name="msg">The message sent by the player for the jailbird.</param> + /// <param name="allowAttack">Whether an attack is allowed to start.</param> + /// <param name="allowInspect">Whether an inspect is allowed to start.</param> + public PlayerProcessingJailbirdMessageEventArgs(ReferenceHub hub, BaseJailbirdItem jailbird, JailbirdMessageType msg, bool allowAttack, bool allowInspect) + { + Player = Player.Get(hub); + JailbirdItem = JailbirdItem.Get(jailbird); + Message = msg; + AllowAttack = allowAttack; + AllowInspect = allowInspect; + IsAllowed = true; + } + + /// <summary> + /// The owner of the jailbird. + /// </summary> + public Player Player { get; } + + /// <summary> + /// The jailbird item. + /// </summary> + public JailbirdItem JailbirdItem { get; } + + /// <summary> + /// Gets or sets the <see cref="JailbirdMessageType"/> sent by the player. + /// </summary> + public JailbirdMessageType Message { get; set; } + + /// <summary> + /// Gets or sets whether starting an attack is allowed. + /// </summary> + public bool AllowAttack { get; set; } + + /// <summary> + /// Gets or sets whether starting an inspect is allowed. + /// </summary> + public bool AllowInspect { get; set; } + + /// <inheritdoc /> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/Scp3114Events/Scp3114StrangleAbortedEventArgs.cs b/LabApi/Events/Arguments/Scp3114Events/Scp3114StrangleAbortedEventArgs.cs new file mode 100644 index 00000000..fbd89912 --- /dev/null +++ b/LabApi/Events/Arguments/Scp3114Events/Scp3114StrangleAbortedEventArgs.cs @@ -0,0 +1,32 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp3114Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp3114Events.StrangleAborted"/> events. +/// </summary> +public class Scp3114StrangleAbortedEventArgs : EventArgs, IPlayerEvent, ITargetEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp3114StrangleAbortedEventArgs"/> class. + /// </summary> + /// <param name="scp3114Hub">The <see cref="ReferenceHub"/> component of the SCP-3114 player.</param> + /// <param name="targetHub">The <see cref="ReferenceHub"/> component of the target player.</param> + public Scp3114StrangleAbortedEventArgs(ReferenceHub scp3114Hub, ReferenceHub targetHub) + { + Player = Player.Get(scp3114Hub); + Target = Player.Get(targetHub); + } + + /// <summary> + /// The SCP-3114 player. + /// </summary> + public Player Player { get; } + + /// <summary> + /// The strangle target. + /// </summary> + public Player Target { get; } +} diff --git a/LabApi/Events/Arguments/Scp3114Events/Scp3114StrangleAbortingEventArgs.cs b/LabApi/Events/Arguments/Scp3114Events/Scp3114StrangleAbortingEventArgs.cs new file mode 100644 index 00000000..b1543bbf --- /dev/null +++ b/LabApi/Events/Arguments/Scp3114Events/Scp3114StrangleAbortingEventArgs.cs @@ -0,0 +1,36 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp3114Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp3114Events.StrangleAborting"/> events. +/// </summary> +public class Scp3114StrangleAbortingEventArgs : EventArgs, IPlayerEvent, ITargetEvent, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp3114StrangleAbortingEventArgs"/> class. + /// </summary> + /// <param name="scp3114Hub">The <see cref="ReferenceHub"/> component of the SCP-3114 player.</param> + /// <param name="targetHub">The <see cref="ReferenceHub"/> component of the target player.</param> + public Scp3114StrangleAbortingEventArgs(ReferenceHub scp3114Hub, ReferenceHub targetHub) + { + Player = Player.Get(scp3114Hub); + Target = Player.Get(targetHub); + IsAllowed = true; + } + + /// <summary> + /// The SCP-3114 player. + /// </summary> + public Player Player { get; } + + /// <summary> + /// The strangle target. + /// </summary> + public Player Target { get; } + + /// <inheritdoc /> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/Scp3114Events/Scp3114StrangleStartedEventArgs.cs b/LabApi/Events/Arguments/Scp3114Events/Scp3114StrangleStartedEventArgs.cs new file mode 100644 index 00000000..b784b4a6 --- /dev/null +++ b/LabApi/Events/Arguments/Scp3114Events/Scp3114StrangleStartedEventArgs.cs @@ -0,0 +1,32 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp3114Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp3114Events.StrangleStarted"/> events. +/// </summary> +public class Scp3114StrangleStartedEventArgs : EventArgs, IPlayerEvent, ITargetEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp3114StrangleStartedEventArgs"/> class. + /// </summary> + /// <param name="scp3114Hub">The <see cref="ReferenceHub"/> component of the SCP-3114 player.</param> + /// <param name="targetHub">The <see cref="ReferenceHub"/> component of the target player.</param> + public Scp3114StrangleStartedEventArgs(ReferenceHub scp3114Hub, ReferenceHub targetHub) + { + Player = Player.Get(scp3114Hub); + Target = Player.Get(targetHub); + } + + /// <summary> + /// The SCP-3114 player. + /// </summary> + public Player Player { get; } + + /// <summary> + /// The strangle target. + /// </summary> + public Player Target { get; } +} diff --git a/LabApi/Events/Arguments/Scp3114Events/Scp3114StrangleStartingEventArgs.cs b/LabApi/Events/Arguments/Scp3114Events/Scp3114StrangleStartingEventArgs.cs new file mode 100644 index 00000000..96193a0c --- /dev/null +++ b/LabApi/Events/Arguments/Scp3114Events/Scp3114StrangleStartingEventArgs.cs @@ -0,0 +1,36 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp3114Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp3114Events.StrangleStarting"/> events. +/// </summary> +public class Scp3114StrangleStartingEventArgs : EventArgs, IPlayerEvent, ITargetEvent, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp3114StrangleStartingEventArgs"/> class. + /// </summary> + /// <param name="scp3114Hub">The <see cref="ReferenceHub"/> component of the SCP-3114 player.</param> + /// <param name="targetHub">The <see cref="ReferenceHub"/> component of the target player.</param> + public Scp3114StrangleStartingEventArgs(ReferenceHub scp3114Hub, ReferenceHub targetHub) + { + Player = Player.Get(scp3114Hub); + Target = Player.Get(targetHub); + IsAllowed = true; + } + + /// <summary> + /// The SCP-3114 player. + /// </summary> + public Player Player { get; } + + /// <summary> + /// The strangle target. + /// </summary> + public Player Target { get; } + + /// <inheritdoc /> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs b/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs index 1bb99fa1..82d1c30f 100644 --- a/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs +++ b/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs @@ -170,6 +170,20 @@ public static partial class PlayerEvents #endregion + #region Badges + + /// <summary> + /// Gets called when the player is changing their global or local badge visibility. + /// </summary> + public static event LabEventHandler<PlayerChangingBadgeVisibilityEventArgs>? ChangingBadgeVisibility; + + /// <summary> + /// Gets called when the player has changed their global or local badge visibility. + /// </summary> + public static event LabEventHandler<PlayerChangedBadgeVisibilityEventArgs>? ChangedBadgeVisibility; + + #endregion + #region Player properties, inventory and effects /// <summary> @@ -425,6 +439,11 @@ public static partial class PlayerEvents /// </summary> public static event LabEventHandler<PlayerUsedItemEventArgs>? UsedItem; + /// <summary> + /// Gets called when the player is about to complete using an item. + /// </summary> + public static event LabEventHandler<PlayerItemUsageEffectsApplyingEventArgs>? ItemUsageEffectsApplying; + /// <summary> /// Gets called when the player is using the radio. /// </summary> @@ -505,6 +524,16 @@ public static partial class PlayerEvents /// </summary> public static event LabEventHandler<PlayerChangedRadioRangeEventArgs>? ChangedRadioRange; + /// <summary> + /// Gets called when processing a player's interaction with the jailbird item. + /// </summary> + public static event LabEventHandler<PlayerProcessingJailbirdMessageEventArgs>? ProcessingJailbirdMessage; + + /// <summary> + /// Gets called when processed the player's interaction with the jailbird item. + /// </summary> + public static event LabEventHandler<PlayerProcessedJailbirdMessageEventArgs>? ProcessedJailbirdMessage; + /// <summary> /// Gets called when the player is toggling a flashlight. /// </summary> diff --git a/LabApi/Events/Handlers/Scp3114Events.EventHandlers.cs b/LabApi/Events/Handlers/Scp3114Events.EventHandlers.cs new file mode 100644 index 00000000..5ece70bb --- /dev/null +++ b/LabApi/Events/Handlers/Scp3114Events.EventHandlers.cs @@ -0,0 +1,29 @@ +using LabApi.Events.Arguments.Scp3114Events; + +namespace LabApi.Events.Handlers; + +/// <summary> +/// Handles all events related to SCP-3114. +/// </summary> +public static partial class Scp3114Events +{ + /// <summary> + /// Gets called when SCP-3114 is starting to strangle a player. + /// </summary> + public static event LabEventHandler<Scp3114StrangleStartingEventArgs>? StrangleStarting; + + /// <summary> + /// Gets called when SCP-3114 has started to strangle a player. + /// </summary> + public static event LabEventHandler<Scp3114StrangleStartedEventArgs>? StrangleStarted; + + /// <summary> + /// Gets called when SCP-3114 is aborting their strangle on the player. + /// </summary> + public static event LabEventHandler<Scp3114StrangleAbortingEventArgs>? StrangleAborting; + + /// <summary> + /// Gets called when SCP-3114 has aborted their strangle on the player. + /// </summary> + public static event LabEventHandler<Scp3114StrangleAbortedEventArgs>? StrangleAborted; +} \ No newline at end of file diff --git a/LabApi/Features/Interfaces/IScp914ItemProcessor.cs b/LabApi/Features/Interfaces/IScp914ItemProcessor.cs index ce9f8f9f..9e7f4c83 100644 --- a/LabApi/Features/Interfaces/IScp914ItemProcessor.cs +++ b/LabApi/Features/Interfaces/IScp914ItemProcessor.cs @@ -1,5 +1,6 @@ using LabApi.Features.Wrappers; using Scp914; +using UnityEngine; namespace LabApi.Features.Interfaces; @@ -8,6 +9,11 @@ namespace LabApi.Features.Interfaces; /// </summary> public interface IScp914ItemProcessor { + /// <summary> + /// The amount of world space position that needs to be added to move a pickup item from the input chamber to the output chamber. + /// </summary> + public static Vector3 MoveVector => Scp914Controller.MoveVector; + /// <summary> /// Whether to use the <see cref="UpgradePickup"/> for inventory items and skip using <see cref="UpgradeItem"/>. /// </summary> @@ -28,6 +34,9 @@ public interface IScp914ItemProcessor /// <summary> /// Called for each pickup in the intake chamber if the <see cref="Wrappers.Scp914.Mode"/> allows so. /// </summary> + /// <remarks> + /// Add <see cref="MoveVector"/> to the pickups world position to move pickup from the input chamber to the output. + /// </remarks> /// <param name="setting">The <see cref="Scp914KnobSetting"/> used for this upgrade.</param> /// <param name="pickup">The <see cref="Pickup"/> to upgrade.</param> /// <returns>The upgrade result.</returns> diff --git a/LabApi/Features/Wrappers/Facility/Rooms/Scp914/IItemProcessor.cs b/LabApi/Features/Wrappers/Facility/Rooms/Scp914/IItemProcessor.cs deleted file mode 100644 index 24009f2c..00000000 --- a/LabApi/Features/Wrappers/Facility/Rooms/Scp914/IItemProcessor.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Scp914; -using UnityEngine; - -namespace LabApi.Features.Wrappers; - -/// <summary> -/// An interface for creating custom SCP-914 Item upgrade processors. -/// </summary> -public interface IItemProcessor -{ - /// <summary> - /// Called for each players items in the intake chamber of SCP-914 if the <see cref="Scp914.Mode"/> allows so. - /// </summary> - /// <param name="setting">The <see cref="Scp914KnobSetting"/> used for this upgrade.</param> - /// <param name="player">The <see cref="Player"/> that owns this item.</param> - /// <param name="item">The <see cref="Item"/> to upgraded.</param> - /// <returns>The upgraded <see cref="Item"/> or null if it was destroyed.</returns> - /// <remarks> - /// Use <see cref="Player.RemoveItem(Item)"/> to remove items and <see cref="Player.AddItem(ItemType, InventorySystem.Items.ItemAddReason)"/> to add items. - /// If adding extra Items over the limit of the inventory consider dropping them as pickups at the output. - /// </remarks> - public Item? UpgradeItem(Scp914KnobSetting setting, Player player, Item item); - - /// <summary> - /// Called for each pickup in the intake chamber if the <see cref="Scp914.Mode"/> allows so. - /// </summary> - /// <param name="setting">The <see cref="Scp914KnobSetting"/> used for this upgrade.</param> - /// <param name="pickup">The <see cref="Pickup"/> to upgrade.</param> - /// <param name="newPosition">The position to teleport the upgraded pickups to.</param> - /// <returns>The upgraded <see cref="Pickup"/> or null if it was destroyed.</returns> - /// <remarks> - /// Use <see cref="Pickup.Destroy()"/> to remove pickups and <see cref="Pickup.Create(ItemType, Vector3)"/> to add pickups. - /// You can create more than one pickup during a single upgrade similar to items. - /// </remarks> - public Pickup? UpgradePickup(Scp914KnobSetting setting, Pickup pickup, Vector3 newPosition); -} From 45e67e82b82580f0b72280830071e26e10655201 Mon Sep 17 00:00:00 2001 From: David <david.sebesta@post.cz> Date: Fri, 11 Jul 2025 23:46:09 +0200 Subject: [PATCH 046/215] Room Events (#264) * Added room events, Room now uses player cache and added RoomRaw to not use it if someone wants * Room to normal --- .../PlayerRoomChangedEventArgs.cs | 40 +++++++++++++++++++ .../PlayerZoneChangedEventArgs.cs | 40 +++++++++++++++++++ .../Handlers/PlayerEvents.EventHandlers.cs | 11 +++++ LabApi/Features/Wrappers/Players/Player.cs | 19 +++++++-- 4 files changed, 106 insertions(+), 4 deletions(-) create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerRoomChangedEventArgs.cs create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerZoneChangedEventArgs.cs diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerRoomChangedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerRoomChangedEventArgs.cs new file mode 100644 index 00000000..416e51c2 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerRoomChangedEventArgs.cs @@ -0,0 +1,40 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using MapGeneration; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.RoomChanged"/> event. +/// </summary> +public class PlayerRoomChangedEventArgs : EventArgs, IPlayerEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="PlayerRoomChangedEventArgs"/> class. + /// </summary> + /// <param name="player">The player whose room changed.</param> + /// <param name="oldRoom">The old room.</param> + /// <param name="newRoom">The new room</param> + public PlayerRoomChangedEventArgs(ReferenceHub player, RoomIdentifier oldRoom, RoomIdentifier newRoom) + { + Player = Player.Get(player); + OldRoom = Room.Get(oldRoom); + NewRoom = Room.Get(newRoom); + } + + /// <summary> + /// Gets the player whose last known room changed. + /// </summary> + public Player Player { get; } + + /// <summary> + /// Gets the old room. May be null if the player just spawned, went through void and such. + /// </summary> + public Room? OldRoom { get; } + + /// <summary> + /// Gets the new rom. May be null if the player went into void, died and such. + /// </summary> + public Room? NewRoom { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerZoneChangedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerZoneChangedEventArgs.cs new file mode 100644 index 00000000..cde8413a --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerZoneChangedEventArgs.cs @@ -0,0 +1,40 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using MapGeneration; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.ZoneChanged"/> event. +/// </summary> +public class PlayerZoneChangedEventArgs : EventArgs, IPlayerEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="PlayerZoneChangedEventArgs"/> class. + /// </summary> + /// <param name="player">The player whose zone changed.</param> + /// <param name="oldZone">The old zone.</param> + /// <param name="newZone">The new zone</param> + public PlayerZoneChangedEventArgs(ReferenceHub player, FacilityZone oldZone, FacilityZone newZone) + { + Player = Player.Get(player); + OldZone = oldZone; + NewZone = newZone; + } + + /// <summary> + /// Gets the player whose last known room changed. + /// </summary> + public Player Player { get; } + + /// <summary> + /// Gets the old zone. May be <see cref="FacilityZone.None"/> if the player just spawned, went through void and such. + /// </summary> + public FacilityZone OldZone; + + /// <summary> + /// Gets the new rom. May be <see cref="FacilityZone.None"/> if the player went into void, died and such. + /// </summary> + public FacilityZone NewZone; +} diff --git a/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs b/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs index 82d1c30f..0b053ca2 100644 --- a/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs +++ b/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs @@ -1,4 +1,5 @@ using LabApi.Events.Arguments.PlayerEvents; +using MapGeneration; namespace LabApi.Events.Handlers; @@ -818,6 +819,16 @@ public static partial class PlayerEvents /// </summary> public static event LabEventHandler<PlayerReceivedAchievementEventArgs>? ReceivedAchievement; + /// <summary> + /// Gets called when player's last known room changes. + /// </summary> + public static event LabEventHandler<PlayerRoomChangedEventArgs>? RoomChanged; + + /// <summary> + /// Gets called when player's last known zone changes. + /// </summary> + public static event LabEventHandler<PlayerZoneChangedEventArgs>? ZoneChanged; + #endregion #region Spectating diff --git a/LabApi/Features/Wrappers/Players/Player.cs b/LabApi/Features/Wrappers/Players/Player.cs index 2c2e0322..88697680 100644 --- a/LabApi/Features/Wrappers/Players/Player.cs +++ b/LabApi/Features/Wrappers/Players/Player.cs @@ -478,9 +478,20 @@ public Item? CurrentItem public IEnumerable<StatusEffectBase> ActiveEffects => ReferenceHub.playerEffectsController.AllEffects.Where(x => x.Intensity > 0); /// <summary> - /// Gets the <see cref="RoomIdentifier"/> at the player's current position. + /// Gets the <see cref="LabApi.Features.Wrappers.Room"/> at the player's current position. + /// May be <see langword="null"/> if the player is in the void. + /// <para> + /// Player inside of the elevator is consider to be in the said room until the elevator teleports to the next door. + /// </para> + /// </summary> + public Room? Room => Room.TryGetRoomAtPosition(Position, out Room room) ? room : null; + + /// <summary> + /// Gets the cached room of the player. Cached room is revalidated once every frame or when player teleports.<br/> + /// It is not guarantee that the <see cref="Position"/> will match the exact same room it should be in due to the caching.<br/> + /// May be <see langword="null"/> if the player is in the void. /// </summary> - public Room? Room => Room.GetRoomAtPosition(Position); + public Room? CachedRoom => ReferenceHub.TryGetCurrentRoom(out RoomIdentifier rid) ? Room.Get(rid) : null; /// <summary> /// Gets the <see cref="FacilityZone"/> for the player's current room. Returns <see cref="FacilityZone.None"/> if the room is null. @@ -1625,7 +1636,7 @@ private static void AddPlayer(ReferenceHub referenceHub) CreatePlayerWrapper(referenceHub); } - catch(Exception ex) + catch (Exception ex) { Console.Logger.InternalError($"Failed to handle player addition with exception: {ex}"); } @@ -1650,7 +1661,7 @@ private static void RemovePlayer(ReferenceHub referenceHub) Dictionary.Remove(referenceHub); } - catch(Exception ex) + catch (Exception ex) { Console.Logger.InternalError($"Failed to handle player removal with exception: {ex}"); } From 7db90705c644f269795041551ac88f6dea2ee254 Mon Sep 17 00:00:00 2001 From: brayden-dowson <88667957+brayden-dowson@users.noreply.github.com> Date: Sat, 12 Jul 2025 07:19:26 +0930 Subject: [PATCH 047/215] Obsolete IsOffline and IsOnline (#251) --- LabApi/Features/Wrappers/Players/Player.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/LabApi/Features/Wrappers/Players/Player.cs b/LabApi/Features/Wrappers/Players/Player.cs index 88697680..a1dfeaf1 100644 --- a/LabApi/Features/Wrappers/Players/Player.cs +++ b/LabApi/Features/Wrappers/Players/Player.cs @@ -102,7 +102,7 @@ public class Player /// <summary> /// Gets the amount of non-verified players /// </summary> - public static int NonVerifiedCount => ConnectionsCount - Count; + public static int NonVerifiedCount => UnauthenticatedList.Count(); /// <summary> /// Gets the amount of connected players. Regardless of their authentication status. @@ -188,6 +188,11 @@ internal Player(ReferenceHub referenceHub) /// </summary> public NetworkConnection Connection => IsHost ? ReferenceHub.networkIdentity.connectionToServer : ReferenceHub.networkIdentity.connectionToClient; + /// <summary> + /// Gets the player's <see cref="NetworkConnectionToClient"/>. + /// </summary> + public NetworkConnectionToClient ConnectionToClient => ReferenceHub.networkIdentity.connectionToClient; + /// <summary> /// Gets the player's <see cref="RecyclablePlayerId"/> value. /// </summary> @@ -196,11 +201,13 @@ internal Player(ReferenceHub referenceHub) /// <summary> /// Gets if the player is currently offline. /// </summary> + [Obsolete("Use IsDestroyed instead.")] public bool IsOffline => GameObject == null; /// <summary> /// Gets if the player is currently online. /// </summary> + [Obsolete("Use !IsDestroyed instead.")] public bool IsOnline => !IsOffline; /// <summary> From d6871ae8fa0194720ce4258b434551c1ef037ca0 Mon Sep 17 00:00:00 2001 From: Placeholder David <davidsebesta1_placeholder_1e98un7@noreply.git.scpslgame.com> Date: Wed, 16 Jul 2025 14:19:36 +0000 Subject: [PATCH 048/215] Transparently Modded - David --- LabApi/Features/Wrappers/Players/Server.cs | 12 +++++-- LabApi/Loader/Features/Plugins/Plugin.cs | 12 +++++++ LabApi/Loader/PluginLoader.cs | 41 ++++++++++++++++++++-- 3 files changed, 59 insertions(+), 6 deletions(-) diff --git a/LabApi/Features/Wrappers/Players/Server.cs b/LabApi/Features/Wrappers/Players/Server.cs index aee9fd1a..dcc686c4 100644 --- a/LabApi/Features/Wrappers/Players/Server.cs +++ b/LabApi/Features/Wrappers/Players/Server.cs @@ -1,8 +1,6 @@ using Achievements; -using CentralAuth; using CommandSystem; using CustomPlayerEffects; -using Generators; using InventorySystem.Configs; using LabApi.Features.Permissions; using LabApi.Features.Permissions.Providers; @@ -136,7 +134,7 @@ public static bool FriendlyFire public static bool AchievementsEnabled { get => !AchievementManager.AchievementsDisabled; - set + set { if (AchievementManager.AchievementsDisabled != value) return; @@ -176,6 +174,14 @@ public static float PlayerListNameRefreshRate set => PlayerList.RefreshRate.Value = value; } + /// <summary> + /// Gets or sets whether the server has been marked as transparently modded.<br/> + /// For this status to be applied automatically, all installed plugins must have their + /// <see cref="LabApi.Loader.Features.Plugins.Plugin.IsTransparent"/> property set to <see langword="true"/>.<br/> + /// For more information, see article 5.2 in the official documentation: https://scpslgame.com/csg + /// </summary> + public static bool IsTransparentlyModded { get; internal set; } + /// <summary> /// Gets the <see cref="ItemCategory">Category</see> <see cref="ILimit{ItemCategory, SByte}">limits</see>. /// </summary> diff --git a/LabApi/Loader/Features/Plugins/Plugin.cs b/LabApi/Loader/Features/Plugins/Plugin.cs index d6fdd7e1..f7bc33a1 100644 --- a/LabApi/Loader/Features/Plugins/Plugin.cs +++ b/LabApi/Loader/Features/Plugins/Plugin.cs @@ -39,6 +39,18 @@ public abstract class Plugin /// </summary> public virtual LoadPriority Priority { get; } = LoadPriority.Medium; + /// <summary> + /// Whether this plugin is considered transparent.<br/> + /// A plugin can be marked as transparent if the server’s modifications are strictly limited to non-intrusive features that do not affect gameplay balance or make significant alterations to the user interface. + /// Examples of transparent modifications are: admin tools, automated timed broadcasts for tips, message of the day or other administrative utilities.<br/> + /// For more information, see article 5.2 in the official documentation: https://scpslgame.com/csg + /// </summary> + /// <remarks> + /// You can keep using the 'transparently modded' flag during occasional short events organised and supervised by + /// Server Staff, regardless of the Modifications used for these events. + /// </remarks> + public virtual bool IsTransparent { get; } = false; + /// <summary> /// The <see cref="Properties"/> of the <see cref="Plugin"/>. /// </summary> diff --git a/LabApi/Loader/PluginLoader.cs b/LabApi/Loader/PluginLoader.cs index bc3b8ec6..44bf5b2c 100644 --- a/LabApi/Loader/PluginLoader.cs +++ b/LabApi/Loader/PluginLoader.cs @@ -73,9 +73,13 @@ public static void Initialize() // We first load all the dependencies and store them in the dependencies list LoadAllDependencies(); + // Then we load all the plugins and enable them LoadAllPlugins(); + // Resolve the server modded transparency flag + ResolveTransparentlyModdedFlag(); + // We also register the default permissions provider PermissionsManager.RegisterProvider<DefaultPermissionsProvider>(); } @@ -153,7 +157,7 @@ public static void LoadAllPlugins() // Then we finally enable all the plugins Logger.Info($"{LoggerPrefix} Enabling all plugins"); - EnablePlugins(Plugins.Keys.OrderBy(plugin => plugin.Priority)); + EnablePlugins(Plugins.Keys.OrderBy(static plugin => plugin.Priority)); } /// <summary> @@ -257,10 +261,10 @@ public static void EnablePlugin(Plugin plugin) { // We mark the server as modded. CustomNetworkManager.Modded = true; - + // We load the configurations of the plugin plugin.LoadConfigs(); - + // We register all the plugin commands plugin.RegisterCommands(); @@ -307,6 +311,37 @@ private static void LoadLabApiConfig() } } + /// <summary> + /// Resolves whether the installed plugins are marked as transparent and sets the <see cref="Server.IsTransparentlyModded"/> flag based on the result. + /// </summary> + private static void ResolveTransparentlyModdedFlag() + { + if (Plugins.Count == 0) + return; + + if (Server.IsTransparentlyModded) + return; + + bool isTransparent = true; + + foreach (Plugin plugin in Plugins.Keys) + { + if (!plugin.IsTransparent) + { + isTransparent = false; + break; + } + } + + Server.IsTransparentlyModded = isTransparent; + + if (isTransparent) + { + Logger.Raw($"{LoggerPrefix} This server has been flagged as transparently modded by one or more installed plugins. If you believe this is a mistake, please review your installed plugins and contact the plugin developers.", ConsoleColor.Red); + ServerConsole.Update = true; + } + } + private static string ResolvePath(string path) { return path.Replace("$port", Server.Port.ToString()); From 571a6871f0f216280d07ece302a336438c9ab2ff Mon Sep 17 00:00:00 2001 From: Jesus-QC <99-jesusqc@users.noreply.git.scpslgame.com> Date: Thu, 17 Jul 2025 13:29:39 +0200 Subject: [PATCH 049/215] Revert "Merge branch 'theriptide-missing-things' into 'dev'" This reverts merge request !233 --- .../PlayerDroppingItemEventArgs.cs | 2 +- .../Features/Wrappers/Facility/Doors/Door.cs | 57 +++--------------- .../Wrappers/Facility/Doors/ElevatorDoor.cs | 3 +- LabApi/Features/Wrappers/Facility/Elevator.cs | 59 +++---------------- .../Features/Wrappers/Facility/Rooms/Room.cs | 2 +- .../Wrappers/Facility/Rooms/Scp914/Scp914.cs | 2 +- LabApi/Features/Wrappers/Players/Player.cs | 54 +---------------- LabApi/Features/Wrappers/Players/Ragdoll.cs | 15 ----- 8 files changed, 22 insertions(+), 172 deletions(-) diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs index c7601c6f..dc5f3e4d 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.DroppingItem"/> event. /// </summary> -public class PlayerDroppingItemEventArgs : EventArgs, ICancellableEvent, IItemEvent, IPlayerEvent +public class PlayerDroppingItemEventArgs : EventArgs, ICancellableEvent, IItemEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerDroppingItemEventArgs"/> class. diff --git a/LabApi/Features/Wrappers/Facility/Doors/Door.cs b/LabApi/Features/Wrappers/Facility/Doors/Door.cs index 1ba3723d..98dca4a0 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/Door.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/Door.cs @@ -198,6 +198,13 @@ public bool IsLocked /// </summary> public DoorLockReason LockReason => (DoorLockReason)Base.ActiveLocks; + /// <summary> + /// Locks the door. + /// </summary> + /// <param name="reason">The reason.</param> + /// <param name="enabled">Whether the door lock reason is new.</param> + public void Lock(DoorLockReason reason, bool enabled) => Base.ServerChangeLock(reason, enabled); + /// <summary> /// Gets or sets the required <see cref="DoorPermissionFlags"/>. /// </summary> @@ -252,56 +259,6 @@ public override string ToString() return $"[{GetType().Name}: DoorName={DoorName}, NameTag={NameTag}, Zone={Zone}, IsOpened={IsOpened}, IsLocked={IsLocked}, Permissions={Permissions}]"; } - /// <summary> - /// Opens the door. - /// </summary> - public void Open() => IsOpened = true; - - /// <summary> - /// Closes the door. - /// </summary> - public void Close() => IsOpened = false; - - /// <summary> - /// Locks the door. - /// </summary> - /// <param name="reason">The reason.</param> - /// <param name="enabled">Whether the door lock reason is new.</param> - [Obsolete($"Use {nameof(ChangeLock)} instead")] - public void Lock(DoorLockReason reason, bool enabled) => Base.ServerChangeLock(reason, enabled); - - /// <summary> - /// Changes the door's lock flags. - /// </summary> - /// <param name="reason">The reason flag to add or remove.</param> - /// <param name="enabled">Whether to apply this door lock flag or release it.</param> - public void ChangeLock(DoorLockReason reason, bool enabled) => Base.ServerChangeLock(reason, enabled); - - /// <summary> - /// Locks the door. - /// </summary> - /// <param name="reason">The reason flag to add for the lock.</param> - /// <remarks> - /// A door is locked when it has any <see cref="DoorLockReason"/> flag. - /// </remarks> - public void Lock(DoorLockReason reason = DoorLockReason.AdminCommand) => Base.ServerChangeLock(reason, true); - - /// <summary> - /// Unlocks the door. - /// </summary> - /// <param name="reason">The reason flag to remove for the lock.</param> - /// <remarks> - /// A door is unlocked when it has zero <see cref="DoorLockReason"/> flags. - /// </remarks> - public void Unlock(DoorLockReason reason = DoorLockReason.AdminCommand) => Base.ServerChangeLock(reason, false); - - /// <summary> - /// Whether the door has the specified <see cref="DoorLockReason"/>. - /// </summary> - /// <param name="reason">The <see cref="DoorLockReason"/> to test.</param> - /// <returns><see langword="true"/> if locked with the specified lock reason.</returns> - public bool HasLock(DoorLockReason reason) => (Base.ActiveLocks & (ushort)reason) > 0; - /// <summary> /// Gets the door wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist. /// </summary> diff --git a/LabApi/Features/Wrappers/Facility/Doors/ElevatorDoor.cs b/LabApi/Features/Wrappers/Facility/Doors/ElevatorDoor.cs index 7c8bca4e..5b34eb14 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/ElevatorDoor.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/ElevatorDoor.cs @@ -1,6 +1,7 @@ using Interactables.Interobjects; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using System.Linq; using BaseElevatorDoor = Interactables.Interobjects.ElevatorDoor; namespace LabApi.Features.Wrappers; @@ -50,7 +51,7 @@ internal override void OnRemove() /// <summary> /// Gets the <see cref="Wrappers.Elevator"/> this door belongs to. /// </summary> - public Elevator Elevator => Elevator.Get(Base.Chamber); + public Elevator? Elevator => Elevator.GetByGroup(Base.Group).FirstOrDefault(); /// <summary> /// Gets the <see cref="ElevatorGroup"/> this door belongs to. diff --git a/LabApi/Features/Wrappers/Facility/Elevator.cs b/LabApi/Features/Wrappers/Facility/Elevator.cs index 37c23ff7..91c67439 100644 --- a/LabApi/Features/Wrappers/Facility/Elevator.cs +++ b/LabApi/Features/Wrappers/Facility/Elevator.cs @@ -5,8 +5,6 @@ using System.Linq; using UnityEngine; using Generators; -using BaseElevatorDoor = Interactables.Interobjects.ElevatorDoor; - namespace LabApi.Features.Wrappers; @@ -15,18 +13,6 @@ namespace LabApi.Features.Wrappers; /// </summary> public class Elevator { - /// <summary> - /// Initializes the <see cref="Elevator"/> class to subscribe to <see cref="ElevatorChamber"/> events. - /// </summary> - [InitializeWrapper] - internal static void Initialize() - { - Dictionary.Clear(); - - ElevatorChamber.OnElevatorSpawned += (chamber) => _ = new Elevator(chamber); - ElevatorChamber.OnElevatorRemoved += (chamber) => Dictionary.Remove(chamber); - } - /// <summary> /// Contains all the cached <see cref="ElevatorChamber">generators</see> in the game, accessible through their <see cref="Scp079Generator"/>. /// </summary> @@ -43,10 +29,8 @@ internal static void Initialize() /// <param name="elevator">The <see cref="ElevatorChamber"/> of the elevator.</param> private Elevator(ElevatorChamber elevator) { - Base = elevator; - GameObject = Base.gameObject; - Transform = Base.transform; Dictionary.Add(elevator, this); + Base = elevator; } /// <summary> @@ -55,34 +39,16 @@ private Elevator(ElevatorChamber elevator) public ElevatorChamber Base { get; } /// <summary> - /// The <see cref="UnityEngine.GameObject"/>. - /// </summary> - public GameObject GameObject { get; } - - /// <summary> - /// The <see cref="UnityEngine.Transform"/>. - /// </summary> - public Transform Transform { get; } - - /// <summary> - /// The world space position of the elevator. - /// </summary> - public Vector3 Position => Transform.position; - - /// <summary> - /// The world space rotation of the elevator. - /// </summary> - public Quaternion Rotation => Transform.rotation; - - /// <summary> - /// Gets all the doors associated with this elevator. + /// Initializes the <see cref="Elevator"/> class to subscribe to <see cref="ElevatorChamber"/> events. /// </summary> - public IEnumerable<ElevatorDoor> Doors => BaseElevatorDoor.GetDoorsForGroup(Group).Select(ElevatorDoor.Get)!; + [InitializeWrapper] + internal static void Initialize() + { + Dictionary.Clear(); - /// <summary> - /// Gets all the rooms associated with this elevator. - /// </summary> - public IEnumerable<Room> Rooms => Doors.SelectMany(x => x.Rooms); + ElevatorChamber.OnElevatorSpawned += (chamber) => _ = new Elevator(chamber); + ElevatorChamber.OnElevatorRemoved += (chamber) => Dictionary.Remove(chamber); + } /// <summary> /// Gets the current destination / location of the elevator. @@ -211,13 +177,6 @@ public static void UnlockAll() /// </summary> public void UnlockAllDoors() => Base.ServerLockAllDoors(DoorLockReason.AdminCommand, false); - /// <summary> - /// Checks to see if the position in considered inside the elevators bounds. - /// </summary> - /// <param name="position">The world space position to check.</param> - /// <returns><see langword="true"/> if the position is contained in the elevators world space bounds.</returns> - public bool IsInside(Vector3 position) => Base.WorldspaceBounds.Contains(position); - /// <summary> /// Gets the elevator wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist. /// </summary> diff --git a/LabApi/Features/Wrappers/Facility/Rooms/Room.cs b/LabApi/Features/Wrappers/Facility/Rooms/Room.cs index 60ca522f..6967b25b 100644 --- a/LabApi/Features/Wrappers/Facility/Rooms/Room.cs +++ b/LabApi/Features/Wrappers/Facility/Rooms/Room.cs @@ -86,7 +86,7 @@ internal virtual void OnRemoved() /// <summary> /// Gets the room's neighbors. /// </summary> - public IEnumerable<Room> ConnectedRooms => Base.ConnectedRooms.Select(Get)!; + public HashSet<RoomIdentifier> ConnectedRooms => Base.ConnectedRooms; /// <summary> /// Gets the room's adjacent rooms where the player can traverse to. diff --git a/LabApi/Features/Wrappers/Facility/Rooms/Scp914/Scp914.cs b/LabApi/Features/Wrappers/Facility/Rooms/Scp914/Scp914.cs index 2676f59c..9410cde1 100644 --- a/LabApi/Features/Wrappers/Facility/Rooms/Scp914/Scp914.cs +++ b/LabApi/Features/Wrappers/Facility/Rooms/Scp914/Scp914.cs @@ -57,7 +57,7 @@ internal override void OnRemoved() /// <summary> /// Gets the entrance <see cref="Door"/> of the SCP-914 room. /// </summary> - public Door Entrance => Doors.FirstOrDefault(x => x.Rooms.Count() == 2); + public Door Entrance => Doors.FirstOrDefault(x => x.Rooms.Length == 2); /// <summary> /// Gets the intake <see cref="Door"/> of the SCP-914 machine. diff --git a/LabApi/Features/Wrappers/Players/Player.cs b/LabApi/Features/Wrappers/Players/Player.cs index 3b6c29a1..a1dfeaf1 100644 --- a/LabApi/Features/Wrappers/Players/Player.cs +++ b/LabApi/Features/Wrappers/Players/Player.cs @@ -31,7 +31,6 @@ using VoiceChat; using VoiceChat.Playbacks; using static PlayerStatsSystem.AhpStat; -using InventorySystem.Items.Armor; namespace LabApi.Features.Wrappers; @@ -76,18 +75,10 @@ public class Player public static IEnumerable<Player> NpcList => List.Where(x => x.IsNpc); /// <summary> - /// A reference to all <see cref="Player"/> instances that are real players but are not authenticated yet. + /// A reference to all <see cref="Player"/> instance that are real players but are not authenticated yet. /// </summary> public static IEnumerable<Player> UnauthenticatedList => List.Where(x => x.IsPlayer && !x.IsReady); - /// <summary> - /// A reference to all <see cref="Player"/> instances that are real players and that have authenticated. - /// </summary> - /// <remarks> - /// This is the set of all players that it is safe to send network messages too. - /// </remarks> - public static IEnumerable<Player> AuthenticatedList => List.Where(x => x.IsPlayer && x.IsReady); - /// <summary> /// A reference to all <see cref="Player"/> instances that are dummy NPCs. /// </summary> @@ -140,7 +131,6 @@ internal Player(ReferenceHub referenceHub) Dictionary.Add(referenceHub, this); ReferenceHub = referenceHub; - Transform = referenceHub.transform; CustomDataStoreManager.AddPlayer(this); } @@ -154,16 +144,6 @@ internal Player(ReferenceHub referenceHub) /// </summary> public GameObject GameObject => ReferenceHub.gameObject; - /// <summary> - /// Gets the player's <see cref="UnityEngine.Transform"/>. - /// </summary> - public Transform Transform { get; } - - /// <summary> - /// Gets whether the player was destroyed. - /// </summary> - public bool IsDestroyed => !ReferenceHub; - /// <summary> /// Gets whether the player is the host or server. /// </summary> @@ -1311,38 +1291,6 @@ public List<Pickup> DropAllItems() /// <returns>The amount of ammo which the player has.</returns> public ushort GetAmmo(ItemType item) => ReferenceHub.inventory.GetCurAmmo(item); - /// <summary> - /// Attempts to get the first <see cref="Item"/> specified by its <see cref="ItemType"/> from the inventory. - /// </summary> - /// <param name="type">The <see cref="ItemType"/> to search for.</param> - /// <param name="item">The found <see cref="Item"/> instance.</param> - /// <returns><see langword="true"/> if found, otherwise <see langword="false"/>.</returns> - public bool TryGetItem(ItemType type, [NotNullWhen(true)] out Item? item) - { - if (Inventory.TryGetInventoryItem(type, out ItemBase itemBase)) - { - item = Item.Get(itemBase); - return true; - } - - item = null; - return false; - } - - /// <summary> - /// Tries to get the current body armor being worn. - /// </summary> - /// <param name="bodyArmor">The found body armor or <see langword="null"/> if none is being worn.</param> - /// <returns><see langword="true"/> if body armor was found, otherwise <see langword="false"/>.</returns> - public bool TryGetBodyArmor([NotNullWhen(true)] out BodyArmorItem? bodyArmor) - { - bodyArmor = null; - if (BodyArmorUtils.TryGetBodyArmor(Inventory, out BodyArmor baseArmor)) - bodyArmor = BodyArmorItem.Get(baseArmor); - - return bodyArmor != null; - } - /// <summary> /// Drops ammo of the specified type from the player's inventory. /// </summary> diff --git a/LabApi/Features/Wrappers/Players/Ragdoll.cs b/LabApi/Features/Wrappers/Players/Ragdoll.cs index 3fc7a5ff..12f39027 100644 --- a/LabApi/Features/Wrappers/Players/Ragdoll.cs +++ b/LabApi/Features/Wrappers/Players/Ragdoll.cs @@ -1,5 +1,4 @@ using Generators; -using InventorySystem.Items.Pickups; using Mirror; using PlayerRoles; using PlayerRoles.PlayableScps.Scp049; @@ -35,11 +34,7 @@ private Ragdoll(BasicRagdoll ragdoll) Base = ragdoll; if (CanCache) - { - GameObject = ragdoll.gameObject; - Transform = ragdoll.transform; Dictionary.TryAdd(ragdoll, this); - } } /// <summary> @@ -52,16 +47,6 @@ private Ragdoll(BasicRagdoll ragdoll) /// </summary> public bool IsDestroyed => Base == null; - /// <summary> - /// Gets the ragdoll's <see cref="UnityEngine.GameObject"/>. - /// </summary> - public GameObject GameObject { get; } - - /// <summary> - /// Gets the pickup's <see cref="UnityEngine.Transform"/>. - /// </summary> - public Transform Transform { get; } - /// <summary> /// Gets or sets the role info of the ragdoll. /// <para>This does NOT change the ragdoll visually.</para> From 71d27c3ef380886630404a6c20df0d70a8562345 Mon Sep 17 00:00:00 2001 From: Placeholder David <davidsebesta1_placeholder_1e98un7@noreply.git.scpslgame.com> Date: Fri, 18 Jul 2025 10:16:07 +0000 Subject: [PATCH 050/215] Culling Parent Wrapper - David --- .../Features/Wrappers/AdminToys/AdminToy.cs | 5 +- .../AdminToys/SpawnableCullingParent.cs | 197 ++++++++++++++++++ 2 files changed, 201 insertions(+), 1 deletion(-) create mode 100644 LabApi/Features/Wrappers/AdminToys/SpawnableCullingParent.cs diff --git a/LabApi/Features/Wrappers/AdminToys/AdminToy.cs b/LabApi/Features/Wrappers/AdminToys/AdminToy.cs index 7e4ce983..6c41a6fb 100644 --- a/LabApi/Features/Wrappers/AdminToys/AdminToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/AdminToy.cs @@ -339,7 +339,10 @@ private static void Register<T>(Func<T, AdminToy?> constructor) where T : AdminT typeWrappers.Add(typeof(T), x => constructor((T)x)); } - private static class PrefabCache<T> where T : AdminToyBase + /// <summary> + /// Static prefab cache used to speed up prefab search. + /// </summary> + internal static class PrefabCache<T> where T : NetworkBehaviour { /// <summary> /// Cached prefab instance for type T. diff --git a/LabApi/Features/Wrappers/AdminToys/SpawnableCullingParent.cs b/LabApi/Features/Wrappers/AdminToys/SpawnableCullingParent.cs new file mode 100644 index 00000000..f8f2cca6 --- /dev/null +++ b/LabApi/Features/Wrappers/AdminToys/SpawnableCullingParent.cs @@ -0,0 +1,197 @@ +using static LabApi.Features.Wrappers.AdminToy; +using AdminToys; +using Mirror; +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using UnityEngine; +using Generators; +using BaseCullingParent = AdminToys.SpawnableCullingParent; +using Logger = LabApi.Features.Console.Logger; + +namespace LabApi.Features.Wrappers; + +/// <summary> +/// Wrapper for <see cref="BaseCullingParent"/>.<br/> +/// Cullable item that deactivates itself when not being looked at. +/// Can contain children admin toys to cull them. +/// </summary> +/// <remarks> +/// This class is <b>not</b> subclass of <see cref="AdminToy"/>. +/// </remarks> +public class SpawnableCullingParent +{ + /// <summary> + /// Initializes the <see cref="SpawnableCullingParent"/> class. + /// </summary> + [InitializeWrapper] + internal static void Initialize() + { + BaseCullingParent.OnAdded += AddCullableParent; + BaseCullingParent.OnRemoved += RemoveCullableParent; + } + + /// <summary> + /// Contains all the cached spawnable culling parents, accessible through their <see cref="Base"/>. + /// </summary> + public static Dictionary<BaseCullingParent, SpawnableCullingParent> Dictionary { get; } = []; + + /// <summary> + /// A reference to all instances of <see cref="SpawnableCullingParent"/>. + /// </summary> + public static IReadOnlyCollection<SpawnableCullingParent> List => Dictionary.Values; + + /// <summary> + /// A protected constructor to prevent external instantiation. + /// </summary> + /// <param name="cullingBase">The base object.</param> + protected SpawnableCullingParent(BaseCullingParent cullingBase) + { + Dictionary.Add(cullingBase, this); + Base = cullingBase; + } + + /// <summary> + /// The <see cref="BaseCullingParent">base</see> object. + /// </summary> + public BaseCullingParent Base { get; } + + /// <summary> + /// The <see cref="UnityEngine.GameObject"/>. + /// </summary> + public GameObject GameObject => Base.gameObject; + + /// <summary> + /// The culling parent's <see cref="UnityEngine.Transform"/>. + /// </summary> + public Transform Transform => Base.transform; + + /// <summary> + /// Whether the <see cref="Base"/> was destroyed. + /// </summary> + /// <remarks> + /// A destroyed object may not be used. + /// </remarks> + public bool IsDestroyed => Base == null; + + /// <summary> + /// Gets or sets the position of the culling parent. + /// </summary> + public Vector3 Position + { + get => Base.BoundsPosition; + set => Base.BoundsPosition = value; + } + + /// <summary> + /// Gets or sets the culling bound size of the culling parent. + /// </summary> + public Vector3 Size + { + get => Base.BoundsSize; + set => Base.BoundsSize = value; + } + + /// <summary> + /// Spawns the culling parent on client. + /// </summary> + public void Spawn() => NetworkServer.Spawn(GameObject); + + /// <summary> + /// Destroys the culling parent on server and client. + /// </summary> + public void Destroy() => NetworkServer.Destroy(GameObject); + + /// <summary> + /// Instantiates a new culling parent object. + /// </summary> + /// <param name="position">The initial position.</param> + /// <param name="size">The bounds size.</param> + /// <param name="networkSpawn">Whether should the game object spawn over network.</param> + /// <returns>The instantiated culling parent.</returns> + public static SpawnableCullingParent Create(Vector3 position, Vector3 size, bool networkSpawn = true) + { + if (PrefabCache<BaseCullingParent>.prefab == null) + { + BaseCullingParent? found = null; + foreach (GameObject prefab in NetworkClient.prefabs.Values) + { + if (prefab.TryGetComponent(out found)) + break; + } + + if (found == null) + throw new InvalidOperationException($"No prefab in NetworkClient.prefabs has component type {typeof(BaseCullingParent)}"); + + PrefabCache<BaseCullingParent>.prefab = found; + } + + BaseCullingParent instance = UnityEngine.Object.Instantiate(PrefabCache<BaseCullingParent>.prefab); + instance.BoundsPosition = position; + instance.BoundsSize = size; + + if (networkSpawn) + NetworkServer.Spawn(instance.gameObject); + + return Get(instance); + } + + /// <summary> + /// Gets the cullable parent wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="AdminToyBase"/> was not <see langword="null"/>. + /// </summary> + /// <param name="cullingBase">The <see cref="Base"/> of the cullable parent.</param> + /// <returns>The requested culling parent or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(cullingBase))] + public static SpawnableCullingParent? Get(BaseCullingParent? cullingBase) + { + if (cullingBase == null) + return null; + + return Dictionary.TryGetValue(cullingBase, out SpawnableCullingParent item) ? item : new SpawnableCullingParent(cullingBase); + } + + /// <summary> + /// Tries to get the culling parent wrapper from the <see cref="Dictionary"/>. + /// </summary> + /// <param name="adminToyBase">The <see cref="Base"/> of the cullable parent.</param> + /// <param name="adminToy">The requested culling parent.</param> + /// <returns><see langword="True"/> if the culling parent exists, otherwise <see langword="false"/>.</returns> + public static bool TryGet(BaseCullingParent? adminToyBase, [NotNullWhen(true)] out SpawnableCullingParent? adminToy) + { + adminToy = Get(adminToyBase); + return adminToy != null; + } + + /// <summary> + /// A private method to handle the creation of new cullable parents on the server. + /// </summary> + /// <param name="cullableParent">The created <see cref="BaseCullingParent"/> instance.</param> + private static void AddCullableParent(BaseCullingParent cullableParent) + { + try + { + if (!Dictionary.ContainsKey(cullableParent)) + _ = new SpawnableCullingParent(cullableParent); + } + catch (Exception e) + { + Logger.InternalError($"Failed to handle admin toy creation with error: {e}"); + } + } + + /// <summary> + /// A private method to handle the removal of cullable parents from the server. + /// </summary> + /// <param name="cullableParent">The to be destroyed <see cref="BaseCullingParent"/> instance.</param> + private static void RemoveCullableParent(BaseCullingParent cullableParent) + { + try + { + Dictionary.Remove(cullableParent); + } + catch (Exception e) + { + Logger.InternalError($"Failed to handle cullable parent destruction with error: {e}"); + } + } +} From 9ceddadad7198652033717c32b81a5e0d836ca75 Mon Sep 17 00:00:00 2001 From: Placeholder David <davidsebesta1_placeholder_1e98un7@noreply.git.scpslgame.com> Date: Sun, 20 Jul 2025 15:27:24 +0000 Subject: [PATCH 051/215] Events pass + force jumping + misc - David --- .../LogAll/LogPlugin/MyCustomEventsHandler.cs | 75 +++++++++++++++++++ .../PlayerChangedAttachmentsEventArgs.cs | 43 +++++++++++ .../PlayerChangingAttachmentsEventArgs.cs | 47 ++++++++++++ .../PlayerDetectedByScp1344EventArgs.cs | 28 +++++++ .../PlayerInteractedWarheadLeverEventArgs.cs | 30 ++++++++ .../PlayerInteractingWarheadLeverEventArgs.cs | 35 +++++++++ .../PlayerEvents/PlayerJumpedEventArgs.cs | 30 ++++++++ .../PlayerMovementStateChangedEventArgs.cs | 38 ++++++++++ .../PlayerSendingAttachmentsPrefsEventArgs.cs | 48 ++++++++++++ .../PlayerSentAttachmentsPrefsEventArgs.cs | 45 +++++++++++ .../Scp3114DisguisedEventArgs.cs | 29 +++++++ .../Scp3114DisguisingEventArgs.cs | 33 ++++++++ .../Scp3114Events/Scp3114RevealedEventArgs.cs | 30 ++++++++ .../Scp3114RevealingEventArgs.cs | 34 +++++++++ .../Scp3114StartedDanceEventArgs.cs | 30 ++++++++ .../Scp3114StartingDanceEventArgs.cs | 36 +++++++++ .../ElevatorSequenceChangedEventArgs.cs | 39 ++++++++++ .../Handlers/PlayerEvents.EventHandlers.cs | 50 +++++++++++++ .../Handlers/Scp3114Events.EventHandlers.cs | 30 ++++++++ .../Handlers/ServerEvents.EventHandlers.cs | 9 ++- .../AdminToys/SpawnableCullingParent.cs | 2 +- LabApi/Features/Wrappers/Facility/Elevator.cs | 16 ++-- .../Facility/Hazards/SinkholeHazard.cs | 2 +- LabApi/Features/Wrappers/Facility/Warhead.cs | 28 +++++++ LabApi/Features/Wrappers/Players/Player.cs | 65 ++++++++++++++++ LabApi/LabApi.csproj | 2 +- 26 files changed, 844 insertions(+), 10 deletions(-) create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerChangedAttachmentsEventArgs.cs create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerChangingAttachmentsEventArgs.cs create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerDetectedByScp1344EventArgs.cs create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerInteractedWarheadLeverEventArgs.cs create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerInteractingWarheadLeverEventArgs.cs create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerJumpedEventArgs.cs create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerMovementStateChangedEventArgs.cs create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerSendingAttachmentsPrefsEventArgs.cs create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerSentAttachmentsPrefsEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp3114Events/Scp3114DisguisedEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp3114Events/Scp3114DisguisingEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp3114Events/Scp3114RevealedEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp3114Events/Scp3114RevealingEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp3114Events/Scp3114StartedDanceEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp3114Events/Scp3114StartingDanceEventArgs.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/ElevatorSequenceChangedEventArgs.cs diff --git a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs index 1d2a65f4..cf11844f 100644 --- a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs +++ b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs @@ -1534,6 +1534,81 @@ public override void OnObjectivePickedScpItemCompleted(ScpItemPickedObjectiveEve Logger.Info($"{nameof(OnObjectivePickedScpItemCompleted)} triggered by {ev.Player.UserId}"); } + public override void OnPlayerJumped(PlayerJumpedEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerJumped)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerMovementStateChanged(PlayerMovementStateChangedEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerMovementStateChanged)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerChangingAttachments(PlayerChangingAttachmentsEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerChangingAttachments)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerChangedAttachments(PlayerChangedAttachmentsEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerChangedAttachments)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerSendingAttachmentsPrefs(PlayerSendingAttachmentsPrefsEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerSendingAttachmentsPrefs)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerSentAttachmentsPrefs(PlayerSentAttachmentsPrefsEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerSentAttachmentsPrefs)} triggered by {ev.Player.UserId}"); + } + + public override void OnServerElevatorSequenceChanged(ElevatorSequenceChangedEventArgs ev) + { + Logger.Info($"{nameof(OnServerElevatorSequenceChanged)} triggered"); + } + + public override void OnPlayerInteractingWarheadLever(PlayerInteractingWarheadLeverEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerInteractingWarheadLever)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerInteractedWarheadLever(PlayerInteractedWarheadLeverEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerInteractedWarheadLever)} triggered by {ev.Player.UserId}"); + } + + public override void OnScp3114Disguising(Scp3114DisguisingEventArgs ev) + { + Logger.Info($"{nameof(OnScp3114Disguising)} triggered by {ev.Player.UserId}"); + } + + public override void OnScp3114Disguised(Scp3114DisguisedEventArgs ev) + { + Logger.Info($"{nameof(OnScp3114Disguised)} triggered by {ev.Player.UserId}"); + } + + public override void OnScp3114Revealing(Scp3114RevealingEventArgs ev) + { + Logger.Info($"{nameof(OnScp3114Revealing)} triggered by {ev.Player.UserId}"); + } + + public override void OnScp3114Revealed(Scp3114RevealedEventArgs ev) + { + Logger.Info($"{nameof(OnScp3114Revealed)} triggered by {ev.Player.UserId}"); + } + + public override void OnScp3114StartDancing(Scp3114StartingDanceEventArgs ev) + { + Logger.Info($"{nameof(OnScp3114StartDancing)} triggered by {ev.Player.UserId}"); + } + + public override void OnScp3114Dance(Scp3114StartedDanceEventArgs ev) + { + Logger.Info($"{nameof(OnScp3114Dance)} triggered by {ev.Player.UserId}"); + } + #region Excluded Events diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangedAttachmentsEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedAttachmentsEventArgs.cs new file mode 100644 index 00000000..c812663d --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedAttachmentsEventArgs.cs @@ -0,0 +1,43 @@ +using InventorySystem.Items.Firearms; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.ChangedAttachments"/> event. +/// </summary> +public class PlayerChangedAttachmentsEventArgs : EventArgs, IPlayerEvent, IFirearmItemEvent +{ + /// <summary> + /// Initialized a new instance of <see cref="PlayerChangedAttachmentsEventArgs"/>. + /// </summary> + /// <param name="player">The player who is changing the firearm attachments.</param> + /// <param name="firearm">The firearm whose attachments are being changed.</param> + /// <param name="oldAttachments">The old attachments code.</param> + /// <param name="newAttachments">The new attachments code.</param> + public PlayerChangedAttachmentsEventArgs(ReferenceHub player, Firearm firearm, uint oldAttachments, uint newAttachments) + { + Player = Player.Get(player); + FirearmItem = FirearmItem.Get(firearm); + OldAttachments = oldAttachments; + NewAttachments = newAttachments; + } + + /// <inheritdoc> + public Player Player { get; } + + /// <inheritdoc> + public FirearmItem FirearmItem { get; } + + /// <summary> + /// Gets previous attachments code. + /// </summary> + public uint OldAttachments { get; } + + /// <summary> + /// Gets the new attachments code. + /// </summary> + public uint NewAttachments { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangingAttachmentsEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingAttachmentsEventArgs.cs new file mode 100644 index 00000000..09564cd0 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingAttachmentsEventArgs.cs @@ -0,0 +1,47 @@ +using InventorySystem.Items.Firearms; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.ChangingAttachments"/> event. +/// </summary> +public class PlayerChangingAttachmentsEventArgs : EventArgs, IPlayerEvent, IFirearmItemEvent, ICancellableEvent +{ + /// <summary> + /// Initialized a new instance of <see cref="PlayerChangingAttachmentsEventArgs"/>. + /// </summary> + /// <param name="player">The player who is changing the firearm attachments.</param> + /// <param name="firearm">The firearm whose attachments are being changed.</param> + /// <param name="oldAttachments">The old attachments code.</param> + /// <param name="newAttachments">The new attachments code requested by the player.</param> + public PlayerChangingAttachmentsEventArgs(ReferenceHub player, Firearm firearm, uint oldAttachments, uint newAttachments) + { + Player = Player.Get(player); + FirearmItem = FirearmItem.Get(firearm); + OldAttachments = oldAttachments; + NewAttachments = newAttachments; + IsAllowed = true; + } + + /// <inheritdoc/ > + public Player Player { get; } + + /// <inheritdoc/ > + public FirearmItem FirearmItem { get; } + + /// <summary> + /// Gets previous attachments code. + /// </summary> + public uint OldAttachments { get; } + + /// <summary> + /// Gets or sets new attachments code. + /// </summary> + public uint NewAttachments { get; set; } + + /// <inheritdoc/ > + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDetectedByScp1344EventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDetectedByScp1344EventArgs.cs new file mode 100644 index 00000000..7fb7dd84 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDetectedByScp1344EventArgs.cs @@ -0,0 +1,28 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.DetectedByScp1344"/> event. +/// </summary> +public class PlayerDetectedByScp1344EventArgs : EventArgs, IPlayerEvent, ITargetEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="PlayerDetectedByScp1344EventArgs"/> class. + /// </summary> + /// <param name="player">The player who has SCP-1344.</param> + /// <param name="target">The player who has been detected.</param> + public PlayerDetectedByScp1344EventArgs(ReferenceHub player, ReferenceHub target) + { + Player = Player.Get(player); + Target = Player.Get(target); + } + + /// <inheritdoc/> + public Player Player { get; } + + /// <inheritdoc/> + public Player Target { get; set; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedWarheadLeverEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedWarheadLeverEventArgs.cs new file mode 100644 index 00000000..8358f32a --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedWarheadLeverEventArgs.cs @@ -0,0 +1,30 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.InteractedWarheadLever"/> event. +/// </summary> +public class PlayerInteractedWarheadLeverEventArgs : EventArgs, IPlayerEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="PlayerInteractedWarheadLeverEventArgs"/> class. + /// </summary> + /// <param name="player">The player who interacted with the lever.</param> + /// <param name="enabled">Bool whether the warhead is enabled and can be started.</param> + public PlayerInteractedWarheadLeverEventArgs(ReferenceHub player, bool enabled) + { + Player = Player.Get(player); + Enabled = enabled; + } + + /// <inheritdoc/ > + public Player Player { get; } + + /// <summary> + /// Gets whether the warhead is now enabled. + /// </summary> + public bool Enabled { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingWarheadLeverEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingWarheadLeverEventArgs.cs new file mode 100644 index 00000000..f5b88fd4 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingWarheadLeverEventArgs.cs @@ -0,0 +1,35 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.InteractingWarheadLever"/> event. +/// </summary> +public class PlayerInteractingWarheadLeverEventArgs : EventArgs, IPlayerEvent, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="PlayerInteractedWarheadLeverEventArgs"/> class. + /// </summary> + /// <param name="player">The player who is interacting with the lever.</param> + /// <param name="enabled">Bool whether the warhead should be enabled and can be started.</param> + public PlayerInteractingWarheadLeverEventArgs(ReferenceHub player, bool enabled) + { + Player = Player.Get(player); + Enabled = enabled; + + IsAllowed = true; + } + + /// <inheritdoc/> + public Player Player { get; } + + /// <summary> + /// Gets or sets whether the warhead should be enabled. + /// </summary> + public bool Enabled { get; } + + /// <inheritdoc/> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerJumpedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerJumpedEventArgs.cs new file mode 100644 index 00000000..166fdcd9 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerJumpedEventArgs.cs @@ -0,0 +1,30 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.Jumped"/> event. +/// </summary> +public class PlayerJumpedEventArgs : EventArgs, IPlayerEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="PlayerJumpedEventArgs"/> class. + /// </summary> + /// <param name="hub">The player who jumped.</param> + /// <param name="jumpStrength">Strength of the jump.</param> + public PlayerJumpedEventArgs(ReferenceHub hub, float jumpStrength) + { + Player = Player.Get(hub); + JumpStrength = jumpStrength; + } + + /// <inheritdoc/> + public Player Player { get; } + + /// <summary> + /// Gets the strength of the jump. + /// </summary> + public float JumpStrength { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerMovementStateChangedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerMovementStateChangedEventArgs.cs new file mode 100644 index 00000000..68a519b4 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerMovementStateChangedEventArgs.cs @@ -0,0 +1,38 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using PlayerRoles.FirstPersonControl; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.MovementStateChanged"/> event. +/// </summary> +public class PlayerMovementStateChangedEventArgs : EventArgs, IPlayerEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="PlayerMovementStateChangedEventArgs"/> class. + /// </summary> + /// <param name="hub">The player whose movement state has changed.</param> + /// <param name="oldState">Old movement state of the player./param> + /// <param name="newState">New movement state of the player.</param> + public PlayerMovementStateChangedEventArgs(ReferenceHub hub, PlayerMovementState oldState, PlayerMovementState newState) + { + Player = Player.Get(hub); + OldState = oldState; + NewState = newState; + } + + /// <inheritdoc/> + public Player Player { get; } + + /// <summary> + /// Gets the old movement state. + /// </summary> + public PlayerMovementState OldState { get; } + + /// <summary> + /// Gets the new movement state. + /// </summary> + public PlayerMovementState NewState { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSendingAttachmentsPrefsEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSendingAttachmentsPrefsEventArgs.cs new file mode 100644 index 00000000..d44aa215 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSendingAttachmentsPrefsEventArgs.cs @@ -0,0 +1,48 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.ChangingAttachmentsPrefs"/> event. +/// </summary> +public class PlayerSendingAttachmentsPrefsEventArgs : EventArgs, IPlayerEvent, ICancellableEvent +{ + /// <summary> + /// Initialized a new instance of <see cref="PlayerSendingAttachmentsPrefsEventArgs"/>. + /// </summary> + /// <param name="player">The player who is changing the firearm attachments.</param> + /// <param name="firearm">The firearm type whose attachments preferences are being changed.</param> + /// <param name="oldAttachments">The old attachments code.</param> + /// <param name="newAttachments">The new attachments code requested by the player.</param> + public PlayerSendingAttachmentsPrefsEventArgs(ReferenceHub player, ItemType firearm, uint oldAttachments, uint newAttachments) + { + Player = Player.Get(player); + FirearmType = firearm; + OldAttachments = oldAttachments; + NewAttachments = newAttachments; + IsAllowed = true; + } + + /// <inheritdoc/ > + public Player Player { get; } + + /// <summary> + /// Gets the <see cref="ItemType"/> of the firearm. + /// </summary> + public ItemType FirearmType { get; set; } + + /// <summary> + /// Gets previous attachments code stored on the server. + /// </summary> + public uint OldAttachments { get; } + + /// <summary> + /// Gets or sets new attachments code. <b>Edited values are NOT propagated back to the client and are stored on the server for on-spawn purposes.</b> + /// </summary> + public uint NewAttachments { get; set; } + + /// <inheritdoc/ > + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSentAttachmentsPrefsEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSentAttachmentsPrefsEventArgs.cs new file mode 100644 index 00000000..4c98624b --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSentAttachmentsPrefsEventArgs.cs @@ -0,0 +1,45 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.ChangedAttachmentsPrefs"/> event. +/// </summary> +public class PlayerSentAttachmentsPrefsEventArgs : EventArgs, IPlayerEvent +{ + /// <summary> + /// Initialized a new instance of <see cref="PlayerSentAttachmentsPrefsEventArgs"/>. + /// </summary> + /// <param name="player">The player who is changing the firearm attachments.</param> + /// <param name="firearm">The firearm type whose attachments preferences are being changed.</param> + /// <param name="oldAttachments">The old attachments code.</param> + /// <param name="newAttachments">The new attachments code.</param> + public PlayerSentAttachmentsPrefsEventArgs(ReferenceHub player, ItemType firearm, uint oldAttachments, uint newAttachments) + { + Player = Player.Get(player); + FirearmType = firearm; + OldAttachments = oldAttachments; + NewAttachments = newAttachments; + } + + /// <inheritdoc/ > + public Player Player { get; } + + /// <summary> + /// The <see cref="ItemType"/> of the firearm. + /// </summary> + public ItemType FirearmType { get; } + + /// <summary> + /// Gets previous attachments code stored on the server. + /// </summary> + public uint OldAttachments { get; } + + /// <summary> + /// Gets the new attachments code stored on the server. + /// </summary> + public uint NewAttachments { get; } + +} diff --git a/LabApi/Events/Arguments/Scp3114Events/Scp3114DisguisedEventArgs.cs b/LabApi/Events/Arguments/Scp3114Events/Scp3114DisguisedEventArgs.cs new file mode 100644 index 00000000..969f98d7 --- /dev/null +++ b/LabApi/Events/Arguments/Scp3114Events/Scp3114DisguisedEventArgs.cs @@ -0,0 +1,29 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using PlayerRoles.Ragdolls; +using System; + +namespace LabApi.Events.Arguments.Scp3114Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp3114Events.Disguised"/> event. +/// </summary> +public class Scp3114DisguisedEventArgs : EventArgs, IPlayerEvent, IRagdollEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp3114DisguisedEventArgs"/> class. + /// </summary> + /// <param name="player">The player SCP who disguised./param> + /// <param name="ragdoll">The ragdoll used for disguising purposes.</param> + public Scp3114DisguisedEventArgs(ReferenceHub player, BasicRagdoll ragdoll) + { + Player = Player.Get(player); + Ragdoll = Ragdoll.Get(ragdoll); + } + + /// <inheritdoc/> + public Player Player { get; } + + /// <inheritdoc/> + public Ragdoll Ragdoll { get; } +} diff --git a/LabApi/Events/Arguments/Scp3114Events/Scp3114DisguisingEventArgs.cs b/LabApi/Events/Arguments/Scp3114Events/Scp3114DisguisingEventArgs.cs new file mode 100644 index 00000000..148e13f6 --- /dev/null +++ b/LabApi/Events/Arguments/Scp3114Events/Scp3114DisguisingEventArgs.cs @@ -0,0 +1,33 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using PlayerRoles.Ragdolls; +using System; + +namespace LabApi.Events.Arguments.Scp3114Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp3114Events.Disguised"/> event. +/// </summary> +public class Scp3114DisguisingEventArgs : EventArgs, IPlayerEvent, IRagdollEvent, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp3114DisguisedEventArgs"/> class. + /// </summary> + /// <param name="player">The player SCP who is disguising./param> + /// <param name="ragdoll">The ragdoll used for disguising purposes.</param> + public Scp3114DisguisingEventArgs(ReferenceHub player, BasicRagdoll ragdoll) + { + Player = Player.Get(player); + Ragdoll = Ragdoll.Get(ragdoll); + IsAllowed = true; + } + + /// <inheritdoc/> + public Player Player { get; } + + /// <inheritdoc/> + public Ragdoll Ragdoll { get; } + + /// <inheritdoc/> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/Scp3114Events/Scp3114RevealedEventArgs.cs b/LabApi/Events/Arguments/Scp3114Events/Scp3114RevealedEventArgs.cs new file mode 100644 index 00000000..f96a57ea --- /dev/null +++ b/LabApi/Events/Arguments/Scp3114Events/Scp3114RevealedEventArgs.cs @@ -0,0 +1,30 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp3114Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp3114Events.Revealed"/> event. +/// </summary> +public class Scp3114RevealedEventArgs : EventArgs, IPlayerEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp3114RevealedEventArgs"/> class. + /// </summary> + /// <param name="player">The player SCP so is undisguised./param> + /// <param name="forced">Bool whether the reveal is forced by timer running out or if it was player's request.</param> + public Scp3114RevealedEventArgs(ReferenceHub player, bool forced) + { + Player = Player.Get(player); + Forced = forced; + } + + /// <inheritdoc/> + public Player Player { get; } + + /// <summary> + /// Gets whether the reveal was forced by timer running out or if it was player's request. + /// </summary> + public bool Forced { get; } +} diff --git a/LabApi/Events/Arguments/Scp3114Events/Scp3114RevealingEventArgs.cs b/LabApi/Events/Arguments/Scp3114Events/Scp3114RevealingEventArgs.cs new file mode 100644 index 00000000..df7e4abb --- /dev/null +++ b/LabApi/Events/Arguments/Scp3114Events/Scp3114RevealingEventArgs.cs @@ -0,0 +1,34 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp3114Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp3114Events.Revealing"/> event. +/// </summary> +public class Scp3114RevealingEventArgs : EventArgs, IPlayerEvent, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp3114RevealingEventArgs"/> class. + /// </summary> + /// <param name="player">The player SCP who is undisguising./param> + /// <param name="forced">Bool whether the reveal is forced by timer running out or if it was player's request.</param> + public Scp3114RevealingEventArgs(ReferenceHub player, bool forced) + { + Player = Player.Get(player); + Forced = forced; + IsAllowed = true; + } + + /// <inheritdoc/> + public Player Player { get; } + + /// <summary> + /// Gets whether the reveal is forced by timer running out or if it was player's request. + /// </summary> + public bool Forced { get; } + + /// <inheritdoc/> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/Scp3114Events/Scp3114StartedDanceEventArgs.cs b/LabApi/Events/Arguments/Scp3114Events/Scp3114StartedDanceEventArgs.cs new file mode 100644 index 00000000..515a1995 --- /dev/null +++ b/LabApi/Events/Arguments/Scp3114Events/Scp3114StartedDanceEventArgs.cs @@ -0,0 +1,30 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp3114Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp3114Events.Dance"/> event. +/// </summary> +public class Scp3114StartedDanceEventArgs : EventArgs, IPlayerEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp3114StartingDanceEventArgs"/> class. + /// </summary> + /// <param name="player">The player who is starting to dance.</param> + /// <param name="danceId">The index of the animation to play.</param> + public Scp3114StartedDanceEventArgs(ReferenceHub player, byte danceId) + { + Player = Player.Get(player); + DanceId = danceId; + } + + /// <summary> + /// Gets or sets the index of the animation to play. + /// </summary> + public byte DanceId { get; } + + /// <inheritdoc/> + public Player Player { get; } +} diff --git a/LabApi/Events/Arguments/Scp3114Events/Scp3114StartingDanceEventArgs.cs b/LabApi/Events/Arguments/Scp3114Events/Scp3114StartingDanceEventArgs.cs new file mode 100644 index 00000000..a9a69170 --- /dev/null +++ b/LabApi/Events/Arguments/Scp3114Events/Scp3114StartingDanceEventArgs.cs @@ -0,0 +1,36 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp3114Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp3114Events.StartDancing"/> event. +/// </summary> +public class Scp3114StartingDanceEventArgs : EventArgs, IPlayerEvent, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp3114StartingDanceEventArgs"/> class. + /// </summary> + /// <param name="player">The player who is starting to dance.</param> + /// <param name="danceId">The index of the animation to play.</param> + public Scp3114StartingDanceEventArgs(ReferenceHub player, byte danceId) + { + Player = Player.Get(player); + DanceId = danceId; + IsAllowed = true; + } + + /// <inheritdoc/> + public Player Player { get; } + + /// <summary> + /// Gets or sets the index of the animation to play. + /// Currently there are 7 dance variants in game. + /// <para>Any value above max length will be moved to equal index via modulo (%) operator.</para> + /// </summary> + public byte DanceId { get; set; } + + /// <inheritdoc/> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/ElevatorSequenceChangedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/ElevatorSequenceChangedEventArgs.cs new file mode 100644 index 00000000..965bdd42 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/ElevatorSequenceChangedEventArgs.cs @@ -0,0 +1,39 @@ +using Interactables.Interobjects; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using static Interactables.Interobjects.ElevatorChamber; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.ElevatorSequenceChanged"/> event. +/// </summary> +public class ElevatorSequenceChangedEventArgs : EventArgs, IElevatorEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="ElevatorSequenceChangedEventArgs"/> class. + /// </summary> + /// <param name="elevator">The elevator whose sequence has changed.</param> + /// <param name="oldSequence"> The old sequence the elevator was in before.</param> + /// <param name="newSequence">The new sequence the elevator has transitioned into.</param> + public ElevatorSequenceChangedEventArgs(ElevatorChamber elevator, ElevatorSequence oldSequence, ElevatorSequence newSequence) + { + Elevator = Elevator.Get(elevator); + OldSequence = oldSequence; + NewSequence = newSequence; + } + + /// <inheritdoc/> + public Elevator Elevator { get; } + + /// <summary> + /// The old sequence the elevator was in before. + /// </summary> + public ElevatorSequence OldSequence { get; } + + /// <summary> + /// The new sequence the elevator has transitioned into. + /// </summary> + public ElevatorSequence NewSequence { get; } +} diff --git a/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs b/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs index 0b053ca2..e5ee2733 100644 --- a/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs +++ b/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs @@ -505,6 +505,26 @@ public static partial class PlayerEvents /// </summary> public static event LabEventHandler<PlayerShotWeaponEventArgs>? ShotWeapon; + /// <summary> + /// Gets called when player is changing weapon attachments. + /// </summary> + public static event LabEventHandler<PlayerChangingAttachmentsEventArgs>? ChangingAttachments; + + /// <summary> + /// Gets called when player has changed weapon attachments. + /// </summary> + public static event LabEventHandler<PlayerChangedAttachmentsEventArgs>? ChangedAttachments; + + /// <summary> + /// Gets called when player is changing weapon attachments preferences. + /// </summary> + public static event LabEventHandler<PlayerSendingAttachmentsPrefsEventArgs>? SendingAttachmentsPrefs; + + /// <summary> + /// Gets called when player has changed weapon attachments preferences. + /// </summary> + public static event LabEventHandler<PlayerSentAttachmentsPrefsEventArgs>? SentAttachmentsPrefs; + /// <summary> /// Gets called when the player is cancelling the use of an item. /// </summary> @@ -565,6 +585,16 @@ public static partial class PlayerEvents /// </summary> public static event LabEventHandler<PlayerToggledRadioEventArgs>? ToggledRadio; + /// <summary> + /// Gets called when player successfully jumps. Not called when jumping is prevented by status effects. + /// </summary> + public static event LabEventHandler<PlayerJumpedEventArgs>? Jumped; + + /// <summary> + /// Gets called when player's movement state change. Such as from walking to running, sneaking and opposite way around. + /// </summary> + public static event LabEventHandler<PlayerMovementStateChangedEventArgs>? MovementStateChanged; + #endregion #region World Interaction @@ -829,6 +859,16 @@ public static partial class PlayerEvents /// </summary> public static event LabEventHandler<PlayerZoneChangedEventArgs>? ZoneChanged; + /// <summary> + /// Gets called when player interacts with warhead lever. + /// </summary> + public static event LabEventHandler<PlayerInteractingWarheadLeverEventArgs>? InteractingWarheadLever; + + /// <summary> + /// Gets called when player interacted with warhead lever. + /// </summary> + public static event LabEventHandler<PlayerInteractedWarheadLeverEventArgs>? InteractedWarheadLever; + #endregion #region Spectating @@ -871,5 +911,15 @@ public static partial class PlayerEvents /// Gets called when a player has validated the visibility of a target player. /// </summary> public static event LabEventHandler<PlayerValidatedVisibilityEventArgs>? ValidatedVisibility; + + #endregion + + #region Scp1344 + + /// <summary> + /// Gets called when player detects enemy player using SCP-1344. + /// </summary> + public static event LabEventHandler<PlayerDetectedByScp1344EventArgs>? DetectedByScp1344; + #endregion } \ No newline at end of file diff --git a/LabApi/Events/Handlers/Scp3114Events.EventHandlers.cs b/LabApi/Events/Handlers/Scp3114Events.EventHandlers.cs index 5ece70bb..8eb5332a 100644 --- a/LabApi/Events/Handlers/Scp3114Events.EventHandlers.cs +++ b/LabApi/Events/Handlers/Scp3114Events.EventHandlers.cs @@ -7,6 +7,26 @@ namespace LabApi.Events.Handlers; /// </summary> public static partial class Scp3114Events { + /// <summary> + /// Gets called when SCP-3114 is disguising itself. + /// </summary> + public static event LabEventHandler<Scp3114DisguisingEventArgs>? Disguising; + + /// <summary> + /// Gets called when SCP-3114 has disguised itself. + /// </summary> + public static event LabEventHandler<Scp3114DisguisedEventArgs>? Disguised; + + /// <summary> + /// Gets called when SCP-3114 is revealing itself. + /// </summary> + public static event LabEventHandler<Scp3114RevealingEventArgs>? Revealing; + + /// <summary> + /// Gets called when SCP-3114 has revealed itself. + /// </summary> + public static event LabEventHandler<Scp3114RevealedEventArgs>? Revealed; + /// <summary> /// Gets called when SCP-3114 is starting to strangle a player. /// </summary> @@ -22,6 +42,16 @@ public static partial class Scp3114Events /// </summary> public static event LabEventHandler<Scp3114StrangleAbortingEventArgs>? StrangleAborting; + /// <summary> + /// Gets called when SCP-3114 started dancing. + /// </summary> + public static event LabEventHandler<Scp3114StartedDanceEventArgs>? Dance; + + /// <summary> + /// Gets called when SCP-3114 is about to dance. + /// </summary> + public static event LabEventHandler<Scp3114StartingDanceEventArgs>? StartDancing; + /// <summary> /// Gets called when SCP-3114 has aborted their strangle on the player. /// </summary> diff --git a/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs b/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs index 7c8ea582..f9b24570 100644 --- a/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs +++ b/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs @@ -141,7 +141,7 @@ public static partial class ServerEvents /// Gets called when the server has created a new pickup. /// </summary> public static event LabEventHandler<PickupCreatedEventArgs>? PickupCreated; - + /// <summary> /// Gets called when the server has destroyed a pickup. /// </summary> @@ -151,7 +151,7 @@ public static partial class ServerEvents /// Gets called when the server is sending an Admin Chat message. /// </summary> public static event LabEventHandler<SendingAdminChatEventArgs>? SendingAdminChat; - + /// <summary> /// Gets called when the server sent an Admin Chat message. /// </summary> @@ -206,4 +206,9 @@ public static partial class ServerEvents /// Gets called when the server activated generator. /// </summary> public static event LabEventHandler<GeneratorActivatedEventArgs>? GeneratorActivated; + + /// <summary> + /// Gets called when elevator's sequence has changed. + /// </summary> + public static event LabEventHandler<ElevatorSequenceChangedEventArgs>? ElevatorSequenceChanged; } \ No newline at end of file diff --git a/LabApi/Features/Wrappers/AdminToys/SpawnableCullingParent.cs b/LabApi/Features/Wrappers/AdminToys/SpawnableCullingParent.cs index f8f2cca6..078fd6d2 100644 --- a/LabApi/Features/Wrappers/AdminToys/SpawnableCullingParent.cs +++ b/LabApi/Features/Wrappers/AdminToys/SpawnableCullingParent.cs @@ -194,4 +194,4 @@ private static void RemoveCullableParent(BaseCullingParent cullableParent) Logger.InternalError($"Failed to handle cullable parent destruction with error: {e}"); } } -} +} \ No newline at end of file diff --git a/LabApi/Features/Wrappers/Facility/Elevator.cs b/LabApi/Features/Wrappers/Facility/Elevator.cs index 91c67439..b9bf631c 100644 --- a/LabApi/Features/Wrappers/Facility/Elevator.cs +++ b/LabApi/Features/Wrappers/Facility/Elevator.cs @@ -5,6 +5,7 @@ using System.Linq; using UnityEngine; using Generators; +using BaseElevatorDoor = Interactables.Interobjects.ElevatorDoor; namespace LabApi.Features.Wrappers; @@ -50,6 +51,16 @@ internal static void Initialize() ElevatorChamber.OnElevatorRemoved += (chamber) => Dictionary.Remove(chamber); } + /// <summary> + /// Gets all the doors associated with this elevator. + /// </summary> + public IEnumerable<ElevatorDoor> Doors => BaseElevatorDoor.GetDoorsForGroup(Group).Select(ElevatorDoor.Get)!; + + /// <summary> + /// Gets all the rooms associated with this elevator. + /// </summary> + public IEnumerable<Room> Rooms => Doors.SelectMany(static x => x.Rooms); + /// <summary> /// Gets the current destination / location of the elevator. /// </summary> @@ -65,11 +76,6 @@ internal static void Initialize() /// </summary> public ElevatorDoor NextDestination => ElevatorDoor.Get(Base.NextDestinationDoor); - /// <summary> - /// Gets all rooms this elevator can move to. - /// </summary> - public IEnumerable<Room> Rooms => Base.FloorDoors.SelectMany(door => door.Rooms.Select(Room.Get)); - /// <summary> /// Gets the destination floor index this elevator will head towards once activated. /// </summary> diff --git a/LabApi/Features/Wrappers/Facility/Hazards/SinkholeHazard.cs b/LabApi/Features/Wrappers/Facility/Hazards/SinkholeHazard.cs index d77c9a80..8e563a2e 100644 --- a/LabApi/Features/Wrappers/Facility/Hazards/SinkholeHazard.cs +++ b/LabApi/Features/Wrappers/Facility/Hazards/SinkholeHazard.cs @@ -20,7 +20,7 @@ public class SinkholeHazard : Hazard /// <summary> /// Gets all currently active sinkholes. /// </summary> - public new IReadOnlyCollection<SinkholeHazard> List => Dictionary.Values; + public static new IReadOnlyCollection<SinkholeHazard> List => Dictionary.Values; /// <summary> /// Prefab used to spawn the hazard. diff --git a/LabApi/Features/Wrappers/Facility/Warhead.cs b/LabApi/Features/Wrappers/Facility/Warhead.cs index 5f06b8d1..963495fc 100644 --- a/LabApi/Features/Wrappers/Facility/Warhead.cs +++ b/LabApi/Features/Wrappers/Facility/Warhead.cs @@ -122,6 +122,34 @@ public static double CooldownTime } } + /// <summary> + /// Forces DMS sequence to count down even if conditions are not met. + /// </summary> + public static bool ForceCountdownToggle + { + get => DeadmanSwitch.ForceCountdownToggle; + set => DeadmanSwitch.ForceCountdownToggle = value; + } + + /// <summary> + /// Indicates how much time is left for the DMS to activate. + /// Value is capped by <see cref="DeadManSwitchMaxTime"/>. + /// </summary> + public static float DeadManSwitchRemaining + { + get => DeadmanSwitch.CountdownTimeLeft; + set => DeadmanSwitch.CountdownTimeLeft = value; + } + + /// <summary> + /// Indicates the amount of time it takes for the DMS to activate. + /// </summary> + public static float DeadManSwitchMaxTime + { + get => DeadmanSwitch.CountdownMaxTime; + set => DeadmanSwitch.CountdownMaxTime = value; + } + /// <summary> /// Gets or sets the value for which <see cref="DetonationScenario"/> to use. /// </summary> diff --git a/LabApi/Features/Wrappers/Players/Player.cs b/LabApi/Features/Wrappers/Players/Player.cs index a1dfeaf1..74030993 100644 --- a/LabApi/Features/Wrappers/Players/Player.cs +++ b/LabApi/Features/Wrappers/Players/Player.cs @@ -1076,6 +1076,53 @@ public static bool TryGet(int playerId, [NotNullWhen(true)] out Player? player) #region Get Player from a Name + /// <summary> + /// Get closest player by lexicographical order. + /// Players are compared by their <see cref="DisplayName"/>. + /// </summary> + /// <param name="input">The input to search the player by.</param> + /// <param name="requireFullMatch">Whether the full match is required.</param> + /// <returns>Player or <see langword="null"/> if no close player found.</returns> + public static Player? GetByDisplayName(string input, bool requireFullMatch = false) => GetByName(input, requireFullMatch, static p => p.DisplayName); + + /// <summary> + /// Gets the closest player by lexicographical order. + /// Players are compared by their <see cref="Nickname"/>. + /// </summary> + /// <param name="input">The input to search the player by.</param> + /// <param name="requireFullMatch">Whether the full match is required.</param> + /// <returns>Player or <see langword="null"/> if no close player found.</returns> + public static Player? GetByNickname(string input, bool requireFullMatch = false) => GetByName(input, requireFullMatch, static p => p.Nickname); + + /// <summary> + /// Gets the closest player by lexicographical order. + /// Base function to allow to select by <see langword="string"/> player property. + /// </summary> + /// <param name="input">The input to search the player by.</param> + /// <param name="requireFullMatch">Whether the full match is required.</param> + /// <param name="propertySelector">Function to select player property.</param> + /// <returns>Player or <see langword="null"/> if no close player found.</returns> + public static Player? GetByName(string input, bool requireFullMatch, Func<Player, string> propertySelector) + { + IOrderedEnumerable<Player> sortedPlayers = List.OrderBy(propertySelector); + + foreach (Player player in sortedPlayers) + { + string toCheck = propertySelector(player); + if (requireFullMatch) + { + if (toCheck.Equals(input, StringComparison.OrdinalIgnoreCase)) + return player; + } + else if (toCheck.StartsWith(input, StringComparison.OrdinalIgnoreCase)) + { + return player; + } + } + + return null; + } + /// <summary> /// Tries to get players by name by seeing if their name starts with the input. /// </summary> @@ -1106,6 +1153,24 @@ public static bool TryGetPlayersByName(string input, out List<Player> players) /// <param name="delta">Rotation to add to the current one. X is vertical and Y is horizontal rotation.</param> public void Rotate(Vector2 delta) => ReferenceHub.TryOverrideRotation(LookRotation + delta); + /// <summary> + /// Forces <see cref="IFpcRole"/> to jump. + /// <para>Jumping can be also adjusted via <see cref="HeavyFooted"/> and <see cref="Lightweight"/> status effects.</para> + /// </summary> + /// <param name="jumpStrength">Strength that the player will jump with.</param> + public void Jump(float jumpStrength) + { + if (ReferenceHub.roleManager.CurrentRole is IFpcRole fpcRole) + fpcRole.FpcModule.Motor.JumpController.ForceJump(jumpStrength); + } + + /// <inheritdoc cref="Jump(float)"/> + public void Jump() + { + if (ReferenceHub.roleManager.CurrentRole is IFpcRole fpcRole) + Jump(fpcRole.FpcModule.JumpSpeed); + } + /// <summary> /// Clears displayed broadcast(s). /// </summary> diff --git a/LabApi/LabApi.csproj b/LabApi/LabApi.csproj index deb9995d..36b605e0 100644 --- a/LabApi/LabApi.csproj +++ b/LabApi/LabApi.csproj @@ -63,7 +63,7 @@ <ItemGroup> <ProjectReference Include="..\LabApi.SourceGenerators\LabApi.SourceGenerators\LabApi.SourceGenerators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" /> </ItemGroup> - + <Target Name="PostBuild" AfterTargets="PostBuildEvent"> <Copy SourceFiles="$(TargetDir)$(TargetName).dll" DestinationFolder="$(SL_SOURCE)\Assets\Plugins" Condition=" '$(SL_SOURCE)' != '' " /> </Target> From a58567e282faf615407c20f6925f41b3854c8dba Mon Sep 17 00:00:00 2001 From: davidsebesta <david.sebesta@post.cz> Date: Sun, 20 Jul 2025 17:47:07 +0200 Subject: [PATCH 052/215] Event Fixes and Additions --- .../EscapedObjectiveEventArgs.cs | 9 ++++++++- .../EscapingObjectiveEventArgs.cs | 9 ++++++++- .../PlayerEvents/PlayerEscapedEventArgs.cs | 10 +++++++++- .../PlayerEvents/PlayerEscapingEventArgs.cs | 10 +++++++++- .../Scp079GainedExperienceEventArgs.cs | 11 +++++++++- .../Scp079GainingExperienceEventArgs.cs | 20 +++++++++++++------ .../Rooms/PocketDimension/PocketDimension.cs | 4 ++-- 7 files changed, 60 insertions(+), 13 deletions(-) diff --git a/LabApi/Events/Arguments/ObjectiveEvents/EscapedObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/EscapedObjectiveEventArgs.cs index 8a29f82a..1bbe2127 100644 --- a/LabApi/Events/Arguments/ObjectiveEvents/EscapedObjectiveEventArgs.cs +++ b/LabApi/Events/Arguments/ObjectiveEvents/EscapedObjectiveEventArgs.cs @@ -16,11 +16,18 @@ public class EscapedObjectiveEventArgs : ObjectiveCompletedBaseEventArgs /// <param name="timeToGrant">The time to reduce from the <paramref name="faction"/>.</param> /// <param name="newRole">The new role the player gets after escaping.</param> /// <param name="sendToPlayers">Whether the objective completion has been sent to players.</param> - public EscapedObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, bool sendToPlayers, RoleTypeId newRole) : base(hub, faction, influenceToGrant, timeToGrant, sendToPlayers) + /// <param name="oldRole">The old role of the player.</param> + public EscapedObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, bool sendToPlayers, RoleTypeId oldRole, RoleTypeId newRole) : base(hub, faction, influenceToGrant, timeToGrant, sendToPlayers) { + OldRole = oldRole; NewRole = newRole; } + /// <summary> + /// Gets the old role of the player. + /// </summary> + public RoleTypeId OldRole { get; } + /// <summary> /// Gets the new role the player is getting. /// </summary> diff --git a/LabApi/Events/Arguments/ObjectiveEvents/EscapingObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/EscapingObjectiveEventArgs.cs index db85602a..830761ab 100644 --- a/LabApi/Events/Arguments/ObjectiveEvents/EscapingObjectiveEventArgs.cs +++ b/LabApi/Events/Arguments/ObjectiveEvents/EscapingObjectiveEventArgs.cs @@ -15,11 +15,18 @@ public class EscapingObjectiveEventArgs : ObjectiveCompletingBaseEventArgs /// <param name="influenceToGrant">The influence points to grant to the <paramref name="faction"/>.</param> /// <param name="timeToGrant">The time to reduce from the <paramref name="faction"/>.</param> /// <param name="newRole">The new role the player gets after escaping.</param> - public EscapingObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, RoleTypeId newRole) : base(hub, faction, influenceToGrant, timeToGrant) + /// <param name="oldRole">The old role of the player.</param> + public EscapingObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, RoleTypeId oldRole, RoleTypeId newRole) : base(hub, faction, influenceToGrant, timeToGrant) { + OldRole = oldRole; NewRole = newRole; } + /// <summary> + /// Gets the old role of the player. + /// </summary> + public RoleTypeId OldRole { get; } + /// <summary> /// Gets the new role the player is getting. /// </summary> diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerEscapedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerEscapedEventArgs.cs index 0d9268ec..bb7c7e70 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerEscapedEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerEscapedEventArgs.cs @@ -18,9 +18,12 @@ public class PlayerEscapedEventArgs : EventArgs, IPlayerEvent /// <param name="player">The player who escaped.</param> /// <param name="newRole">The new role.</param> /// <param name="escapeScenarioType">The scenario of the escape.</param> - public PlayerEscapedEventArgs(ReferenceHub player, RoleTypeId newRole, EscapeScenarioType escapeScenarioType, Bounds escapeZone) + /// <param name="oldRole">The old role of the player.</param> + /// <param name="escapeZone">The bounds of the escape zone that was triggered.</param> + public PlayerEscapedEventArgs(ReferenceHub player, RoleTypeId oldRole, RoleTypeId newRole, EscapeScenarioType escapeScenarioType, Bounds escapeZone) { Player = Player.Get(player); + OldRole = oldRole; NewRole = newRole; EscapeScenarioType = escapeScenarioType; EscapeZone = escapeZone; @@ -31,6 +34,11 @@ public PlayerEscapedEventArgs(ReferenceHub player, RoleTypeId newRole, EscapeSce /// </summary> public Player Player { get; } + /// <summary> + /// Gets the old role of the player. + /// </summary> + public RoleTypeId OldRole { get; } + /// <summary> /// Gets the new role. /// </summary> diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerEscapingEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerEscapingEventArgs.cs index 52e3dae7..7d35fc47 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerEscapingEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerEscapingEventArgs.cs @@ -18,10 +18,13 @@ public class PlayerEscapingEventArgs : EventArgs, IPlayerEvent, ICancellableEven /// <param name="player">The player who is escaping.</param> /// <param name="newRole">The new role that is set after escape.</param> /// <param name="escapeScenario">The scenario of the escape.</param> - public PlayerEscapingEventArgs(ReferenceHub player, RoleTypeId newRole, EscapeScenarioType escapeScenario, Bounds escapeZone) + /// <param name="oldRole">The old role of the player.</param> + /// <param name="escapeZone">The bounds of the escape zone that was triggered.</param> + public PlayerEscapingEventArgs(ReferenceHub player, RoleTypeId oldRole, RoleTypeId newRole, EscapeScenarioType escapeScenario, Bounds escapeZone) { IsAllowed = true; Player = Player.Get(player); + OldRole = oldRole; NewRole = newRole; EscapeScenario = escapeScenario; EscapeZone = escapeZone; @@ -32,6 +35,11 @@ public PlayerEscapingEventArgs(ReferenceHub player, RoleTypeId newRole, EscapeSc /// </summary> public Player Player { get; } + /// <summary> + /// Gets the old role of the player. + /// </summary> + public RoleTypeId OldRole { get; } + /// <summary> /// Gets or sets the new role that is set after escape. /// </summary> diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079GainedExperienceEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079GainedExperienceEventArgs.cs index be6aba7a..bfcfe624 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079GainedExperienceEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079GainedExperienceEventArgs.cs @@ -1,7 +1,9 @@ using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using PlayerRoles; using PlayerRoles.PlayableScps.Scp079; using System; +using UnityEngine; namespace LabApi.Events.Arguments.Scp079Events; @@ -16,11 +18,13 @@ public class Scp079GainedExperienceEventArgs : EventArgs, IPlayerEvent /// <param name="player">The SCP-079 player instance.</param> /// <param name="amount">The amount of experience gained.</param> /// <param name="reason">The reason of experience gain shown in HUD.</param> - public Scp079GainedExperienceEventArgs(ReferenceHub player, float amount, Scp079HudTranslation reason) + /// <param name = "subject" > The optional subject of the notification, used as replacement to display which class has been terminated</param> + public Scp079GainedExperienceEventArgs(ReferenceHub player, float amount, Scp079HudTranslation reason, RoleTypeId subject) { Player = Player.Get(player); Amount = amount; Reason = reason; + Subject = subject; } /// <summary> @@ -37,4 +41,9 @@ public Scp079GainedExperienceEventArgs(ReferenceHub player, float amount, Scp079 /// The reason of experience gain shown in HUD. /// </summary> public Scp079HudTranslation Reason { get; } + + /// <summary> + /// Gets optional subject of the notification, used as replacement to display which class has been terminated. + /// </summary> + public RoleTypeId Subject { get; } } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079GainingExperienceEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079GainingExperienceEventArgs.cs index 787811a1..75e26a99 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079GainingExperienceEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079GainingExperienceEventArgs.cs @@ -1,5 +1,6 @@ using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using PlayerRoles; using PlayerRoles.PlayableScps.Scp079; using System; @@ -16,28 +17,35 @@ public class Scp079GainingExperienceEventArgs : EventArgs, IPlayerEvent, ICancel /// <param name="player">The SCP-079 player instance.</param> /// <param name="amount">The amount of experience that is going to be gained.</param> /// <param name="reason">The reason of experience gain that is going to be shown in HUD.</param> - public Scp079GainingExperienceEventArgs(ReferenceHub player, float amount, Scp079HudTranslation reason) + /// <param name="subject">The optional subject of the notification, used as replacement to display which class has been terminated</param> + public Scp079GainingExperienceEventArgs(ReferenceHub player, float amount, Scp079HudTranslation reason, RoleTypeId subject) { Player = Player.Get(player); Amount = amount; Reason = reason; + Subject = subject; IsAllowed = true; } /// <summary> - /// The SCP-079 player instance. + /// Gets the SCP-079 player instance. /// </summary> public Player Player { get; } /// <summary> - /// The amount of experience that is going to be gained. + /// Gets or sets the amount of experience that is going to be gained. /// </summary> - public float Amount { get; } + public float Amount { get; set; } /// <summary> - /// The reason of experience gain that is going to be shown in HUD. + /// Gets or sets the reason of experience gain that is going to be shown in HUD. /// </summary> - public Scp079HudTranslation Reason { get; } + public Scp079HudTranslation Reason { get; set; } + + /// <summary> + /// Gets or sets the optional subject of the notification, used as replacement to display which class has been terminated. + /// </summary> + public RoleTypeId Subject { get; set; } /// <inheritdoc /> public bool IsAllowed { get; set; } diff --git a/LabApi/Features/Wrappers/Facility/Rooms/PocketDimension/PocketDimension.cs b/LabApi/Features/Wrappers/Facility/Rooms/PocketDimension/PocketDimension.cs index 3c4839d0..af10e71b 100644 --- a/LabApi/Features/Wrappers/Facility/Rooms/PocketDimension/PocketDimension.cs +++ b/LabApi/Features/Wrappers/Facility/Rooms/PocketDimension/PocketDimension.cs @@ -121,7 +121,7 @@ public static Vector3 GetCaughtPosition(Player player) /// Triggers pocket dimension leaving/left events. /// </remarks> public static void ForceExit(Player player) - => PocketDimensionTeleport.Exit(null, player.ReferenceHub); + => PocketDimensionTeleport.TryExit(null, player.ReferenceHub); /// <summary> /// Force a player to be killed by the pocket dimension. @@ -132,7 +132,7 @@ public static void ForceExit(Player player) /// Triggers pocket dimension leaving/left events. /// </remarks> public static void ForceKill(Player player) - => PocketDimensionTeleport.Kill(null, player.ReferenceHub); + => PocketDimensionTeleport.TryKill(null, player.ReferenceHub); /// <summary> /// Gets whether a <see cref="Pickup"/> is inside the pocket dimension. From 5000ed0d5b4071cd3b92ca0b787315f8596dbef1 Mon Sep 17 00:00:00 2001 From: davidsebesta1 <david.sebesta@post.cz> Date: Wed, 23 Jul 2025 11:31:01 +0200 Subject: [PATCH 053/215] Added SCP-127 teleporting/ed events Added respawn effect play to respawn wave Added Window wrapper Added energy to MicroHID pickup Fixed cassie clear method Fixed CheckEvent method ambigious method exception --- .../Scp173Events/Scp173TeleportedEventArgs.cs | 41 +++++ .../Scp173TeleportingEventArgs.cs | 37 +++++ .../CustomHandlers/CustomHandlersManager.cs | 17 +- .../Handlers/Scp173Events.EventHandlers.cs | 10 ++ LabApi/Features/Wrappers/Facility/Cassie.cs | 3 +- .../Facility/Respawning/Waves/RespawnWave.cs | 11 ++ .../Wrappers/Facility/Structures/Window.cs | 148 ++++++++++++++++++ .../Wrappers/Pickups/MicroHIDPickup.cs | 26 ++- 8 files changed, 287 insertions(+), 6 deletions(-) create mode 100644 LabApi/Events/Arguments/Scp173Events/Scp173TeleportedEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp173Events/Scp173TeleportingEventArgs.cs create mode 100644 LabApi/Features/Wrappers/Facility/Structures/Window.cs diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173TeleportedEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173TeleportedEventArgs.cs new file mode 100644 index 00000000..e77a7e5b --- /dev/null +++ b/LabApi/Events/Arguments/Scp173Events/Scp173TeleportedEventArgs.cs @@ -0,0 +1,41 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using UnityEngine; + +namespace LabApi.Events.Arguments.Scp173Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp173Events.Teleported"/> event. +/// </summary> +public class Scp173TeleportedEventArgs : EventArgs, IPlayerEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp173TeleportingEventArgs"/> class. + /// </summary> + /// <param name="hub">The SCP-173 player.</param> + /// <param name="position">The target position to teleport to.</param> + public Scp173TeleportedEventArgs(ReferenceHub hub, Vector3 position) + { + IsAllowed = true; + Player = Player.Get(hub); + Position = position; + } + + /// <summary> + /// Gets the SCP-173 player instance. + /// </summary> + public Player Player { get; } + + /// <summary> + /// Gets the target player position that the SCP-173 has teleported to. + /// Note that this position is on the floor and the <see cref="Player"/> has been teleported 1/2 of its character height up to prevent clipping through floor. + /// </summary> + public Vector3 Position { get; } + + /// <summary> + /// Gets or sets whether the SCP-173 player can teleport.<para/> + /// This even is fired even if the charge ability is not ready so you may override it on the server aswell. + /// </summary> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173TeleportingEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173TeleportingEventArgs.cs new file mode 100644 index 00000000..afa550e6 --- /dev/null +++ b/LabApi/Events/Arguments/Scp173Events/Scp173TeleportingEventArgs.cs @@ -0,0 +1,37 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using UnityEngine; + +namespace LabApi.Events.Arguments.Scp173Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp173Events.Teleporting"/> event. +/// </summary> +public class Scp173TeleportingEventArgs : EventArgs, IPlayerEvent, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp173TeleportingEventArgs"/> class. + /// </summary> + /// <param name="hub">The SCP-173 player.</param> + /// <param name="position">The target position to teleport to.</param> + public Scp173TeleportingEventArgs(ReferenceHub hub, Vector3 position) + { + IsAllowed = true; + Player = Player.Get(hub); + } + + /// <summary> + /// Gets the SCP-173 player instance. + /// </summary> + public Player Player { get; } + + /// <summary> + /// Gets or sets the target player position to teleport SCP-173 player to.<para/> + /// Note that this position is on the floor and the <see cref="Player"/> is then teleported 1/2 of its character height up to prevent clipping through floor. + /// </summary> + public Vector3 Position { get; set; } + + /// <inheritdoc /> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/CustomHandlers/CustomHandlersManager.cs b/LabApi/Events/CustomHandlers/CustomHandlersManager.cs index ea493357..b7de5fdd 100644 --- a/LabApi/Events/CustomHandlers/CustomHandlersManager.cs +++ b/LabApi/Events/CustomHandlers/CustomHandlersManager.cs @@ -49,11 +49,20 @@ public static void UnregisterEventsHandler<T>(T handler) public static void CheckEvent<T>(T handler, Type handlerType, string methodDelegate, Type eventType, string eventName) where T : CustomEventsHandler { - // We first get the method from the handler. - MethodInfo? method = handlerType.GetMethod(methodDelegate, BindingFlags.Public | BindingFlags.Instance); + // We first get the method from the handler, there can be custom methods names as the original events but with different overloads, so we filter them. + MethodInfo[] candidates = handlerType.GetMethods(BindingFlags.Public | BindingFlags.Instance); - // If the method is null or not an override, we return. - if (method == null || !IsOverride(method)) + MethodInfo method = null; + foreach (MethodInfo candidate in candidates) + { + if (candidate.Name == methodDelegate && IsOverride(candidate)) + { + method = candidate; + break; + } + } + + if (method == null) return; // We get the event from the event type. diff --git a/LabApi/Events/Handlers/Scp173Events.EventHandlers.cs b/LabApi/Events/Handlers/Scp173Events.EventHandlers.cs index dd597691..fef62eb3 100644 --- a/LabApi/Events/Handlers/Scp173Events.EventHandlers.cs +++ b/LabApi/Events/Handlers/Scp173Events.EventHandlers.cs @@ -56,4 +56,14 @@ public static partial class Scp173Events /// Gets called when SCP-173 has played a sound. /// </summary> public static event LabEventHandler<Scp173PlayedSoundEventArgs>? PlayedSound; + + /// <summary> + /// Gets called when SCP-173 is teleporting. + /// </summary> + public static event LabEventHandler<Scp173TeleportingEventArgs>? Teleporting; + + /// <summary> + /// Gets called when SCP-173 has teleported. + /// </summary> + public static event LabEventHandler<Scp173TeleportedEventArgs>? Teleported; } \ No newline at end of file diff --git a/LabApi/Features/Wrappers/Facility/Cassie.cs b/LabApi/Features/Wrappers/Facility/Cassie.cs index 79d267e8..9b74b818 100644 --- a/LabApi/Features/Wrappers/Facility/Cassie.cs +++ b/LabApi/Features/Wrappers/Facility/Cassie.cs @@ -40,6 +40,7 @@ public static class Cassie /// </summary> /// <param name="message">The message.</param> /// <param name="rawNumber">Raw numbers.</param> + /// <param name="speed">The speed of the cassie talking.</param> /// <returns>Duration of the specific message in seconds.</returns> public static float CalculateDuration(string message, bool rawNumber = false, float speed = 1f) => singleton.CalculateDuration(message, rawNumber, speed); @@ -71,7 +72,7 @@ public static class Cassie /// <summary> /// Clears the Cassie announcements queue. /// </summary> - public static void Clear() => singleton.ClearQueue(); + public static void Clear() => RespawnEffectsController.ClearQueue(); /// <summary> /// Converts player's team into Cassie-able word. Unit names are converted into NATO_X words, followed by a number. For example "Alpha-5" is converted to "NATO_A 5". diff --git a/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs b/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs index 52246ae7..77489098 100644 --- a/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs +++ b/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs @@ -142,4 +142,15 @@ public void PlayAnnouncement() if (Base is IAnnouncedWave wave) wave.Announcement.PlayAnnouncement(); } + + /// <summary> + /// Plays the respawn animation without spawning the wave. + /// </summary> + public void PlayRespawnEffect() + { + if (Base is not IAnimatedWave) + return; + + WaveUpdateMessage.ServerSendUpdate(Base, UpdateMessageFlags.Trigger); + } } diff --git a/LabApi/Features/Wrappers/Facility/Structures/Window.cs b/LabApi/Features/Wrappers/Facility/Structures/Window.cs new file mode 100644 index 00000000..5a626f76 --- /dev/null +++ b/LabApi/Features/Wrappers/Facility/Structures/Window.cs @@ -0,0 +1,148 @@ +using Generators; +using MapGeneration.Distributors; +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using UnityEngine; + +namespace LabApi.Features.Wrappers; + +/// <summary> +/// The wrapper over the <see cref="BreakableWindow"/> object. +/// </summary> +public class Window +{ + /// <summary> + /// Initializes the <see cref="Window"/> wrapper by subscribing to <see cref="BreakableWindow"/> events. + /// </summary> + [InitializeWrapper] + internal static void Initialize() + { + //TODO: Add added and removed methods + } + + /// <summary> + /// Contains all the cached structures, accessible through their <see cref="SpawnableStructure"/>. + /// </summary> + public static Dictionary<BreakableWindow, Window> Dictionary { get; } = []; + + /// <summary> + /// A reference to all <see cref="Structure"/> instances. + /// </summary> + public static IReadOnlyCollection<Window> List => Dictionary.Values; + + /// <summary> + /// An internal constructor to prevent external instantiation. + /// </summary> + /// <param name="breakableWindow">The base <see cref="BreakableWindow"/> object.</param> + internal Window(BreakableWindow breakableWindow) + { + Base = breakableWindow; + + if (CanCache) + Dictionary.Add(breakableWindow, this); + } + + /// <summary> + /// An internal method to remove itself from the cache when the base object is destroyed. + /// </summary> + internal virtual void OnRemove() + { + Dictionary.Remove(Base); + } + + /// <summary> + /// The base <see cref="SpawnableStructure"/> object. + /// </summary> + public BreakableWindow Base { get; } + + /// <summary> + /// Gets the structure's <see cref="UnityEngine.GameObject"/>. + /// </summary> + public GameObject GameObject => Base.gameObject; + + /// <summary> + /// Gets the structure's <see cref="UnityEngine.Transform"/>. + /// </summary> + public Transform Transform => Base.transform; + + /// <summary> + /// Whether to cache the wrapper. + /// </summary> + protected internal bool CanCache => !IsDestroyed && Base.isActiveAndEnabled; + + /// <summary> + /// Gets whether the window was destroyed. + /// </summary> + public bool IsDestroyed => Base == null || GameObject == null; + + /// <summary> + /// Gets or sets the window's position. + /// </summary> + public Vector3 Position + { + get => Transform.position; + } + + /// <summary> + /// Gets or sets the window's rotatiom. + /// </summary> + public Quaternion Rotation + { + get => Transform.rotation; + } + + /// <inheritdoc /> + public override string ToString() + { + return $"[{GetType().Name}: Position={Position}, Rotation={Rotation} IsDestroyed={IsDestroyed}]"; + } + + /// <summary> + /// Gets the structure wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BreakableWindow"/> was not <see langword="null"/>. + /// </summary> + /// <param name="breakableWindow">The <see cref="Base"/> of the window.</param> + /// <returns>The requested structure or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(breakableWindow))] + public static Window? Get(BreakableWindow? breakableWindow) + { + if (breakableWindow == null) + return null; + + return Dictionary.TryGetValue(breakableWindow, out Window structure) ? structure : new Window(breakableWindow); + } + + /// <summary> + /// Tries to get the window wrapper from the <see cref="Dictionary"/>. + /// </summary> + /// <param name="breakableWindow">The <see cref="Base"/> of the window.</param> + /// <param name="window">The requested window.</param> + /// <returns>True of the structure exists, otherwise false.</returns> + public static bool TryGet(BreakableWindow? breakableWindow, [NotNullWhen(true)] out Window? window) + { + window = Get(breakableWindow); + return window != null; + } + + /// <summary> + /// Private method to handle the creation of new windows in the server. + /// </summary> + /// <param name="structure">The <see cref="BreakableWindow"/> that was created.</param> + private static void OnAdded(BreakableWindow structure) + { + if (!Dictionary.ContainsKey(structure)) + _ = new Window(structure); + } + + /// <summary> + /// Private method to handle the removal of windows from the server. + /// </summary> + /// <param name="spawnableStructure">The <see cref="BreakableWindow"/> that was removed.</param> + private static void OnRemoved(BreakableWindow spawnableStructure) + { + if (Dictionary.TryGetValue(spawnableStructure, out Window structure)) + structure.OnRemove(); + } + + +} diff --git a/LabApi/Features/Wrappers/Pickups/MicroHIDPickup.cs b/LabApi/Features/Wrappers/Pickups/MicroHIDPickup.cs index 6d30c11d..49415d36 100644 --- a/LabApi/Features/Wrappers/Pickups/MicroHIDPickup.cs +++ b/LabApi/Features/Wrappers/Pickups/MicroHIDPickup.cs @@ -1,4 +1,6 @@ -using InventorySystem.Items.MicroHID.Modules; +using InventorySystem; +using InventorySystem.Items.MicroHID.Modules; +using LabApi.Features.Console; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using BaseMicroHIDPickup = InventorySystem.Items.MicroHID.MicroHIDPickup; @@ -71,6 +73,28 @@ public MicroHidFiringMode FiringMode set => BaseCycleController.LastFiringMode = value; } + /// <summary> + /// Gets or sets the energy amount in this Micro-HID pickup.<para/> + /// Value for the energy is between 0f - 1f and is automatically clamped. + /// </summary> + public float Energy + { + get + { + return EnergyManagerModule.GetEnergy(Serial); + } + set + { + if (!InventoryItemLoader.TryGetItem(ItemType.MicroHID, out InventorySystem.Items.MicroHID.MicroHIDItem item)) + { + Logger.Error("Unable to get the base microhid item!"); + return; + } + + item.EnergyManager.ServerSetEnergy(Serial, value); + } + } + /// <summary> /// The progress from 0 to 1 for how ready the micro is to fire. /// Goes up when winding up, and down when winding down. From 79daec2bc9ed45dae16b6f778a32bd1b8b59c64e Mon Sep 17 00:00:00 2001 From: Placeholder github Source User <braydendowson_placeholder_10l6sno@noreply.git.scpslgame.com> Date: Wed, 23 Jul 2025 20:27:13 +0000 Subject: [PATCH 054/215] waypoint toy - Riptide --- .../Features/Wrappers/AdminToys/AdminToy.cs | 1 + .../Wrappers/AdminToys/WaypointToy.cs | 133 ++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 LabApi/Features/Wrappers/AdminToys/WaypointToy.cs diff --git a/LabApi/Features/Wrappers/AdminToys/AdminToy.cs b/LabApi/Features/Wrappers/AdminToys/AdminToy.cs index 507168bd..6dd8cdaf 100644 --- a/LabApi/Features/Wrappers/AdminToys/AdminToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/AdminToy.cs @@ -30,6 +30,7 @@ internal static void Initialize() Register<Scp079CameraToy>(static x => new CameraToy(x)); Register<AdminToys.CapybaraToy>(static x => new CapybaraToy(x)); Register<AdminToys.TextToy>(static x => new TextToy(x)); + Register<AdminToys.WaypointToy>(static x => new WaypointToy(x)); } /// <summary> diff --git a/LabApi/Features/Wrappers/AdminToys/WaypointToy.cs b/LabApi/Features/Wrappers/AdminToys/WaypointToy.cs new file mode 100644 index 00000000..9c5e0fa7 --- /dev/null +++ b/LabApi/Features/Wrappers/AdminToys/WaypointToy.cs @@ -0,0 +1,133 @@ +using LabApi.Features.Wrappers; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using UnityEngine; +using BaseWaypointToy = AdminToys.WaypointToy; + +namespace LabApi.Features.Wrappers; + +/// <summary> +/// Wrapper for the <see cref="BaseWaypointToy"/> class. +/// </summary> +public class WaypointToy : AdminToy +{ + /// <summary> + /// Contains all the waypoint toys, accessible through their <see cref="Base"/>. + /// </summary> + public new static Dictionary<BaseWaypointToy, WaypointToy> Dictionary { get; } = []; + + /// <summary> + /// A reference to all instances of <see cref="WaypointToy"/>. + /// </summary> + public new static IReadOnlyCollection<WaypointToy> List => Dictionary.Values; + + /// <summary> + /// The <see cref="BaseWaypointToy"/> object. + /// </summary> + public new BaseWaypointToy Base { get; } + + /// <summary> + /// Gets or sets whether to visualize the waypoint's maximum bounds. + /// </summary> + public bool VisualizeBounds + { + get => Base.VisualizeBounds; + set => Base.NetworkVisualizeBounds = value; + } + + /// <summary> + /// Gets or sets how many meters to bias towards this waypoint. + /// </summary> + /// <remarks> + /// The closest waypoint is determined by its square distance. + /// When set this takes away <c>(Priority * Priority)</c> from the sqr distance. + /// </remarks> + public float PriorityBias + { + get => Base.Priority; + set => Base.NetworkPriority = value; + } + + /// <summary> + /// An internal constructor to prevent external instantiation. + /// </summary> + /// <param name="baseWaypointToy">The base <see cref="BaseWaypointToy"/> object.</param> + internal WaypointToy(BaseWaypointToy baseWaypointToy) + : base(baseWaypointToy) + { + Dictionary.Add(baseWaypointToy, this); + Base = baseWaypointToy; + } + + /// <summary> + /// An internal method to remove itself from the cache when the base object is destroyed. + /// </summary> + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); + } + + /// <inheritdoc /> + public override string ToString() + { + return $"[WaypointToy: Position{Position}, VisualizeBounds:{VisualizeBounds}, PriorityBias:{PriorityBias}]"; + } + + /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> + public static WaypointToy Create(Transform? parent = null, bool networkSpawn = true) + => Create(Vector3.zero, parent, networkSpawn); + + /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> + public static WaypointToy Create(Vector3 position, Transform? parent = null, bool networkSpawn = true) + => Create(position, Quaternion.identity, parent, networkSpawn); + + /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> + public static WaypointToy Create(Vector3 position, Quaternion rotation, Transform? parent = null, bool networkSpawn = true) + => Create(position, rotation, Vector3.one, parent, networkSpawn); + + /// <summary> + /// Creates a new waypoint toy. + /// </summary> + /// <param name="position">The initial local position.</param> + /// <param name="rotation">The initial local rotation.</param> + /// <param name="scale">The initial local scale.</param> + /// <param name="parent">The parent transform.</param> + /// <param name="networkSpawn">Whether to spawn the toy on the client.</param> + /// <returns>The created waypoint toy.</returns> + public static WaypointToy Create(Vector3 position, Quaternion rotation, Vector3 scale, Transform? parent = null, bool networkSpawn = true) + { + WaypointToy toy = Get(Create<BaseWaypointToy>(position, rotation, scale, parent)); + + if (networkSpawn) + toy.Spawn(); + + return toy; + } + + /// <summary> + /// Gets the waypoint toy wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseWaypointToy"/> was not <see langword="null"/>. + /// </summary> + /// <param name="baseWaypointToy">The <see cref="Base"/> of the waypoint toy.</param> + /// <returns>The requested waypoint toy or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(baseWaypointToy))] + public static WaypointToy? Get(BaseWaypointToy? baseWaypointToy) + { + if (baseWaypointToy == null) + return null; + + return Dictionary.TryGetValue(baseWaypointToy, out WaypointToy item) ? item : (WaypointToy)CreateAdminToyWrapper(baseWaypointToy); + } + + /// <summary> + /// Tries to get the waypoint toy wrapper from the <see cref="Dictionary"/>. + /// </summary> + /// <param name="baseWaypointToy">The <see cref="Base"/> of the waypoint toy.</param> + /// <param name="waypointToy">The requested waypoint toy.</param> + /// <returns><see langword="True"/> if the waypoint exists, otherwise <see langword="false"/>.</returns> + public static bool TryGet(BaseWaypointToy? baseWaypointToy, [NotNullWhen(true)] out WaypointToy? waypointToy) + { + waypointToy = Get(baseWaypointToy); + return waypointToy != null; + } +} From 23de6f379f3e9f7831a065cb41275e042df49f31 Mon Sep 17 00:00:00 2001 From: davidsebesta1 <david.sebesta@post.cz> Date: Thu, 24 Jul 2025 00:09:52 +0200 Subject: [PATCH 055/215] Window finalize with events and properties --- .../Wrappers/Facility/Structures/Window.cs | 32 +++++++++++++++---- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Structures/Window.cs b/LabApi/Features/Wrappers/Facility/Structures/Window.cs index 5a626f76..6f54309c 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/Window.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/Window.cs @@ -1,6 +1,6 @@ using Generators; using MapGeneration.Distributors; -using System; +using PlayerStatsSystem; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using UnityEngine; @@ -18,11 +18,12 @@ public class Window [InitializeWrapper] internal static void Initialize() { - //TODO: Add added and removed methods + BreakableWindow.OnAdded += OnAdded; + BreakableWindow.OnDestroyed += OnRemoved; } /// <summary> - /// Contains all the cached structures, accessible through their <see cref="SpawnableStructure"/>. + /// Contains all the cached structures, accessible through their <see cref="BreakableWindow"/>. /// </summary> public static Dictionary<BreakableWindow, Window> Dictionary { get; } = []; @@ -72,12 +73,29 @@ internal virtual void OnRemove() protected internal bool CanCache => !IsDestroyed && Base.isActiveAndEnabled; /// <summary> - /// Gets whether the window was destroyed. + /// Gets whether the window gameobject was destroyed. /// </summary> public bool IsDestroyed => Base == null || GameObject == null; /// <summary> - /// Gets or sets the window's position. + /// Gets whether the window is broken. + /// </summary> + public bool IsBroken => Base.NetworkIsBroken; + + /// <summary> + /// Gets or sets window's health. + /// </summary> + public float Health + { + get => Base.Health; + set + { + Base.Damage(Base.Health - value, new CustomReasonDamageHandler(string.Empty), Vector3.zero); + } + } + + /// <summary> + /// Gets the window's position. /// </summary> public Vector3 Position { @@ -85,7 +103,7 @@ public Vector3 Position } /// <summary> - /// Gets or sets the window's rotatiom. + /// Gets the window's rotation. /// </summary> public Quaternion Rotation { @@ -117,7 +135,7 @@ public override string ToString() /// </summary> /// <param name="breakableWindow">The <see cref="Base"/> of the window.</param> /// <param name="window">The requested window.</param> - /// <returns>True of the structure exists, otherwise false.</returns> + /// <returns><see langword="True"/> of the structure exists, otherwise <see langword="false"/>.</returns> public static bool TryGet(BreakableWindow? breakableWindow, [NotNullWhen(true)] out Window? window) { window = Get(breakableWindow); From 5629462acd650700bf57e48b08cfbb8bf433effb Mon Sep 17 00:00:00 2001 From: Placeholder David <davidsebesta1_placeholder_1e98un7@noreply.git.scpslgame.com> Date: Thu, 24 Jul 2025 10:43:35 +0000 Subject: [PATCH 056/215] Firearms wrappers - David --- .../LogAll/LogPlugin/MyCustomEventsHandler.cs | 45 ++ .../Items/Firearms/IRevolverItemEvent.cs | 17 + .../Items/Firearms/IScp127ItemEvent.cs | 19 + .../PlayerActivatedGeneratorEventArgs.cs | 6 +- .../PlayerActivatingGeneratorEventArgs.cs | 6 +- .../PlayerAimedWeaponEventArgs.cs | 6 +- .../PlayerAimingWeaponEventArgs.cs | 6 +- .../PlayerEvents/PlayerBannedEventArgs.cs | 6 +- .../PlayerEvents/PlayerBanningEventArgs.cs | 6 +- .../PlayerCancelledUsingItemEventArgs.cs | 6 +- .../PlayerCancellingUsingItemEventArgs.cs | 6 +- .../PlayerChangedItemEventArgs.cs | 6 +- .../PlayerChangedNicknameEventArgs.cs | 6 +- .../PlayerChangedRadioRangeEventArgs.cs | 6 +- .../PlayerChangedRoleEventArgs.cs | 6 +- .../PlayerChangedSpectatorEventArgs.cs | 6 +- .../PlayerChangingItemEventArgs.cs | 6 +- .../PlayerChangingNicknameEventArgs.cs | 6 +- .../PlayerChangingRadioRangeEventArgs.cs | 6 +- .../PlayerChangingRoleEventArgs.cs | 6 +- .../PlayerClosedGeneratorEventArgs.cs | 6 +- .../PlayerClosingGeneratorEventArgs.cs | 6 +- .../PlayerEvents/PlayerCuffedEventArgs.cs | 6 +- .../PlayerEvents/PlayerCuffingEventArgs.cs | 6 +- .../PlayerDamagedShootingTargetEventArgs.cs | 6 +- .../PlayerDamagedWindowEventArgs.cs | 6 +- .../PlayerDamagingShootingTargetEventArgs.cs | 6 +- .../PlayerDamagingWindowEventArgs.cs | 6 +- .../PlayerDeactivatedGeneratorEventArgs.cs | 6 +- .../PlayerDeactivatingGeneratorEventArgs.cs | 6 +- .../PlayerEvents/PlayerDeathEventArgs.cs | 6 +- .../PlayerDroppedAmmoEventArgs.cs | 6 +- .../PlayerDroppedItemEventArgs.cs | 6 +- .../PlayerDroppingAmmoEventArgs.cs | 6 +- .../PlayerDroppingItemEventArgs.cs | 6 +- .../PlayerDryFiredWeaponEventArgs.cs | 6 +- .../PlayerDryFiringWeaponEventArgs.cs | 6 +- .../PlayerEvents/PlayerDyingEventArgs.cs | 6 +- .../PlayerEffectUpdatedEventArgs.cs | 6 +- .../PlayerEffectUpdatingEventArgs.cs | 6 +- .../PlayerEnteredHazardEventArgs.cs | 6 +- .../PlayerEnteredPocketDimensionEventArgs.cs | 6 +- .../PlayerEnteringHazardEventArgs.cs | 6 +- .../PlayerEnteringPocketDimensionEventArgs.cs | 6 +- .../PlayerEvents/PlayerEscapedEventArgs.cs | 6 +- .../PlayerEvents/PlayerEscapingEventArgs.cs | 6 +- .../PlayerFlippedCoinEventArgs.cs | 6 +- .../PlayerFlippingCoinEventArgs.cs | 6 +- .../PlayerGroupChangedEventArgs.cs | 6 +- .../PlayerGroupChangingEventArgs.cs | 6 +- .../PlayerInteractedDoorEventArgs.cs | 6 +- .../PlayerInteractedElevatorEventArgs.cs | 6 +- .../PlayerInteractedGeneratorEventArgs.cs | 6 +- .../PlayerInteractedLockerEventArgs.cs | 6 +- .../PlayerInteractedScp330EventArgs.cs | 6 +- ...PlayerInteractedShootingTargetEventArgs.cs | 6 +- .../PlayerInteractedToyEventArgs.cs | 6 +- .../PlayerInteractingDoorEventArgs.cs | 6 +- .../PlayerInteractingElevatorEventArgs.cs | 6 +- .../PlayerInteractingGeneratorEventArgs.cs | 6 +- .../PlayerInteractingLockerEventArgs.cs | 6 +- .../PlayerInteractingScp330EventArgs.cs | 6 +- ...layerInteractingShootingTargetEventArgs.cs | 6 +- .../PlayerEvents/PlayerKickedEventArgs.cs | 6 +- .../PlayerEvents/PlayerKickingEventArgs.cs | 6 +- .../PlayerLeavingHazardEventArgs.cs | 6 +- .../PlayerLeavingPocketDimensionEventArgs.cs | 6 +- .../PlayerEvents/PlayerLeftEventArgs.cs | 6 +- .../PlayerEvents/PlayerLeftHazardEventArgs.cs | 6 +- .../PlayerLeftPocketDimensionEventArgs.cs | 6 +- .../PlayerEvents/PlayerMutedEventArgs.cs | 6 +- .../PlayerEvents/PlayerMutingEventArgs.cs | 6 +- .../PlayerOpenedGeneratorEventArgs.cs | 6 +- .../PlayerOpeningGeneratorEventArgs.cs | 6 +- .../PlayerPickedUpAmmoEventArgs.cs | 6 +- .../PlayerPickedUpArmorEventArgs.cs | 6 +- .../PlayerPickedUpItemEventArgs.cs | 6 +- .../PlayerPickedUpScp330EventArgs.cs | 6 +- .../PlayerPickingUpAmmoEventArgs.cs | 6 +- .../PlayerPickingUpArmorEventArgs.cs | 6 +- .../PlayerPickingUpItemEventArgs.cs | 6 +- .../PlayerPickingUpScp330EventArgs.cs | 6 +- .../PlayerPlacedBloodEventArgs.cs | 6 +- .../PlayerEvents/PlayerPlacedBulletHole.cs | 6 +- .../PlayerPlacingBloodEventArgs.cs | 6 +- .../PlayerPlacingBulletHoleEventArgs.cs | 6 +- .../PlayerReceivedLoadoutEventArgs.cs | 6 +- .../PlayerReceivingLoadoutEventArgs.cs | 6 +- .../PlayerReloadedWeaponEventArgs.cs | 6 +- .../PlayerReloadingWeaponEventArgs.cs | 6 +- .../PlayerReportedCheaterEventArgs.cs | 6 +- .../PlayerReportedPlayerEventArgs.cs | 6 +- .../PlayerReportingCheaterEventArgs.cs | 6 +- .../PlayerReportingPlayerEventArgs.cs | 6 +- .../PlayerSearchToyAbortedEventArgs.cs | 6 +- .../PlayerSearchedAmmoEventArgs.cs | 6 +- .../PlayerSearchedArmorEventArgs.cs | 6 +- .../PlayerSearchedPickupEventArgs.cs | 6 +- .../PlayerSearchedToyEventArgs.cs | 6 +- .../PlayerSearchingAmmoEventArgs.cs | 6 +- .../PlayerSearchingArmorEventArgs.cs | 6 +- .../PlayerSearchingPickupEventArgs.cs | 6 +- .../PlayerSearchingToyEventArgs.cs | 6 +- .../PlayerShootingWeaponEventArgs.cs | 6 +- .../PlayerEvents/PlayerShotWeaponEventArgs.cs | 6 +- .../PlayerEvents/PlayerSpawnedEventArgs.cs | 6 +- .../PlayerSpawnedRagdollEventArgs.cs | 6 +- .../PlayerEvents/PlayerSpawningEventArgs.cs | 6 +- .../PlayerSpawningRagdollEventArgs.cs | 6 +- .../PlayerSpinnedRevolverEventArgs.cs | 32 ++ .../PlayerSpinningRevolverEventArgs.cs | 37 ++ .../PlayerEvents/PlayerThrewItemEventArgs.cs | 6 +- .../PlayerThrewProjectileEventArgs.cs | 6 +- .../PlayerThrowingItemEventArgs.cs | 6 +- .../PlayerThrowingProjectileEventArgs.cs | 6 +- ...ayerToggledDisruptorFiringModeEventArgs.cs | 41 ++ .../PlayerToggledFlashlightEventArgs.cs | 6 +- .../PlayerToggledNoclipEventArgs.cs | 6 +- .../PlayerToggledRadioEventArgs.cs | 6 +- .../PlayerToggledWeaponFlashlightEventArgs.cs | 6 +- .../PlayerTogglingFlashlightEventArgs.cs | 6 +- .../PlayerTogglingNoclipEventArgs.cs | 6 +- .../PlayerTogglingRadioEventArgs.cs | 6 +- ...PlayerTogglingWeaponFlashlightEventArgs.cs | 6 +- .../PlayerEvents/PlayerUncuffedEventArgs.cs | 6 +- .../PlayerEvents/PlayerUncuffingEventArgs.cs | 6 +- .../PlayerUnloadedWeaponEventArgs.cs | 6 +- .../PlayerUnloadingWeaponEventArgs.cs | 6 +- .../PlayerUnlockedGeneratorEventArgs.cs | 6 +- .../PlayerUnlockedWarheadButtonEventArgs.cs | 6 +- .../PlayerUnlockingGeneratorEventArgs.cs | 6 +- .../PlayerUnlockingWarheadButtonEventArgs.cs | 6 +- .../PlayerEvents/PlayerUnmutedEventArgs.cs | 6 +- .../PlayerEvents/PlayerUnmutingEventArgs.cs | 6 +- .../PlayerUsedIntercomEventArgs.cs | 6 +- .../PlayerEvents/PlayerUsedItemEventArgs.cs | 6 +- .../PlayerEvents/PlayerUsedRadioEventArgs.cs | 6 +- .../PlayerUsingIntercomEventArgs.cs | 6 +- .../PlayerEvents/PlayerUsingItemEventArgs.cs | 6 +- .../PlayerEvents/PlayerUsingRadioEventArgs.cs | 6 +- .../Scp049ResurrectedBodyEventArgs.cs | 6 +- .../Scp049ResurrectingBodyEventArgs.cs | 6 +- .../Scp049StartingResurrectionEventArgs.cs | 6 +- .../Scp049UsedDoctorsCallEventArgs.cs | 6 +- .../Scp049Events/Scp049UsedSenseEventArgs.cs | 6 +- .../Scp049UsingDoctorsCallEventArgs.cs | 6 +- .../Scp049Events/Scp049UsingSenseEventArgs.cs | 6 +- .../Scp079BlackedOutRoomEventArgs.cs | 6 +- .../Scp079BlackedOutZoneEventArgs.cs | 6 +- .../Scp079BlackingOutRoomEventsArgs.cs | 6 +- .../Scp079BlackingOutZoneEventArgs.cs | 6 +- .../Scp079CancelledRoomLockdownEventArgs.cs | 6 +- .../Scp079CancellingRoomLockdownEventArgs.cs | 6 +- .../Scp079ChangedCameraEventArgs.cs | 6 +- .../Scp079ChangingCameraEventArgs.cs | 6 +- .../Scp079GainedExperienceEventArgs.cs | 6 +- .../Scp079GainingExperienceEventArgs.cs | 6 +- .../Scp079Events/Scp079LeveledUpEventArgs.cs | 6 +- .../Scp079Events/Scp079LevelingUpEventArgs.cs | 6 +- .../Scp079Events/Scp079LockedDoorEventArgs.cs | 6 +- .../Scp079LockedDownRoomEventArgs.cs | 6 +- .../Scp079LockingDoorEventArgs.cs | 6 +- .../Scp079LockingDownRoomEventArgs.cs | 6 +- .../Scp079RecontainedEventArgs.cs | 6 +- .../Scp079RecontainingEventArgs.cs | 6 +- .../Scp079UnlockedDoorEventArgs.cs | 6 +- .../Scp079UnlockingDoorEventArgs.cs | 6 +- .../Scp079Events/Scp079UsedTeslaEventArgs.cs | 6 +- .../Scp079Events/Scp079UsingTeslaEventArgs.cs | 6 +- .../Scp096AddedTargetEventArgs.cs | 6 +- .../Scp096AddingTargetEventArgs.cs | 6 +- .../Scp096ChangedStateEventArgs.cs | 6 +- .../Scp096ChangingStateEventArgs.cs | 6 +- .../Scp096Events/Scp096ChargedEventArgs.cs | 6 +- .../Scp096Events/Scp096ChargingEventArgs.cs | 6 +- .../Scp096Events/Scp096EnragedEventArgs.cs | 6 +- .../Scp096Events/Scp096EnragingEventArgs.cs | 6 +- .../Scp096Events/Scp096PriedGateEventArgs.cs | 6 +- .../Scp096Events/Scp096PryingGateEventArgs.cs | 6 +- .../Scp096StartCryingEventArgs.cs | 6 +- .../Scp096StartedCryingEventArgs.cs | 6 +- .../Scp096TriedNotToCryEventArgs.cs | 6 +- .../Scp096TryingNotToCryEventArgs.cs | 6 +- .../Scp106ChangedStalkModeEventArgs.cs | 6 +- .../Scp106ChangedSubmersionStatusEventArgs.cs | 6 +- .../Scp106ChangedVigorEventArgs.cs | 6 +- .../Scp106ChangingStalkModeEventArgs.cs | 6 +- ...Scp106ChangingSubmersionStatusEventArgs.cs | 6 +- .../Scp106ChangingVigorEventArgs.cs | 6 +- .../Scp106TeleportedPlayerEvent.cs | 6 +- .../Scp106TeleportingPlayerEvent.cs | 6 +- .../Scp106UsedHunterAtlasEventArgs.cs | 6 +- .../Scp106UsingHunterAtlasEventArgs.cs | 6 +- .../Scp127GainExperienceEventArgs.cs | 34 ++ .../Scp127GainingExperienceEventArgs.cs | 37 ++ .../Scp127Events/Scp127LevelUpEventArgs.cs | 34 ++ .../Scp127LevellingUpEventArgs.cs | 38 ++ .../Scp127Events/Scp127TalkedEventArgs.cs | 42 ++ .../Scp127Events/Scp127TalkingEventArgs.cs | 46 ++ .../Scp173AddedObserverEventArgs.cs | 6 +- .../Scp173AddingObserverEventArgs.cs | 6 +- .../Scp173BreakneckSpeedChangedEventArgs.cs | 6 +- .../Scp173BreakneckSpeedChangingEventArgs.cs | 6 +- .../Scp173CreatedTantrumEventArgs.cs | 6 +- .../Scp173CreatingTantrumEventArgs.cs | 6 +- .../Scp173PlayedSoundEventArgs.cs | 6 +- .../Scp173PlayingSoundEventArgs.cs | 6 +- .../Scp173RemovedObserverEventArgs.cs | 6 +- .../Scp173RemovingObserverEventArgs.cs | 6 +- .../Scp914Events/Scp914ActivatedEventArgs.cs | 6 +- .../Scp914Events/Scp914ActivatingEventArgs.cs | 6 +- .../Scp914KnobChangedEventArgs.cs | 6 +- .../Scp914KnobChangingEventArgs.cs | 6 +- .../Scp914ProcessedInventoryItemEventArgs.cs | 6 +- .../Scp914ProcessedPlayerEventArgs.cs | 6 +- .../Scp914ProcessingInventoryItemEventArgs.cs | 6 +- .../Scp914ProcessingPlayerEventArgs.cs | 6 +- .../Scp939Events/Scp939AttackedEventArgs.cs | 6 +- .../Scp939Events/Scp939AttackingEventArgs.cs | 6 +- .../Scp939CreatedAmnesticCloudEventArgs.cs | 6 +- .../Scp939CreatingAmnesticCloudEventArgs.cs | 6 +- .../Scp939Events/Scp939LungedEventArgs.cs | 6 +- .../Scp939Events/Scp939LungingEventArgs.cs | 6 +- .../CassieQueuedScpTerminationEventArgs.cs | 6 +- .../CassieQueuingScpTerminationEventArgs.cs | 6 +- .../ServerEvents/ExplosionSpawnedEventArgs.cs | 6 +- .../ExplosionSpawningEventArgs.cs | 6 +- .../ProjectileExplodedEventArgs.cs | 6 +- .../ProjectileExplodingEventArgs.cs | 6 +- .../WarheadDetonatedEventArgs.cs | 6 +- .../WarheadDetonatingEventArgs.cs | 6 +- .../WarheadEvents/WarheadStartedEventArgs.cs | 6 +- .../WarheadEvents/WarheadStartingEventArgs.cs | 6 +- .../WarheadEvents/WarheadStoppedEventArgs.cs | 6 +- .../WarheadEvents/WarheadStoppingEventArgs.cs | 6 +- .../Handlers/PlayerEvents.EventHandlers.cs | 15 + .../Handlers/Scp127Events.EventHandlers.cs | 39 ++ .../Features/Wrappers/Facility/Doors/Door.cs | 1 + .../Wrappers/Items/Firearm/FirearmItem.cs | 539 +++++++++++++++++- .../Items/Firearm/ParticleDisruptorItem.cs | 62 -- .../SpecialFirearms/ParticleDisruptorItem.cs | 155 +++++ .../SpecialFirearms/RevolverFirearm.cs | 185 ++++++ .../Firearm/SpecialFirearms/Scp127Firearm.cs | 213 +++++++ .../Firearm/SpecialFirearms/ShotgunFirearm.cs | 138 +++++ LabApi/Features/Wrappers/Items/Item.cs | 7 +- 245 files changed, 2372 insertions(+), 742 deletions(-) create mode 100644 LabApi/Events/Arguments/Interfaces/Items/Firearms/IRevolverItemEvent.cs create mode 100644 LabApi/Events/Arguments/Interfaces/Items/Firearms/IScp127ItemEvent.cs create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerSpinnedRevolverEventArgs.cs create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerSpinningRevolverEventArgs.cs create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerToggledDisruptorFiringModeEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp127Events/Scp127GainExperienceEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp127Events/Scp127GainingExperienceEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp127Events/Scp127LevelUpEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp127Events/Scp127LevellingUpEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp127Events/Scp127TalkedEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp127Events/Scp127TalkingEventArgs.cs create mode 100644 LabApi/Events/Handlers/Scp127Events.EventHandlers.cs delete mode 100644 LabApi/Features/Wrappers/Items/Firearm/ParticleDisruptorItem.cs create mode 100644 LabApi/Features/Wrappers/Items/Firearm/SpecialFirearms/ParticleDisruptorItem.cs create mode 100644 LabApi/Features/Wrappers/Items/Firearm/SpecialFirearms/RevolverFirearm.cs create mode 100644 LabApi/Features/Wrappers/Items/Firearm/SpecialFirearms/Scp127Firearm.cs create mode 100644 LabApi/Features/Wrappers/Items/Firearm/SpecialFirearms/ShotgunFirearm.cs diff --git a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs index cf11844f..8cc52f5b 100644 --- a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs +++ b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs @@ -6,6 +6,7 @@ using LabApi.Events.Arguments.Scp079Events; using LabApi.Events.Arguments.Scp096Events; using LabApi.Events.Arguments.Scp106Events; +using LabApi.Events.Arguments.Scp127Events; using LabApi.Events.Arguments.Scp173Events; using LabApi.Events.Arguments.Scp3114Events; using LabApi.Events.Arguments.Scp914Events; @@ -1609,6 +1610,50 @@ public override void OnScp3114Dance(Scp3114StartedDanceEventArgs ev) Logger.Info($"{nameof(OnScp3114Dance)} triggered by {ev.Player.UserId}"); } + public override void OnPlayerToggledDisruptorFiringMode(PlayerToggledDisruptorFiringModeEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerToggledDisruptorFiringMode)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerSpinningRevolver(PlayerSpinningRevolverEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerSpinningRevolver)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerSpinnedRevolver(PlayerSpinnedRevolverEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerSpinnedRevolver)} triggered by {ev.Player.UserId}"); + } + + public override void OnScp127GainingExperience(Scp127GainingExperienceEventArgs ev) + { + Logger.Info($"{nameof(OnScp127GainingExperience)} triggered by {ev.Scp127Item.CurrentOwner}"); + } + + public override void OnScp127GainExperience(Scp127GainExperienceEventArgs ev) + { + Logger.Info($"{nameof(OnScp127GainExperience)} triggered by {ev.Scp127Item.CurrentOwner}"); + } + + public override void OnScp127LevellingUp(Scp127LevellingUpEventArgs ev) + { + Logger.Info($"{nameof(OnScp127LevellingUp)} triggered by {ev.Scp127Item.CurrentOwner}"); + } + + public override void OnScp127LevelUp(Scp127LevelUpEventArgs ev) + { + Logger.Info($"{nameof(OnScp127LevelUp)} triggered by {ev.Scp127Item.CurrentOwner}"); + } + + public override void OnScp127Talking(Scp127TalkingEventArgs ev) + { + Logger.Info($"{nameof(OnScp127Talking)} triggered by {ev.Scp127Item.CurrentOwner}"); + } + + public override void OnScp127Talked(Scp127TalkedEventArgs ev) + { + Logger.Info($"{nameof(OnScp127Talked)} triggered by {ev.Scp127Item.CurrentOwner}"); + } #region Excluded Events diff --git a/LabApi/Events/Arguments/Interfaces/Items/Firearms/IRevolverItemEvent.cs b/LabApi/Events/Arguments/Interfaces/Items/Firearms/IRevolverItemEvent.cs new file mode 100644 index 00000000..24d0777a --- /dev/null +++ b/LabApi/Events/Arguments/Interfaces/Items/Firearms/IRevolverItemEvent.cs @@ -0,0 +1,17 @@ +using LabApi.Features.Wrappers; + +namespace LabApi.Events.Arguments.Interfaces; + +/// <summary> +/// Represents an event that involves a revolver. +/// </summary> +public interface IRevolverItemEvent : IItemEvent +{ + /// <inheritdoc /> + Item? IItemEvent.Item => Revolver; + + /// <summary> + /// The revolver that is involved in the event. + /// </summary> + public RevolverFirearm? Revolver { get; } +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/Interfaces/Items/Firearms/IScp127ItemEvent.cs b/LabApi/Events/Arguments/Interfaces/Items/Firearms/IScp127ItemEvent.cs new file mode 100644 index 00000000..7a59ec14 --- /dev/null +++ b/LabApi/Events/Arguments/Interfaces/Items/Firearms/IScp127ItemEvent.cs @@ -0,0 +1,19 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; + +namespace LabApi.Events.Arguments.Interfaces; + +/// <summary> +/// Represents an event that involves SCP-127. +/// </summary> +public interface IScp127ItemEvent : IItemEvent +{ + /// <inheritdoc /> + Item? IItemEvent.Item => Scp127Item; + + /// <summary> + /// The SCP-127 item that is involved in the event. + /// </summary> + public Scp127Firearm? Scp127Item { get; } +} + diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerActivatedGeneratorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerActivatedGeneratorEventArgs.cs index bcc59650..9a63b0a8 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerActivatedGeneratorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerActivatedGeneratorEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerActivatedGeneratorEventArgs : EventArgs, IPlayerEvent, IGener /// <summary> /// Initializes a new instance of the <see cref="PlayerActivatedGeneratorEventArgs"/> class. /// </summary> - /// <param name="player">The player who activated the generator.</param> + /// <param name="hub">The player who activated the generator.</param> /// <param name="generator">The generator that the player has activated.</param> - public PlayerActivatedGeneratorEventArgs(ReferenceHub player, Scp079Generator generator) + public PlayerActivatedGeneratorEventArgs(ReferenceHub hub, Scp079Generator generator) { - Player = Player.Get(player); + Player = Player.Get(hub); Generator = Generator.Get(generator); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerActivatingGeneratorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerActivatingGeneratorEventArgs.cs index def56887..691c1ae3 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerActivatingGeneratorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerActivatingGeneratorEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerActivatingGeneratorEventArgs : EventArgs, IPlayerEvent, IGene /// <summary> /// Initializes a new instance of the <see cref="PlayerActivatingGeneratorEventArgs"/> class. /// </summary> - /// <param name="player">The player who is activating the generator.</param> + /// <param name="hub">The player who is activating the generator.</param> /// <param name="generator">The generator that the player is activating.</param> - public PlayerActivatingGeneratorEventArgs(ReferenceHub player, Scp079Generator generator) + public PlayerActivatingGeneratorEventArgs(ReferenceHub hub, Scp079Generator generator) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Generator = Generator.Get(generator); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerAimedWeaponEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerAimedWeaponEventArgs.cs index a737ea84..0a797935 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerAimedWeaponEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerAimedWeaponEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerAimedWeaponEventArgs : EventArgs, IPlayerEvent, IFirearmItemE /// <summary> /// Initializes a new instance of the <see cref="PlayerAimedWeaponEventArgs"/> class. /// </summary> - /// <param name="player">The player who aimed the weapon.</param> + /// <param name="hub">The player who aimed the weapon.</param> /// <param name="weapon">The weapon that the player aimed.</param> /// <param name="aiming">Whether the player was aiming or unaiming their weapon.</param> - public PlayerAimedWeaponEventArgs(ReferenceHub player, Firearm weapon, bool aiming) + public PlayerAimedWeaponEventArgs(ReferenceHub hub, Firearm weapon, bool aiming) { - Player = Player.Get(player); + Player = Player.Get(hub); FirearmItem = FirearmItem.Get(weapon); Aiming = aiming; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerAimingWeaponEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerAimingWeaponEventArgs.cs index 1bbf62cd..13131342 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerAimingWeaponEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerAimingWeaponEventArgs.cs @@ -15,13 +15,13 @@ namespace LabApi.Events.Arguments.PlayerEvents; // /// <summary> // /// Initializes a new instance of the <see cref="PlayerAimingWeaponEventArgs"/> class. // /// </summary> -// /// <param name="player">The player who is aiming the weapon.</param> +// /// <param name="hub">The player who is aiming the weapon.</param> // /// <param name="weapon">The weapon that the player is aiming.</param> // /// <param name="aiming">Whether or not the player is aiming or unaiming their weapon.</param> -// public PlayerAimingWeaponEventArgs(ReferenceHub player, ItemBase weapon, bool aiming) +// public PlayerAimingWeaponEventArgs(ReferenceHub hub, ItemBase weapon, bool aiming) // { // IsAllowed = true; -// Player = Player.Get(player); +// Player = Player.Get(hub); // Weapon = Item.Get(weapon); // Aiming = aiming; // } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerBannedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerBannedEventArgs.cs index 6731568d..e1e46d3f 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerBannedEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerBannedEventArgs.cs @@ -12,14 +12,14 @@ public class PlayerBannedEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerBannedEventArgs"/> class. /// </summary> - /// <param name="player">The player who is getting the ban.</param> + /// <param name="hub">The player who is getting the ban.</param> /// <param name="playerId">The ID of the player who is getting the ban.</param> /// <param name="issuer">The player who issued the ban.</param> /// <param name="reason">The reason of the ban.</param> /// <param name="duration">The duration of the ban.</param> - public PlayerBannedEventArgs(ReferenceHub? player, string playerId, ReferenceHub issuer, string reason, long duration) + public PlayerBannedEventArgs(ReferenceHub? hub, string playerId, ReferenceHub issuer, string reason, long duration) { - Player = Player.Get(player); + Player = Player.Get(hub); PlayerId = playerId; Issuer = Player.Get(issuer); Reason = reason; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerBanningEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerBanningEventArgs.cs index 4358f492..af46873f 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerBanningEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerBanningEventArgs.cs @@ -12,15 +12,15 @@ public class PlayerBanningEventArgs : EventArgs, IPlayerEvent, ICancellableEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerBanningEventArgs"/> class. /// </summary> - /// <param name="player">The player who is getting the ban.</param> + /// <param name="hub">The player who is getting the ban.</param> /// <param name="playerId">The ID of the player who is getting the ban.</param> /// <param name="issuer">The player who issued the ban.</param> /// <param name="reason">The reason of the ban.</param> /// <param name="duration">The duration of the ban.</param> - public PlayerBanningEventArgs(ReferenceHub? player, string playerId, ReferenceHub issuer, string reason, long duration) + public PlayerBanningEventArgs(ReferenceHub? hub, string playerId, ReferenceHub issuer, string reason, long duration) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); PlayerId = playerId; Issuer = Player.Get(issuer); Reason = reason; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerCancelledUsingItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerCancelledUsingItemEventArgs.cs index ec2b16bd..bd5a4c20 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerCancelledUsingItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerCancelledUsingItemEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerCancelledUsingItemEventArgs : EventArgs, IUsableItemEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerCancelledUsingItemEventArgs"/> class. /// </summary> - /// <param name="player">The player who cancelled using the item.</param> + /// <param name="hub">The player who cancelled using the item.</param> /// <param name="item">The item which the player cancelled using.</param> - public PlayerCancelledUsingItemEventArgs(ReferenceHub player, BaseUsableItem item) + public PlayerCancelledUsingItemEventArgs(ReferenceHub hub, BaseUsableItem item) { - Player = Player.Get(player); + Player = Player.Get(hub); UsableItem = UsableItem.Get(item); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerCancellingUsingItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerCancellingUsingItemEventArgs.cs index 60c16c64..f088410c 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerCancellingUsingItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerCancellingUsingItemEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerCancellingUsingItemEventArgs : EventArgs, IUsableItemEvent, I /// <summary> /// Initializes a new instance of the <see cref="PlayerCancellingUsingItemEventArgs"/> class. /// </summary> - /// <param name="player">The player who is cancelling using the item.</param> + /// <param name="hub">The player who is cancelling using the item.</param> /// <param name="item">The item which the player cancels using.</param> - public PlayerCancellingUsingItemEventArgs(ReferenceHub player, BaseUsableItem item) + public PlayerCancellingUsingItemEventArgs(ReferenceHub hub, BaseUsableItem item) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); UsableItem = UsableItem.Get(item); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangedItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedItemEventArgs.cs index 7333606b..2b34bcdf 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerChangedItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedItemEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerChangedItemEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerChangedItemEventArgs"/> class. /// </summary> - /// <param name="player">The player who changed current item.</param> + /// <param name="hub">The player who changed current item.</param> /// <param name="oldItem">The old item which player changed to.</param> /// <param name="newItem">The new item which player changed to.</param> - public PlayerChangedItemEventArgs(ReferenceHub player, ItemBase? oldItem, ItemBase? newItem) + public PlayerChangedItemEventArgs(ReferenceHub hub, ItemBase? oldItem, ItemBase? newItem) { - Player = Player.Get(player); + Player = Player.Get(hub); OldItem = Item.Get(oldItem); NewItem = Item.Get(newItem); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangedNicknameEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedNicknameEventArgs.cs index f3368fe2..adf3fd81 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerChangedNicknameEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedNicknameEventArgs.cs @@ -12,12 +12,12 @@ public class PlayerChangedNicknameEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerChangedNicknameEventArgs"/> class. /// </summary> - /// <param name="player">The player whose nickname has changed.</param> + /// <param name="hub">The player whose nickname has changed.</param> /// <param name="oldNickname">The old nickname of the player.</param> /// <param name="newNickname">The new nickname of the player.</param> - public PlayerChangedNicknameEventArgs(ReferenceHub player, string? oldNickname, string? newNickname) + public PlayerChangedNicknameEventArgs(ReferenceHub hub, string? oldNickname, string? newNickname) { - Player = Player.Get(player); + Player = Player.Get(hub); OldNickname = oldNickname; NewNickname = newNickname; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangedRadioRangeEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedRadioRangeEventArgs.cs index 92984e5b..baafec54 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerChangedRadioRangeEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedRadioRangeEventArgs.cs @@ -14,12 +14,12 @@ public class PlayerChangedRadioRangeEventArgs : EventArgs, IRadioItemEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerChangedRadioRangeEventArgs"/> class. /// </summary> - /// <param name="player">The player who changed radio range.</param> + /// <param name="hub">The player who changed radio range.</param> /// <param name="radio">The radio item.</param> /// <param name="range">The new range level.</param> - public PlayerChangedRadioRangeEventArgs(ReferenceHub player, BaseRadioItem radio, RadioRangeLevel range) + public PlayerChangedRadioRangeEventArgs(ReferenceHub hub, BaseRadioItem radio, RadioRangeLevel range) { - Player = Player.Get(player); + Player = Player.Get(hub); RadioItem = RadioItem.Get(radio); Range = range; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangedRoleEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedRoleEventArgs.cs index fcd19bae..a2fc0810 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerChangedRoleEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedRoleEventArgs.cs @@ -13,14 +13,14 @@ public class PlayerChangedRoleEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerChangedRoleEventArgs"/> class. /// </summary> - /// <param name="player">The player whose role changed.</param> + /// <param name="hub">The player whose role changed.</param> /// <param name="oldRole">The old role type.</param> /// <param name="newRole">The new role object of the player.</param> /// <param name="changeReason">The reason of role changed.</param> /// <param name="spawnFlags">The spawn flags used for this role change.</param> - public PlayerChangedRoleEventArgs(ReferenceHub player, RoleTypeId oldRole, PlayerRoleBase newRole, RoleChangeReason changeReason, RoleSpawnFlags spawnFlags) + public PlayerChangedRoleEventArgs(ReferenceHub hub, RoleTypeId oldRole, PlayerRoleBase newRole, RoleChangeReason changeReason, RoleSpawnFlags spawnFlags) { - Player = Player.Get(player); + Player = Player.Get(hub); OldRole = oldRole; NewRole = newRole; ChangeReason = changeReason; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangedSpectatorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedSpectatorEventArgs.cs index ae76eab5..69a6cf48 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerChangedSpectatorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedSpectatorEventArgs.cs @@ -12,12 +12,12 @@ public class PlayerChangedSpectatorEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerChangedSpectatorEventArgs"/> class. /// </summary> - /// <param name="player">The player who changed spectator.</param> + /// <param name="hub">The player who changed spectator.</param> /// <param name="oldTarget">Old target that was spectated previously.</param> /// <param name="newTarget">New target that was spectating changed to.</param> - public PlayerChangedSpectatorEventArgs(ReferenceHub player, ReferenceHub oldTarget, ReferenceHub newTarget) + public PlayerChangedSpectatorEventArgs(ReferenceHub hub, ReferenceHub oldTarget, ReferenceHub newTarget) { - Player = Player.Get(player); + Player = Player.Get(hub); OldTarget = Player.Get(oldTarget); NewTarget = Player.Get(newTarget); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangingItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingItemEventArgs.cs index cbfe21e8..1f3e719f 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerChangingItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingItemEventArgs.cs @@ -13,13 +13,13 @@ public class PlayerChangingItemEventArgs : EventArgs, IPlayerEvent, ICancellable /// <summary> /// Initializes a new instance of the <see cref="PlayerChangingItemEventArgs"/> class. /// </summary> - /// <param name="player">The player who is changing item.</param> + /// <param name="hub">The player who is changing item.</param> /// <param name="oldItem">The old item.</param> /// <param name="newItem">The new item that is being equipped.</param> - public PlayerChangingItemEventArgs(ReferenceHub player, ItemBase? oldItem, ItemBase? newItem) + public PlayerChangingItemEventArgs(ReferenceHub hub, ItemBase? oldItem, ItemBase? newItem) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); OldItem = Item.Get(oldItem); NewItem = Item.Get(newItem); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangingNicknameEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingNicknameEventArgs.cs index 12a45c24..45d57e81 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerChangingNicknameEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingNicknameEventArgs.cs @@ -12,13 +12,13 @@ public class PlayerChangingNicknameEventArgs : EventArgs, IPlayerEvent, ICancell /// <summary> /// Initializes a new instance of the <see cref="PlayerChangingNicknameEventArgs"/> class. /// </summary> - /// <param name="player">The player whose nickname is changing.</param> + /// <param name="hub">The player whose nickname is changing.</param> /// <param name="oldNickname">The old nickname of the player.</param> /// <param name="newNickname">The new nickname of the player.</param> - public PlayerChangingNicknameEventArgs(ReferenceHub player, string? oldNickname, string? newNickname) + public PlayerChangingNicknameEventArgs(ReferenceHub hub, string? oldNickname, string? newNickname) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); OldNickname = oldNickname; NewNickname = newNickname; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangingRadioRangeEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingRadioRangeEventArgs.cs index 0f79bfc5..387e0ca3 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerChangingRadioRangeEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingRadioRangeEventArgs.cs @@ -14,13 +14,13 @@ public class PlayerChangingRadioRangeEventArgs : EventArgs, IRadioItemEvent, ICa /// <summary> /// Initializes a new instance of the <see cref="PlayerChangingRadioRangeEventArgs"/> class. /// </summary> - /// <param name="player">The player who is changing radio range.</param> + /// <param name="hub">The player who is changing radio range.</param> /// <param name="radio">The radio item.</param> /// <param name="range">The range level that is radio being changed to.</param> - public PlayerChangingRadioRangeEventArgs(ReferenceHub player, BaseRadioItem radio, RadioRangeLevel range) + public PlayerChangingRadioRangeEventArgs(ReferenceHub hub, BaseRadioItem radio, RadioRangeLevel range) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); RadioItem = RadioItem.Get(radio); Range = range; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangingRoleEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingRoleEventArgs.cs index 0ce9e283..59c68293 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerChangingRoleEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingRoleEventArgs.cs @@ -13,15 +13,15 @@ public class PlayerChangingRoleEventArgs : EventArgs, IPlayerEvent, ICancellable /// <summary> /// Initializes a new instance of the <see cref="PlayerChangingRoleEventArgs"/> class. /// </summary> - /// <param name="player">The player whose role is changing.</param> + /// <param name="hub">The player whose role is changing.</param> /// <param name="oldRole">The old role object of the player.</param> /// <param name="newRole">The new role type.</param> /// <param name="changeReason">The reason of role changing.</param> /// <param name="spawnFlags">The spawn flags for this role change.</param> - public PlayerChangingRoleEventArgs(ReferenceHub player, PlayerRoleBase oldRole, RoleTypeId newRole, RoleChangeReason changeReason, RoleSpawnFlags spawnFlags) + public PlayerChangingRoleEventArgs(ReferenceHub hub, PlayerRoleBase oldRole, RoleTypeId newRole, RoleChangeReason changeReason, RoleSpawnFlags spawnFlags) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); OldRole = oldRole; NewRole = newRole; ChangeReason = changeReason; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerClosedGeneratorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerClosedGeneratorEventArgs.cs index bc30549e..ccfa2033 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerClosedGeneratorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerClosedGeneratorEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerClosedGeneratorEventArgs : EventArgs, IPlayerEvent, IGenerato /// <summary> /// Initializes a new instance of the <see cref="PlayerClosedGeneratorEventArgs"/> class. /// </summary> - /// <param name="player">The player who closed the generator.</param> + /// <param name="hub">The player who closed the generator.</param> /// <param name="generator">The generator.</param> - public PlayerClosedGeneratorEventArgs(ReferenceHub player, Scp079Generator generator) + public PlayerClosedGeneratorEventArgs(ReferenceHub hub, Scp079Generator generator) { - Player = Player.Get(player); + Player = Player.Get(hub); Generator = Generator.Get(generator); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerClosingGeneratorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerClosingGeneratorEventArgs.cs index 4acb3bde..8ae7bbc2 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerClosingGeneratorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerClosingGeneratorEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerClosingGeneratorEventArgs : EventArgs, IPlayerEvent, IGenerat /// <summary> /// Initializes a new instance of the <see cref="PlayerClosingGeneratorEventArgs"/> class. /// </summary> - /// <param name="player">The player who is closing the generator.</param> + /// <param name="hub">The player who is closing the generator.</param> /// <param name="generator">The generator.</param> - public PlayerClosingGeneratorEventArgs(ReferenceHub player, Scp079Generator generator) + public PlayerClosingGeneratorEventArgs(ReferenceHub hub, Scp079Generator generator) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Generator = Generator.Get(generator); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerCuffedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerCuffedEventArgs.cs index 1b7c6076..7abc3d10 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerCuffedEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerCuffedEventArgs.cs @@ -12,11 +12,11 @@ public class PlayerCuffedEventArgs : EventArgs, IPlayerEvent, ITargetEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerCuffedEventArgs"/> class. /// </summary> - /// <param name="player">The player who detained another one.</param> + /// <param name="hub">The player who detained another one.</param> /// <param name="target">The player who was detained.</param> - public PlayerCuffedEventArgs(ReferenceHub player, ReferenceHub target) + public PlayerCuffedEventArgs(ReferenceHub hub, ReferenceHub target) { - Player = Player.Get(player); + Player = Player.Get(hub); Target = Player.Get(target); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerCuffingEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerCuffingEventArgs.cs index 4aafad95..16b0e9c6 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerCuffingEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerCuffingEventArgs.cs @@ -12,12 +12,12 @@ public class PlayerCuffingEventArgs : EventArgs, IPlayerEvent, ITargetEvent, ICa /// <summary> /// Initializes a new instance of the <see cref="PlayerCuffingEventArgs"/> class. /// </summary> - /// <param name="player">The player who is detaining another one.</param> + /// <param name="hub">The player who is detaining another one.</param> /// <param name="target">The player who is being detained.</param> - public PlayerCuffingEventArgs(ReferenceHub player, ReferenceHub target) + public PlayerCuffingEventArgs(ReferenceHub hub, ReferenceHub target) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Target = Player.Get(target); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagedShootingTargetEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagedShootingTargetEventArgs.cs index cf0010f7..a2a6c88d 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagedShootingTargetEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagedShootingTargetEventArgs.cs @@ -14,12 +14,12 @@ public class PlayerDamagedShootingTargetEventArgs : EventArgs, IPlayerEvent, ISh /// <summary> /// Initializes a new instance of the <see cref="PlayerDamagedShootingTargetEventArgs"/> class. /// </summary> - /// <param name="player">The player who damaged the shooting target.</param> + /// <param name="hub">The player who damaged the shooting target.</param> /// <param name="target">The shooting target.</param> /// <param name="damageHandler">The damage handler.</param> - public PlayerDamagedShootingTargetEventArgs(ReferenceHub player, ShootingTarget target, DamageHandlerBase damageHandler) + public PlayerDamagedShootingTargetEventArgs(ReferenceHub hub, ShootingTarget target, DamageHandlerBase damageHandler) { - Player = Player.Get(player); + Player = Player.Get(hub); ShootingTarget = ShootingTargetToy.Get(target); DamageHandler = damageHandler; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagedWindowEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagedWindowEventArgs.cs index 2a67d768..b13308cb 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagedWindowEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagedWindowEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerDamagedWindowEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerDamagedWindowEventArgs"/> class. /// </summary> - /// <param name="player">The player who damaged the window.</param> + /// <param name="hub">The player who damaged the window.</param> /// <param name="window">The window.</param> /// <param name="damageHandler">The damage handler.</param> - public PlayerDamagedWindowEventArgs(ReferenceHub player, BreakableWindow window, DamageHandlerBase damageHandler) + public PlayerDamagedWindowEventArgs(ReferenceHub hub, BreakableWindow window, DamageHandlerBase damageHandler) { - Player = Player.Get(player); + Player = Player.Get(hub); Window = window; DamageHandler = damageHandler; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingShootingTargetEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingShootingTargetEventArgs.cs index 1a25a160..602e94e6 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingShootingTargetEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingShootingTargetEventArgs.cs @@ -14,13 +14,13 @@ public class PlayerDamagingShootingTargetEventArgs : EventArgs, IPlayerEvent, IS /// <summary> /// Initializes a new instance of the <see cref="PlayerDamagingShootingTargetEventArgs"/> class. /// </summary> - /// <param name="player">The player who is damaging the shooting target.</param> + /// <param name="hub">The player who is damaging the shooting target.</param> /// <param name="target">The shooting target.</param> /// <param name="damageHandler">The damage handler.</param> - public PlayerDamagingShootingTargetEventArgs(ReferenceHub player, ShootingTarget target, DamageHandlerBase damageHandler) + public PlayerDamagingShootingTargetEventArgs(ReferenceHub hub, ShootingTarget target, DamageHandlerBase damageHandler) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); ShootingTarget = ShootingTargetToy.Get(target); DamageHandler = damageHandler; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingWindowEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingWindowEventArgs.cs index 3758606e..86fd4a70 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingWindowEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingWindowEventArgs.cs @@ -13,13 +13,13 @@ public class PlayerDamagingWindowEventArgs : EventArgs, ICancellableEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerDamagingWindowEventArgs"/> class. /// </summary> - /// <param name="player">The player who is damaging the window.</param> + /// <param name="hub">The player who is damaging the window.</param> /// <param name="window">The window.</param> /// <param name="damageHandler">The damage handler.</param> - public PlayerDamagingWindowEventArgs(ReferenceHub player, BreakableWindow window, DamageHandlerBase damageHandler) + public PlayerDamagingWindowEventArgs(ReferenceHub hub, BreakableWindow window, DamageHandlerBase damageHandler) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Window = window; DamageHandler = damageHandler; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDeactivatedGeneratorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDeactivatedGeneratorEventArgs.cs index 8fd753a4..dcfdee83 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDeactivatedGeneratorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDeactivatedGeneratorEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerDeactivatedGeneratorEventArgs : EventArgs, IPlayerEvent, IGen /// <summary> /// Initializes a new instance of the <see cref="PlayerDeactivatedGeneratorEventArgs"/> class. /// </summary> - /// <param name="player">The player who deactivated the generator.</param> + /// <param name="hub">The player who deactivated the generator.</param> /// <param name="generator">The generator.</param> - public PlayerDeactivatedGeneratorEventArgs(ReferenceHub player, Scp079Generator generator) + public PlayerDeactivatedGeneratorEventArgs(ReferenceHub hub, Scp079Generator generator) { - Player = Player.Get(player); + Player = Player.Get(hub); Generator = Generator.Get(generator); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDeactivatingGeneratorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDeactivatingGeneratorEventArgs.cs index 57bbf5b6..978da2c8 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDeactivatingGeneratorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDeactivatingGeneratorEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerDeactivatingGeneratorEventArgs : EventArgs, IGeneratorEvent, /// <summary> /// Initializes a new instance of the <see cref="PlayerDeactivatingGeneratorEventArgs"/> class. /// </summary> - /// <param name="player">The player who is deactivating the generator.</param> + /// <param name="hub">The player who is deactivating the generator.</param> /// <param name="generator">The generator.</param> - public PlayerDeactivatingGeneratorEventArgs(ReferenceHub player, Scp079Generator generator) + public PlayerDeactivatingGeneratorEventArgs(ReferenceHub hub, Scp079Generator generator) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Generator = Generator.Get(generator); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDeathEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDeathEventArgs.cs index d58359eb..45c73f40 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDeathEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDeathEventArgs.cs @@ -15,17 +15,17 @@ public class PlayerDeathEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerDeathEventArgs"/> class. /// </summary> - /// <param name="player">The player who died.</param> + /// <param name="hub">The player who died.</param> /// <param name="attacker">The player who caused the death.</param> /// <param name="damageHandler">The damage that caused the death.</param> /// <param name="oldRole">The previous role of the player before death.</param> /// <param name="oldPosition">The previous world position of the player before death.</param> /// <param name="oldVelocity">The previous velocity of the player before death.</param> /// <param name="oldCameraRotation">The previous world rotation of the players camera before death.</param> - public PlayerDeathEventArgs(ReferenceHub player, ReferenceHub? attacker, DamageHandlerBase damageHandler, + public PlayerDeathEventArgs(ReferenceHub hub, ReferenceHub? attacker, DamageHandlerBase damageHandler, RoleTypeId oldRole, Vector3 oldPosition, Vector3 oldVelocity, Quaternion oldCameraRotation) { - Player = Player.Get(player); + Player = Player.Get(hub); Attacker = Player.Get(attacker); DamageHandler = damageHandler; OldRole = oldRole; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppedAmmoEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppedAmmoEventArgs.cs index 1e9b60fd..c5a47655 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppedAmmoEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppedAmmoEventArgs.cs @@ -13,13 +13,13 @@ public class PlayerDroppedAmmoEventArgs : EventArgs, IPlayerEvent, IAmmoPickupEv /// <summary> /// Initializes a new instance of the <see cref="PlayerDroppedAmmoEventArgs"/> class. /// </summary> - /// <param name="player">The player who is dropping the ammo.</param> + /// <param name="hub">The player who is dropping the ammo.</param> /// <param name="type">The type of ammo being dropped.</param> /// <param name="amount">The amount of ammo being dropped.</param> /// <param name="pickup">The ammo pickup.</param> - public PlayerDroppedAmmoEventArgs(ReferenceHub player, ItemType type, int amount, BaseAmmoPickup pickup) + public PlayerDroppedAmmoEventArgs(ReferenceHub hub, ItemType type, int amount, BaseAmmoPickup pickup) { - Player = Player.Get(player); + Player = Player.Get(hub); Type = type; Amount = amount; AmmoPickup = AmmoPickup.Get(pickup); diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppedItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppedItemEventArgs.cs index 9dd3ff9e..5895c0bd 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppedItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppedItemEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerDroppedItemEventArgs : EventArgs, IPlayerEvent, IPickupEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerDroppedItemEventArgs"/> class. /// </summary> - /// <param name="player">The player who dropped the item.</param> + /// <param name="hub">The player who dropped the item.</param> /// <param name="pickup">The item pickup.</param> /// <param name="isThrowing">Whether the item will be thrown.</param> - public PlayerDroppedItemEventArgs(ReferenceHub player, ItemPickupBase pickup, bool isThrowing) + public PlayerDroppedItemEventArgs(ReferenceHub hub, ItemPickupBase pickup, bool isThrowing) { - Player = Player.Get(player); + Player = Player.Get(hub); Pickup = Pickup.Get(pickup); Throw = isThrowing; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingAmmoEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingAmmoEventArgs.cs index 73bc7a84..dda5faba 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingAmmoEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingAmmoEventArgs.cs @@ -12,13 +12,13 @@ public class PlayerDroppingAmmoEventArgs : EventArgs, ICancellableEvent, IPlayer /// <summary> /// Initializes a new instance of the <see cref="PlayerDroppingAmmoEventArgs"/> class. /// </summary> - /// <param name="player">The player who is dropping the ammo.</param> + /// <param name="hub">The player who is dropping the ammo.</param> /// <param name="type">The type of ammo being dropped.</param> /// <param name="amount">The amount of ammo being dropped.</param> - public PlayerDroppingAmmoEventArgs(ReferenceHub player, ItemType type, int amount) + public PlayerDroppingAmmoEventArgs(ReferenceHub hub, ItemType type, int amount) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Type = type; Amount = amount; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs index dc5f3e4d..74cca24a 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs @@ -13,13 +13,13 @@ public class PlayerDroppingItemEventArgs : EventArgs, ICancellableEvent, IItemEv /// <summary> /// Initializes a new instance of the <see cref="PlayerDroppingItemEventArgs"/> class. /// </summary> - /// <param name="player">The player who is dropping the item.</param> + /// <param name="hub">The player who is dropping the item.</param> /// <param name="item">The item being dropped.</param> /// <param name="isThrowing">Whether the item will be thrown.</param> - public PlayerDroppingItemEventArgs(ReferenceHub player, ItemBase item, bool isThrowing) + public PlayerDroppingItemEventArgs(ReferenceHub hub, ItemBase item, bool isThrowing) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Item = Item.Get(item); Throw = isThrowing; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDryFiredWeaponEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDryFiredWeaponEventArgs.cs index 67475bde..54ec7101 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDryFiredWeaponEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDryFiredWeaponEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerDryFiredWeaponEventArgs : EventArgs, IPlayerEvent, IFirearmIt /// <summary> /// Initializes a new instance of the <see cref="PlayerDryFiredWeaponEventArgs"/> class. /// </summary> - /// <param name="player">The player who dry fired.</param> + /// <param name="hub">The player who dry fired.</param> /// <param name="weapon">The weapon item.</param> - public PlayerDryFiredWeaponEventArgs(ReferenceHub player, Firearm weapon) + public PlayerDryFiredWeaponEventArgs(ReferenceHub hub, Firearm weapon) { - Player = Player.Get(player); + Player = Player.Get(hub); FirearmItem = FirearmItem.Get(weapon); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDryFiringWeaponEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDryFiringWeaponEventArgs.cs index 61d62ffe..3bced66d 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDryFiringWeaponEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDryFiringWeaponEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerDryFiringWeaponEventArgs : EventArgs, IFirearmItemEvent, ICan /// <summary> /// Initializes a new instance of the <see cref="PlayerDryFiringWeaponEventArgs"/> class. /// </summary> - /// <param name="player">The player who is dry firing.</param> + /// <param name="hub">The player who is dry firing.</param> /// <param name="weapon">The weapon item.</param> - public PlayerDryFiringWeaponEventArgs(ReferenceHub player, Firearm weapon) + public PlayerDryFiringWeaponEventArgs(ReferenceHub hub, Firearm weapon) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); FirearmItem = FirearmItem.Get(weapon); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDyingEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDyingEventArgs.cs index 70dafb23..6fb84cb2 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDyingEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDyingEventArgs.cs @@ -13,13 +13,13 @@ public class PlayerDyingEventArgs : EventArgs, ICancellableEvent, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerDyingEventArgs"/> class. /// </summary> - /// <param name="player">The player who is dying.</param> + /// <param name="hub">The player who is dying.</param> /// <param name="attacker">The player who attacked.</param> /// <param name="damageHandler">The damage handler who is causing death.</param> - public PlayerDyingEventArgs(ReferenceHub player, ReferenceHub? attacker, DamageHandlerBase damageHandler) + public PlayerDyingEventArgs(ReferenceHub hub, ReferenceHub? attacker, DamageHandlerBase damageHandler) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Attacker = Player.Get(attacker); DamageHandler = damageHandler; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerEffectUpdatedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerEffectUpdatedEventArgs.cs index add1ddbb..086c0bb7 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerEffectUpdatedEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerEffectUpdatedEventArgs.cs @@ -13,13 +13,13 @@ public class PlayerEffectUpdatedEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerReceivingLoadoutEventArgs"/> class. /// </summary> - /// <param name="player">The player whose effect has been updated.</param> + /// <param name="hub">The player whose effect has been updated.</param> /// <param name="effect">The effect that is being updated.</param> /// <param name="intensity">Intensity of the effect.</param> /// <param name="duration">Duration of the effect in seconds.</param> - public PlayerEffectUpdatedEventArgs(ReferenceHub player, StatusEffectBase effect, byte intensity, float duration) + public PlayerEffectUpdatedEventArgs(ReferenceHub hub, StatusEffectBase effect, byte intensity, float duration) { - Player = Player.Get(player); + Player = Player.Get(hub); Effect = effect; Intensity = intensity; Duration = duration; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerEffectUpdatingEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerEffectUpdatingEventArgs.cs index 54c84d53..9c539679 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerEffectUpdatingEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerEffectUpdatingEventArgs.cs @@ -13,14 +13,14 @@ public class PlayerEffectUpdatingEventArgs : EventArgs, ICancellableEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerEffectUpdatingEventArgs"/> class. /// </summary> - /// <param name="player">The player whose effect is being updated.</param> + /// <param name="hub">The player whose effect is being updated.</param> /// <param name="effect">The effect that is being updated.</param> /// <param name="intensity">Intensity of the effect.</param> /// <param name="duration">Duration of the effect in seconds.</param> - public PlayerEffectUpdatingEventArgs(ReferenceHub player, StatusEffectBase effect, byte intensity, float duration) + public PlayerEffectUpdatingEventArgs(ReferenceHub hub, StatusEffectBase effect, byte intensity, float duration) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Effect = effect; Intensity = intensity; Duration = duration; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerEnteredHazardEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerEnteredHazardEventArgs.cs index 922a47f3..2eabbba9 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerEnteredHazardEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerEnteredHazardEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerEnteredHazardEventArgs : EventArgs, IPlayerEvent, IHazardEven /// <summary> /// Initializes a new instance of the <see cref="PlayerEnteringPocketDimensionEventArgs"/> class. /// </summary> - /// <param name="player">The player who entered the hazard.</param> + /// <param name="hub">The player who entered the hazard.</param> /// <param name="hazard">The hazard.</param> - public PlayerEnteredHazardEventArgs(ReferenceHub player, EnvironmentalHazard hazard) + public PlayerEnteredHazardEventArgs(ReferenceHub hub, EnvironmentalHazard hazard) { - Player = Player.Get(player); + Player = Player.Get(hub); Hazard = Hazard.Get(hazard); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerEnteredPocketDimensionEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerEnteredPocketDimensionEventArgs.cs index 33047082..206803e7 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerEnteredPocketDimensionEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerEnteredPocketDimensionEventArgs.cs @@ -12,10 +12,10 @@ public class PlayerEnteredPocketDimensionEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerEnteredPocketDimensionEventArgs"/> class. /// </summary> - /// <param name="player">The player who entered the pocket dimension.</param> - public PlayerEnteredPocketDimensionEventArgs(ReferenceHub player) + /// <param name="hub">The player who entered the pocket dimension.</param> + public PlayerEnteredPocketDimensionEventArgs(ReferenceHub hub) { - Player = Player.Get(player); + Player = Player.Get(hub); } /// <summary> diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerEnteringHazardEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerEnteringHazardEventArgs.cs index 65c547a2..ce34ae0e 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerEnteringHazardEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerEnteringHazardEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerEnteringHazardEventArgs : EventArgs, IPlayerEvent, IHazardEve /// <summary> /// Initializes a new instance of the <see cref="PlayerEnteringPocketDimensionEventArgs"/> class. /// </summary> - /// <param name="player">The player who entered the hazard.</param> + /// <param name="hub">The player who entered the hazard.</param> /// <param name="hazard">The hazard.</param> - public PlayerEnteringHazardEventArgs(ReferenceHub player, EnvironmentalHazard hazard) + public PlayerEnteringHazardEventArgs(ReferenceHub hub, EnvironmentalHazard hazard) { - Player = Player.Get(player); + Player = Player.Get(hub); Hazard = Hazard.Get(hazard); IsAllowed = true; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerEnteringPocketDimensionEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerEnteringPocketDimensionEventArgs.cs index a7f4c1b0..23878f1f 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerEnteringPocketDimensionEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerEnteringPocketDimensionEventArgs.cs @@ -12,11 +12,11 @@ public class PlayerEnteringPocketDimensionEventArgs : EventArgs, IPlayerEvent, I /// <summary> /// Initializes a new instance of the <see cref="PlayerEnteringPocketDimensionEventArgs"/> class. /// </summary> - /// <param name="player">The player who is entering the pocket dimension.</param> - public PlayerEnteringPocketDimensionEventArgs(ReferenceHub player) + /// <param name="hub">The player who is entering the pocket dimension.</param> + public PlayerEnteringPocketDimensionEventArgs(ReferenceHub hub) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); } /// <summary> diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerEscapedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerEscapedEventArgs.cs index bb7c7e70..25859366 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerEscapedEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerEscapedEventArgs.cs @@ -15,14 +15,14 @@ public class PlayerEscapedEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerEscapedEventArgs"/> class. /// </summary> - /// <param name="player">The player who escaped.</param> + /// <param name="hub">The player who escaped.</param> /// <param name="newRole">The new role.</param> /// <param name="escapeScenarioType">The scenario of the escape.</param> /// <param name="oldRole">The old role of the player.</param> /// <param name="escapeZone">The bounds of the escape zone that was triggered.</param> - public PlayerEscapedEventArgs(ReferenceHub player, RoleTypeId oldRole, RoleTypeId newRole, EscapeScenarioType escapeScenarioType, Bounds escapeZone) + public PlayerEscapedEventArgs(ReferenceHub hub, RoleTypeId oldRole, RoleTypeId newRole, EscapeScenarioType escapeScenarioType, Bounds escapeZone) { - Player = Player.Get(player); + Player = Player.Get(hub); OldRole = oldRole; NewRole = newRole; EscapeScenarioType = escapeScenarioType; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerEscapingEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerEscapingEventArgs.cs index 7d35fc47..fbf2abad 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerEscapingEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerEscapingEventArgs.cs @@ -15,15 +15,15 @@ public class PlayerEscapingEventArgs : EventArgs, IPlayerEvent, ICancellableEven /// <summary> /// Initializes a new instance of the <see cref="PlayerEscapingEventArgs"/> class. /// </summary> - /// <param name="player">The player who is escaping.</param> + /// <param name="hub">The player who is escaping.</param> /// <param name="newRole">The new role that is set after escape.</param> /// <param name="escapeScenario">The scenario of the escape.</param> /// <param name="oldRole">The old role of the player.</param> /// <param name="escapeZone">The bounds of the escape zone that was triggered.</param> - public PlayerEscapingEventArgs(ReferenceHub player, RoleTypeId oldRole, RoleTypeId newRole, EscapeScenarioType escapeScenario, Bounds escapeZone) + public PlayerEscapingEventArgs(ReferenceHub hub, RoleTypeId oldRole, RoleTypeId newRole, EscapeScenarioType escapeScenario, Bounds escapeZone) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); OldRole = oldRole; NewRole = newRole; EscapeScenario = escapeScenario; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerFlippedCoinEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerFlippedCoinEventArgs.cs index f2defb2d..3277f32d 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerFlippedCoinEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerFlippedCoinEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerFlippedCoinEventArgs : EventArgs, IPlayerEvent, ICoinItemEven /// <summary> /// Initializes a new instance of the <see cref="PlayerFlippingCoinEventArgs"/> class. /// </summary> - /// <param name="player">The player who flipped the coin.</param> + /// <param name="hub">The player who flipped the coin.</param> /// <param name="coin">The coin that was flipped.</param> /// <param name="isTails">Whenever the coin flip is tails.</param> - public PlayerFlippedCoinEventArgs(ReferenceHub player, Coin coin, bool isTails) + public PlayerFlippedCoinEventArgs(ReferenceHub hub, Coin coin, bool isTails) { - Player = Player.Get(player); + Player = Player.Get(hub); CoinItem = CoinItem.Get(coin); IsTails = isTails; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerFlippingCoinEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerFlippingCoinEventArgs.cs index 84c1d6ad..3df5bfd8 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerFlippingCoinEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerFlippingCoinEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerFlippingCoinEventArgs : EventArgs, ICancellableEvent, ICoinIt /// <summary> /// Initializes a new instance of the <see cref="PlayerFlippingCoinEventArgs"/> class. /// </summary> - /// <param name="player">The player who is flipping the coin.</param> + /// <param name="hub">The player who is flipping the coin.</param> /// <param name="coin">The coin that is being flipped.</param> /// <param name="isTails">Whenever the coin flip is tails.</param> - public PlayerFlippingCoinEventArgs(ReferenceHub player, Coin coin, bool isTails) + public PlayerFlippingCoinEventArgs(ReferenceHub hub, Coin coin, bool isTails) { - Player = Player.Get(player); + Player = Player.Get(hub); CoinItem = CoinItem.Get(coin); IsTails = isTails; IsAllowed = true; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerGroupChangedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerGroupChangedEventArgs.cs index 7619d60f..3c311bb9 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerGroupChangedEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerGroupChangedEventArgs.cs @@ -12,11 +12,11 @@ public class PlayerGroupChangedEventArgs : EventArgs, IPlayerEvent, IGroupEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerGroupChangedEventArgs"/> class. /// </summary> - /// <param name="player">The player whose group changed.</param> + /// <param name="hub">The player whose group changed.</param> /// <param name="group">The new group.</param> - public PlayerGroupChangedEventArgs(ReferenceHub player, UserGroup group) + public PlayerGroupChangedEventArgs(ReferenceHub hub, UserGroup group) { - Player = Player.Get(player); + Player = Player.Get(hub); Group = group; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerGroupChangingEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerGroupChangingEventArgs.cs index 5e8ab249..707d7719 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerGroupChangingEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerGroupChangingEventArgs.cs @@ -12,11 +12,11 @@ public class PlayerGroupChangingEventArgs : EventArgs, IPlayerEvent, IGroupEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerGroupChangingEventArgs"/> class. /// </summary> - /// <param name="player">The player whose group is changing.</param> + /// <param name="hub">The player whose group is changing.</param> /// <param name="group">The new group.</param> - public PlayerGroupChangingEventArgs(ReferenceHub player, UserGroup? group) + public PlayerGroupChangingEventArgs(ReferenceHub hub, UserGroup? group) { - Player = Player.Get(player); + Player = Player.Get(hub); Group = group; IsAllowed = true; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedDoorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedDoorEventArgs.cs index 7a18c032..b63c2119 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedDoorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedDoorEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerInteractedDoorEventArgs : EventArgs, IPlayerEvent, IDoorEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerInteractedDoorEventArgs"/> class. /// </summary> - /// <param name="player">The player who is interacting with the door.</param> + /// <param name="hub">The player who is interacting with the door.</param> /// <param name="door">The door that is being interacted with.</param> /// <param name="canOpen">Whenever player can open the door.</param> - public PlayerInteractedDoorEventArgs(ReferenceHub player, DoorVariant door, bool canOpen) + public PlayerInteractedDoorEventArgs(ReferenceHub hub, DoorVariant door, bool canOpen) { - Player = Player.Get(player); + Player = Player.Get(hub); Door = Door.Get(door); CanOpen = canOpen; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedElevatorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedElevatorEventArgs.cs index 3f672798..06795b30 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedElevatorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedElevatorEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerInteractedElevatorEventArgs : EventArgs, IPlayerEvent, IEleva /// <summary> /// Initializes a new instance of the <see cref="PlayerInteractedElevatorEventArgs"/> class. /// </summary> - /// <param name="player">The player who interacted with elevator panel.</param> + /// <param name="hub">The player who interacted with elevator panel.</param> /// <param name="elevator">The elevator chamber.</param> /// <param name="panel">The elevator panel that was interaction done with.</param> - public PlayerInteractedElevatorEventArgs(ReferenceHub player, ElevatorChamber elevator, ElevatorPanel panel) + public PlayerInteractedElevatorEventArgs(ReferenceHub hub, ElevatorChamber elevator, ElevatorPanel panel) { - Player = Player.Get(player); + Player = Player.Get(hub); Elevator = Elevator.Get(elevator); Panel = panel; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedGeneratorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedGeneratorEventArgs.cs index 7b85020f..dad41929 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedGeneratorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedGeneratorEventArgs.cs @@ -14,12 +14,12 @@ public class PlayerInteractedGeneratorEventArgs : EventArgs, IPlayerEvent, IGene /// <summary> /// Initializes a new instance of the <see cref="PlayerInteractedGeneratorEventArgs"/> class. /// </summary> - /// <param name="player">The player who interacted with the generator.</param> + /// <param name="hub">The player who interacted with the generator.</param> /// <param name="generator">The generator object.</param> /// <param name="colliderId">The collider ID.</param> - public PlayerInteractedGeneratorEventArgs(ReferenceHub player, Scp079Generator generator, GeneratorColliderId colliderId) + public PlayerInteractedGeneratorEventArgs(ReferenceHub hub, Scp079Generator generator, GeneratorColliderId colliderId) { - Player = Player.Get(player); + Player = Player.Get(hub); Generator = Generator.Get(generator); ColliderId = colliderId; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedLockerEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedLockerEventArgs.cs index 13348fea..50f941fa 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedLockerEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedLockerEventArgs.cs @@ -14,13 +14,13 @@ public class PlayerInteractedLockerEventArgs : EventArgs, IPlayerEvent, ILockerE /// <summary> /// Initializes a new instance of the <see cref="PlayerInteractedLockerEventArgs"/> class. /// </summary> - /// <param name="player">The player who is interacted with the locker.</param> + /// <param name="hub">The player who is interacted with the locker.</param> /// <param name="locker">The locker that was interacted with.</param> /// <param name="chamber">The chamber that was targeted.</param> /// <param name="canOpen">Whether the player was allowed to open it.</param> - public PlayerInteractedLockerEventArgs(ReferenceHub player, BaseLocker locker, BaseLockerChamber chamber, bool canOpen) + public PlayerInteractedLockerEventArgs(ReferenceHub hub, BaseLocker locker, BaseLockerChamber chamber, bool canOpen) { - Player = Player.Get(player); + Player = Player.Get(hub); Locker = Locker.Get(locker); Chamber = LockerChamber.Get(chamber); CanOpen = canOpen; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedScp330EventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedScp330EventArgs.cs index a357d661..6f545632 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedScp330EventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedScp330EventArgs.cs @@ -14,14 +14,14 @@ public class PlayerInteractedScp330EventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerInteractedScp330EventArgs"/> class. /// </summary> - /// <param name="player">The player who interacted with SCP-330.</param> + /// <param name="hub">The player who interacted with SCP-330.</param> /// <param name="uses">The amount of uses that target player did.</param> /// <param name="playSound">Whenever pickup sound should have been.</param> /// <param name="allowPunishment">Whenever the <see cref="SeveredHands"/> effect was applied.</param> /// <param name="type">Type of the candy which was given to the player.</param> - public PlayerInteractedScp330EventArgs(ReferenceHub player, int uses, bool playSound, bool allowPunishment, CandyKindID type) + public PlayerInteractedScp330EventArgs(ReferenceHub hub, int uses, bool playSound, bool allowPunishment, CandyKindID type) { - Player = Player.Get(player); + Player = Player.Get(hub); Uses = uses; PlaySound = playSound; AllowPunishment = allowPunishment; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedShootingTargetEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedShootingTargetEventArgs.cs index 7ff0e14c..03f02c3f 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedShootingTargetEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedShootingTargetEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerInteractedShootingTargetEventArgs : EventArgs, IPlayerEvent, /// <summary> /// Initializes a new instance of the <see cref="PlayerInteractedShootingTargetEventArgs"/> class. /// </summary> - /// <param name="player">The player who interacted with the target.</param> + /// <param name="hub">The player who interacted with the target.</param> /// <param name="target">The shooting target.</param> - public PlayerInteractedShootingTargetEventArgs(ReferenceHub player, ShootingTarget target) + public PlayerInteractedShootingTargetEventArgs(ReferenceHub hub, ShootingTarget target) { - Player = Player.Get(player); + Player = Player.Get(hub); ShootingTarget = ShootingTargetToy.Get(target); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedToyEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedToyEventArgs.cs index 255d4a64..4212ff5c 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedToyEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedToyEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerInteractedToyEventArgs : EventArgs, IPlayerEvent, IInteractab /// <summary> /// Initializes a new instance of the <see cref="PlayerInteractedToyEventArgs"/> class. /// </summary> - /// <param name="player">The player who interacted with the toy.</param> + /// <param name="hub">The player who interacted with the toy.</param> /// <param name="toy">The toy instance that was interacted with.</param> - public PlayerInteractedToyEventArgs(ReferenceHub player, InvisibleInteractableToy toy) + public PlayerInteractedToyEventArgs(ReferenceHub hub, InvisibleInteractableToy toy) { - Player = Player.Get(player); + Player = Player.Get(hub); Interactable = InteractableToy.Get(toy); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingDoorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingDoorEventArgs.cs index 012e450f..f4293733 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingDoorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingDoorEventArgs.cs @@ -13,13 +13,13 @@ public class PlayerInteractingDoorEventArgs : EventArgs, IDoorEvent, ICancellabl /// <summary> /// Initializes a new instance of the <see cref="PlayerInteractingDoorEventArgs"/> class. /// </summary> - /// <param name="player">The player who is interacting with the door.</param> + /// <param name="hub">The player who is interacting with the door.</param> /// <param name="door">The door that is being interacted with.</param> /// <param name="canOpen">Whenever player can open the door.</param> - public PlayerInteractingDoorEventArgs(ReferenceHub player, DoorVariant door, bool canOpen) + public PlayerInteractingDoorEventArgs(ReferenceHub hub, DoorVariant door, bool canOpen) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Door = Door.Get(door); CanOpen = canOpen; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingElevatorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingElevatorEventArgs.cs index 8197b0a6..ee3feabe 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingElevatorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingElevatorEventArgs.cs @@ -13,13 +13,13 @@ public class PlayerInteractingElevatorEventArgs : EventArgs, IPlayerEvent, IElev /// <summary> /// Initializes a new instance of the <see cref="PlayerInteractingElevatorEventArgs"/> class. /// </summary> - /// <param name="player">The player who is interacting with the elevator.</param> + /// <param name="hub">The player who is interacting with the elevator.</param> /// <param name="elevator">The elevator.</param> /// <param name="panel">The elevator panel.</param> - public PlayerInteractingElevatorEventArgs(ReferenceHub player, ElevatorChamber elevator, ElevatorPanel panel) + public PlayerInteractingElevatorEventArgs(ReferenceHub hub, ElevatorChamber elevator, ElevatorPanel panel) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Elevator = Elevator.Get(elevator); Panel = panel; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingGeneratorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingGeneratorEventArgs.cs index 72d0821b..406d7911 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingGeneratorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingGeneratorEventArgs.cs @@ -14,13 +14,13 @@ public class PlayerInteractingGeneratorEventArgs : EventArgs, IPlayerEvent, IGen /// <summary> /// Initializes a new instance of the <see cref="PlayerInteractingGeneratorEventArgs"/> class. /// </summary> - /// <param name="player">The player who is interacting with the generator.</param> + /// <param name="hub">The player who is interacting with the generator.</param> /// <param name="generator">The generator object.</param> /// <param name="colliderId">The collider ID.</param> - public PlayerInteractingGeneratorEventArgs(ReferenceHub player, Scp079Generator generator, GeneratorColliderId colliderId) + public PlayerInteractingGeneratorEventArgs(ReferenceHub hub, Scp079Generator generator, GeneratorColliderId colliderId) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Generator = Generator.Get(generator); ColliderId = colliderId; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingLockerEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingLockerEventArgs.cs index 3538eb32..7db994d4 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingLockerEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingLockerEventArgs.cs @@ -14,14 +14,14 @@ public class PlayerInteractingLockerEventArgs : EventArgs, IPlayerEvent, ILocker /// <summary> /// Initializes a new instance of the <see cref="PlayerInteractingLockerEventArgs"/> class. /// </summary> - /// <param name="player">The player who is interacting with the locker.</param> + /// <param name="hub">The player who is interacting with the locker.</param> /// <param name="locker">The locker that is being interacted with.</param> /// <param name="chamber">The chamber that is being targeted.</param> /// <param name="canOpen">Whether the player is allowed to open it.</param> - public PlayerInteractingLockerEventArgs(ReferenceHub player, BaseLocker locker, BaseLockerChamber chamber, bool canOpen) + public PlayerInteractingLockerEventArgs(ReferenceHub hub, BaseLocker locker, BaseLockerChamber chamber, bool canOpen) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Locker = Locker.Get(locker); Chamber = LockerChamber.Get(chamber); CanOpen = canOpen; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingScp330EventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingScp330EventArgs.cs index f3f4c54f..d1aca621 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingScp330EventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingScp330EventArgs.cs @@ -14,15 +14,15 @@ public class PlayerInteractingScp330EventArgs : EventArgs, IPlayerEvent, ICancel /// <summary> /// Initializes a new instance of the <see cref="PlayerInteractingScp330EventArgs"/> class. /// </summary> - /// <param name="player">The player who is interacting with SCP-330.</param> + /// <param name="hub">The player who is interacting with SCP-330.</param> /// <param name="uses">The amount of uses that target player did.</param> /// <param name="playSound">Whenever the sound should be played of pickup up candy.</param> /// <param name="allowPunishment">Whenever the <see cref="SeveredHands"/> effect should be applied.</param> /// <param name="type">Type of the candy which will be given to the player.</param> - public PlayerInteractingScp330EventArgs(ReferenceHub player, int uses, bool playSound, bool allowPunishment, CandyKindID type) + public PlayerInteractingScp330EventArgs(ReferenceHub hub, int uses, bool playSound, bool allowPunishment, CandyKindID type) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Uses = uses; PlaySound = playSound; AllowPunishment = allowPunishment; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingShootingTargetEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingShootingTargetEventArgs.cs index df6805a6..f27d42a5 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingShootingTargetEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingShootingTargetEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerInteractingShootingTargetEventArgs : EventArgs, IPlayerEvent, /// <summary> /// Initializes a new instance of the <see cref="PlayerInteractingShootingTargetEventArgs"/> class. /// </summary> - /// <param name="player">The player who is interacting with the target.</param> + /// <param name="hub">The player who is interacting with the target.</param> /// <param name="target">The shooting target.</param> - public PlayerInteractingShootingTargetEventArgs(ReferenceHub player, ShootingTarget target) + public PlayerInteractingShootingTargetEventArgs(ReferenceHub hub, ShootingTarget target) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); ShootingTarget = ShootingTargetToy.Get(target); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerKickedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerKickedEventArgs.cs index e0b3cc9e..731659f2 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerKickedEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerKickedEventArgs.cs @@ -12,12 +12,12 @@ public class PlayerKickedEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerKickedEventArgs"/> class. /// </summary> - /// <param name="player">The player who was kicked.</param> + /// <param name="hub">The player who was kicked.</param> /// <param name="issuer">The player who issued the kick.</param> /// <param name="reason">The reason for which is player being kicked.</param> - public PlayerKickedEventArgs(ReferenceHub player, ReferenceHub issuer, string reason) + public PlayerKickedEventArgs(ReferenceHub hub, ReferenceHub issuer, string reason) { - Player = Player.Get(player); + Player = Player.Get(hub); Issuer = Player.Get(issuer); Reason = reason; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerKickingEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerKickingEventArgs.cs index f117cc37..aa841320 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerKickingEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerKickingEventArgs.cs @@ -12,13 +12,13 @@ public class PlayerKickingEventArgs : EventArgs, IPlayerEvent, ICancellableEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerKickingEventArgs"/> class. /// </summary> - /// <param name="player">The player who is being kicked.</param> + /// <param name="hub">The player who is being kicked.</param> /// <param name="issuer">The player who is issuing the kick.</param> /// <param name="reason">The reason for which is player being kicked.</param> - public PlayerKickingEventArgs(ReferenceHub player, ReferenceHub issuer, string reason) + public PlayerKickingEventArgs(ReferenceHub hub, ReferenceHub issuer, string reason) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Issuer = Player.Get(issuer); Reason = reason; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerLeavingHazardEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerLeavingHazardEventArgs.cs index 01e06192..1edd1f61 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerLeavingHazardEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerLeavingHazardEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerLeavingHazardEventArgs : EventArgs, IPlayerEvent, IHazardEven /// <summary> /// Initializes a new instance of the <see cref="PlayerLeavingHazardEventArgs"/> class. /// </summary> - /// <param name="player">The player who is leaving.</param> + /// <param name="hub">The player who is leaving.</param> /// <param name="hazard">The hazard that the player is leaving.</param> - public PlayerLeavingHazardEventArgs(ReferenceHub player, EnvironmentalHazard hazard) + public PlayerLeavingHazardEventArgs(ReferenceHub hub, EnvironmentalHazard hazard) { - Player = Player.Get(player); + Player = Player.Get(hub); Hazard = Hazard.Get(hazard); IsAllowed = true; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerLeavingPocketDimensionEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerLeavingPocketDimensionEventArgs.cs index e480979c..f78985e6 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerLeavingPocketDimensionEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerLeavingPocketDimensionEventArgs.cs @@ -12,13 +12,13 @@ public class PlayerLeavingPocketDimensionEventArgs : EventArgs, IPlayerEvent, IC /// <summary> /// Initializes a new instance of the <see cref="PlayerLeavingPocketDimensionEventArgs"/> class. /// </summary> - /// <param name="player">The player who is trying to leave from pocket dimension.</param> + /// <param name="hub">The player who is trying to leave from pocket dimension.</param> /// <param name="teleport">The teleport the player collided with.</param> /// <param name="isSuccessful">Whether it is gonna be success.</param> - public PlayerLeavingPocketDimensionEventArgs(ReferenceHub player, PocketDimensionTeleport teleport, bool isSuccessful) + public PlayerLeavingPocketDimensionEventArgs(ReferenceHub hub, PocketDimensionTeleport teleport, bool isSuccessful) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Teleport = PocketTeleport.Get(teleport); IsSuccessful = isSuccessful; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerLeftEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerLeftEventArgs.cs index fd4ace02..a7538446 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerLeftEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerLeftEventArgs.cs @@ -12,10 +12,10 @@ public class PlayerLeftEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerLeftEventArgs"/> class. /// </summary> - /// <param name="player">The player who left.</param> - public PlayerLeftEventArgs(ReferenceHub player) + /// <param name="hub">The player who left.</param> + public PlayerLeftEventArgs(ReferenceHub hub) { - Player = Player.Get(player); + Player = Player.Get(hub); } /// <summary> diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerLeftHazardEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerLeftHazardEventArgs.cs index 7efcc852..2f70c2ed 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerLeftHazardEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerLeftHazardEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerLeftHazardEventArgs : EventArgs, IPlayerEvent, IHazardEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerLeftHazardEventArgs"/> class. /// </summary> - /// <param name="player">The player who left the hazard.</param> + /// <param name="hub">The player who left the hazard.</param> /// <param name="hazard">The hazard that the player left.</param> - public PlayerLeftHazardEventArgs(ReferenceHub player, EnvironmentalHazard hazard) + public PlayerLeftHazardEventArgs(ReferenceHub hub, EnvironmentalHazard hazard) { - Player = Player.Get(player); + Player = Player.Get(hub); Hazard = Hazard.Get(hazard); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerLeftPocketDimensionEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerLeftPocketDimensionEventArgs.cs index 5eac423d..667d4650 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerLeftPocketDimensionEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerLeftPocketDimensionEventArgs.cs @@ -12,12 +12,12 @@ public class PlayerLeftPocketDimensionEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerLeftPocketDimensionEventArgs"/> class. /// </summary> - /// <param name="player">The player who tried to left pocket dimension.</param> + /// <param name="hub">The player who tried to left pocket dimension.</param> /// <param name="teleport">The teleport the player collided with.</param> /// <param name="isSuccessful">Whether the escape was successful.</param> - public PlayerLeftPocketDimensionEventArgs(ReferenceHub player, PocketDimensionTeleport teleport, bool isSuccessful) + public PlayerLeftPocketDimensionEventArgs(ReferenceHub hub, PocketDimensionTeleport teleport, bool isSuccessful) { - Player = Player.Get(player); + Player = Player.Get(hub); Teleport = PocketTeleport.Get(teleport); IsSuccessful = isSuccessful; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerMutedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerMutedEventArgs.cs index 9dffcbd3..1e777544 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerMutedEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerMutedEventArgs.cs @@ -12,12 +12,12 @@ public class PlayerMutedEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerMutedEventArgs"/> class. /// </summary> - /// <param name="player">The player who was muted.</param> + /// <param name="hub">The player who was muted.</param> /// <param name="issuer">The player who issued the mute.</param> /// <param name="isIntercom">Whenever mute was applied to intercom.</param> - public PlayerMutedEventArgs(ReferenceHub player, ReferenceHub issuer, bool isIntercom) + public PlayerMutedEventArgs(ReferenceHub hub, ReferenceHub issuer, bool isIntercom) { - Player = Player.Get(player); + Player = Player.Get(hub); Issuer = Player.Get(issuer); IsIntercom = isIntercom; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerMutingEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerMutingEventArgs.cs index 77c9e5d0..af506b62 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerMutingEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerMutingEventArgs.cs @@ -12,13 +12,13 @@ public class PlayerMutingEventArgs : EventArgs, IPlayerEvent, ICancellableEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerMutingEventArgs"/> class. /// </summary> - /// <param name="player">The player who is being muted.</param> + /// <param name="hub">The player who is being muted.</param> /// <param name="issuer">The player who is issuing the mute.</param> /// <param name="isIntercom">Whenever mute is being applied to intercom.</param> - public PlayerMutingEventArgs(ReferenceHub player, ReferenceHub issuer, bool isIntercom) + public PlayerMutingEventArgs(ReferenceHub hub, ReferenceHub issuer, bool isIntercom) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Issuer = Player.Get(issuer); IsIntercom = isIntercom; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerOpenedGeneratorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerOpenedGeneratorEventArgs.cs index ddde7e0b..9a5982a9 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerOpenedGeneratorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerOpenedGeneratorEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerOpenedGeneratorEventArgs : EventArgs, IPlayerEvent, IGenerato /// <summary> /// Initializes a new instance of the <see cref="PlayerOpenedGeneratorEventArgs"/> class. /// </summary> - /// <param name="player">The player who opened the generator.</param> + /// <param name="hub">The player who opened the generator.</param> /// <param name="generator">The generator that was opened.</param> - public PlayerOpenedGeneratorEventArgs(ReferenceHub player, Scp079Generator generator) + public PlayerOpenedGeneratorEventArgs(ReferenceHub hub, Scp079Generator generator) { - Player = Player.Get(player); + Player = Player.Get(hub); Generator = Generator.Get(generator); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerOpeningGeneratorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerOpeningGeneratorEventArgs.cs index b7722cef..2e036678 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerOpeningGeneratorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerOpeningGeneratorEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerOpeningGeneratorEventArgs : EventArgs, IPlayerEvent, IGenerat /// <summary> /// Initializes a new instance of the <see cref="PlayerOpeningGeneratorEventArgs"/> class. /// </summary> - /// <param name="player">The player who is opening the generator.</param> + /// <param name="hub">The player who is opening the generator.</param> /// <param name="generator">The generator.</param> - public PlayerOpeningGeneratorEventArgs(ReferenceHub player, Scp079Generator generator) + public PlayerOpeningGeneratorEventArgs(ReferenceHub hub, Scp079Generator generator) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Generator = Generator.Get(generator); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpAmmoEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpAmmoEventArgs.cs index 125aeb02..4b818777 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpAmmoEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpAmmoEventArgs.cs @@ -13,13 +13,13 @@ public class PlayerPickedUpAmmoEventArgs : EventArgs, IPlayerEvent, IAmmoPickupE /// <summary> /// Initializes a new instance of the <see cref="PlayerPickedUpAmmoEventArgs"/> class. /// </summary> - /// <param name="player">The player that picked up the ammo.</param> + /// <param name="hub">The player that picked up the ammo.</param> /// <param name="ammoType">Type of the ammo.</param> /// <param name="ammoAmount">The amount that is was picked up.</param> /// <param name="pickup">The pickup object.</param> - public PlayerPickedUpAmmoEventArgs(ReferenceHub player, ItemType ammoType, ushort ammoAmount, BaseAmmoPickup pickup) + public PlayerPickedUpAmmoEventArgs(ReferenceHub hub, ItemType ammoType, ushort ammoAmount, BaseAmmoPickup pickup) { - Player = Player.Get(player); + Player = Player.Get(hub); AmmoType = ammoType; AmmoAmount = ammoAmount; AmmoPickup = AmmoPickup.Get(pickup); diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpArmorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpArmorEventArgs.cs index ddfdd6e3..7ca160b6 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpArmorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpArmorEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerPickedUpArmorEventArgs : EventArgs, IPlayerEvent, IBodyArmorI /// <summary> /// Initializes a new instance of the <see cref="PlayerPickedUpArmorEventArgs"/> class. /// </summary> - /// <param name="player">The player who picked up armor.</param> + /// <param name="hub">The player who picked up armor.</param> /// <param name="armor">The armor that was picked up.</param> - public PlayerPickedUpArmorEventArgs(ReferenceHub player, BodyArmor? armor) + public PlayerPickedUpArmorEventArgs(ReferenceHub hub, BodyArmor? armor) { - Player = Player.Get(player); + Player = Player.Get(hub); BodyArmorItem = BodyArmorItem.Get(armor); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpItemEventArgs.cs index f5c7e37f..618d429e 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpItemEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerPickedUpItemEventArgs : EventArgs, IPlayerEvent, IItemEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerPickedUpItemEventArgs"/> class. /// </summary> - /// <param name="player">The player who picked up the item.</param> + /// <param name="hub">The player who picked up the item.</param> /// <param name="item">The item that was picked up.</param> - public PlayerPickedUpItemEventArgs(ReferenceHub player, ItemBase item) + public PlayerPickedUpItemEventArgs(ReferenceHub hub, ItemBase item) { - Player = Player.Get(player); + Player = Player.Get(hub); Item = Item.Get(item); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpScp330EventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpScp330EventArgs.cs index e82caa6d..5ab9ac54 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpScp330EventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpScp330EventArgs.cs @@ -14,12 +14,12 @@ public class PlayerPickedUpScp330EventArgs : EventArgs, IPlayerEvent, ICandyItem /// <summary> /// Initializes a new instance of the <see cref="PlayerPickedUpScp330EventArgs"/> class. /// </summary> - /// <param name="player">The player who picked up SCP-330.</param> + /// <param name="hub">The player who picked up SCP-330.</param> /// <param name="pickup">The pickup item.</param> /// <param name="item">SCP-330 bag item of the player.</param> - public PlayerPickedUpScp330EventArgs(ReferenceHub player, BaseScp330Pickup pickup, BaseScp330Bag item) + public PlayerPickedUpScp330EventArgs(ReferenceHub hub, BaseScp330Pickup pickup, BaseScp330Bag item) { - Player = Player.Get(player); + Player = Player.Get(hub); CandyPickup = Scp330Pickup.Get(pickup); CandyItem = Scp330Item.Get(item); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPickingUpAmmoEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPickingUpAmmoEventArgs.cs index 5117fa08..a4c6f4d6 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPickingUpAmmoEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPickingUpAmmoEventArgs.cs @@ -13,14 +13,14 @@ public class PlayerPickingUpAmmoEventArgs : EventArgs, IPlayerEvent, IAmmoPickup /// <summary> /// Initializes a new instance of the <see cref="PlayerPickingUpAmmoEventArgs"/> class. /// </summary> - /// <param name="player">The player who is pickup the ammo pickup.</param> + /// <param name="hub">The player who is pickup the ammo pickup.</param> /// <param name="ammoType">Type of the ammo.</param> /// <param name="ammoAmount">Amount of ammo that is being picked up.</param> /// <param name="pickup">Ammo pickup.</param> - public PlayerPickingUpAmmoEventArgs(ReferenceHub player, ItemType ammoType, ushort ammoAmount, BaseAmmoPickup pickup) + public PlayerPickingUpAmmoEventArgs(ReferenceHub hub, ItemType ammoType, ushort ammoAmount, BaseAmmoPickup pickup) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); AmmoType = ammoType; AmmoAmount = ammoAmount; AmmoPickup = AmmoPickup.Get(pickup); diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPickingUpArmorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPickingUpArmorEventArgs.cs index b3e39e8a..d3627f14 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPickingUpArmorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPickingUpArmorEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerPickingUpArmorEventArgs : EventArgs, IPlayerEvent, IBodyArmor /// <summary> /// Initializes a new instance of the <see cref="PlayerPickingUpArmorEventArgs"/> class. /// </summary> - /// <param name="player">The player who picked up the armor.</param> + /// <param name="hub">The player who picked up the armor.</param> /// <param name="pickup">The armor pickup.</param> - public PlayerPickingUpArmorEventArgs(ReferenceHub player, BaseBodyArmorPickup pickup) + public PlayerPickingUpArmorEventArgs(ReferenceHub hub, BaseBodyArmorPickup pickup) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); BodyArmorPickup = BodyArmorPickup.Get(pickup); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPickingUpItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPickingUpItemEventArgs.cs index 4b358e8b..ca21e90d 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPickingUpItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPickingUpItemEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerPickingUpItemEventArgs : EventArgs, IPlayerEvent, IPickupEven /// <summary> /// Initializes a new instance of the <see cref="PlayerPickingUpItemEventArgs"/> class. /// </summary> - /// <param name="player">The player who picked up the item.</param> + /// <param name="hub">The player who picked up the item.</param> /// <param name="pickup">The item pickup.</param> - public PlayerPickingUpItemEventArgs(ReferenceHub player, ItemPickupBase pickup) + public PlayerPickingUpItemEventArgs(ReferenceHub hub, ItemPickupBase pickup) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Pickup = Pickup.Get(pickup); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPickingUpScp330EventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPickingUpScp330EventArgs.cs index 871c1048..002743de 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPickingUpScp330EventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPickingUpScp330EventArgs.cs @@ -13,12 +13,12 @@ public class PlayerPickingUpScp330EventArgs : EventArgs, IPlayerEvent, ICandyPic /// <summary> /// Initializes a new instance of the <see cref="PlayerPickingUpScp330EventArgs"/> class. /// </summary> - /// <param name="player">The player who is picking up SCP-330.</param> + /// <param name="hub">The player who is picking up SCP-330.</param> /// <param name="pickup">The SCP-330 pickup.</param> - public PlayerPickingUpScp330EventArgs(ReferenceHub player, BaseScp330Pickup pickup) + public PlayerPickingUpScp330EventArgs(ReferenceHub hub, BaseScp330Pickup pickup) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); CandyPickup = Scp330Pickup.Get(pickup); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBloodEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBloodEventArgs.cs index e4385b58..4d76ffa7 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBloodEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBloodEventArgs.cs @@ -13,13 +13,13 @@ public class PlayerPlacedBloodEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerPlacedBloodEventArgs"/> class. /// </summary> - /// <param name="player">The player whose blood it is.</param> + /// <param name="hub">The player whose blood it is.</param> /// <param name="attacker">The player that attacked.</param> /// <param name="hitPosition">Position at which blood has been spawned.</param> /// <param name="startRaycast">Position where the blood decal raycast will start for it to be properly attached to surface.</param> - public PlayerPlacedBloodEventArgs(ReferenceHub player, ReferenceHub attacker, Vector3 hitPosition, Vector3 startRaycast) + public PlayerPlacedBloodEventArgs(ReferenceHub hub, ReferenceHub attacker, Vector3 hitPosition, Vector3 startRaycast) { - Player = Player.Get(player); + Player = Player.Get(hub); Attacker = Player.Get(attacker); HitPosition = hitPosition; RaycastStart = startRaycast; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBulletHole.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBulletHole.cs index 0c9bab18..910ac3a7 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBulletHole.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBulletHole.cs @@ -13,13 +13,13 @@ public class PlayerPlacedBulletHoleEventArgs : EventArgs /// <summary> /// Initializes a new instance of the <see cref="PlayerPlacedBulletHoleEventArgs"/> class. /// </summary> - /// <param name="player">The player who caused this bullet hole.</param> + /// <param name="hub">The player who caused this bullet hole.</param> /// <param name="type">Decal type which has spawned.</param> /// <param name="hitPosition">Position at which bullet hole has spawned.</param> /// <param name="startRaycast">Position where the bullet hole raycast has started for it to be properly attached to surface.</param> - public PlayerPlacedBulletHoleEventArgs(ReferenceHub player, DecalPoolType type, Vector3 hitPosition, Vector3 startRaycast) + public PlayerPlacedBulletHoleEventArgs(ReferenceHub hub, DecalPoolType type, Vector3 hitPosition, Vector3 startRaycast) { - Player = Player.Get(player); + Player = Player.Get(hub); DecalType = type; HitPosition = hitPosition; RaycastStart = startRaycast; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacingBloodEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacingBloodEventArgs.cs index cf28fff4..a34c4451 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacingBloodEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacingBloodEventArgs.cs @@ -13,14 +13,14 @@ public class PlayerPlacingBloodEventArgs : EventArgs, IPlayerEvent, ICancellable /// <summary> /// Initializes a new instance of the <see cref="PlayerPlacingBloodEventArgs"/> class. /// </summary> - /// <param name="player">The player whose blood it is.</param> + /// <param name="hub">The player whose blood it is.</param> /// <param name="attacker">The player that attacked.</param> /// <param name="hitPosition">Position at which is blood being placed.</param> /// <param name="startRaycast">Position where the blood decal raycast will start for it to be properly attached to surface.</param> - public PlayerPlacingBloodEventArgs(ReferenceHub player, ReferenceHub attacker, Vector3 hitPosition, Vector3 startRaycast) + public PlayerPlacingBloodEventArgs(ReferenceHub hub, ReferenceHub attacker, Vector3 hitPosition, Vector3 startRaycast) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Attacker = Player.Get(attacker); HitPosition = hitPosition; RaycastStart = startRaycast; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacingBulletHoleEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacingBulletHoleEventArgs.cs index ca82271a..a9929378 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacingBulletHoleEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacingBulletHoleEventArgs.cs @@ -14,14 +14,14 @@ public class PlayerPlacingBulletHoleEventArgs : EventArgs, IPlayerEvent, ICancel /// <summary> /// Initializes a new instance of the <see cref="PlayerPlacingBulletHoleEventArgs"/> class. /// </summary> - /// <param name="player">The player who caused it.</param> + /// <param name="hub">The player who caused it.</param> /// <param name="type">Decal type to be spawned.</param> /// <param name="hitPosition">Position at which is bullet hole being placed.</param> /// <param name="startRaycast">Position where the bullet hole raycast will start for it to be properly attached to surface.</param> - public PlayerPlacingBulletHoleEventArgs(ReferenceHub player, DecalPoolType type, Vector3 hitPosition, Vector3 startRaycast) + public PlayerPlacingBulletHoleEventArgs(ReferenceHub hub, DecalPoolType type, Vector3 hitPosition, Vector3 startRaycast) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); DecalType = type; HitPosition = hitPosition; RaycastStart = startRaycast; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerReceivedLoadoutEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerReceivedLoadoutEventArgs.cs index fd2d86c7..44fe9d79 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerReceivedLoadoutEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerReceivedLoadoutEventArgs.cs @@ -13,13 +13,13 @@ public class PlayerReceivedLoadoutEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerReceivedLoadoutEventArgs"/> class. /// </summary> - /// <param name="player">The player instance.</param> + /// <param name="hub">The player instance.</param> /// <param name="items">The items which player received.</param> /// <param name="ammo">The ammo which player received.</param> /// <param name="inventoryReset">If players inventory did reset.</param> - public PlayerReceivedLoadoutEventArgs(ReferenceHub player, List<ItemType> items, Dictionary<ItemType, ushort> ammo, bool inventoryReset) + public PlayerReceivedLoadoutEventArgs(ReferenceHub hub, List<ItemType> items, Dictionary<ItemType, ushort> ammo, bool inventoryReset) { - Player = Player.Get(player); + Player = Player.Get(hub); Items = items; Ammo = ammo; InventoryReset = inventoryReset; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerReceivingLoadoutEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerReceivingLoadoutEventArgs.cs index 9e71d4bb..48565c63 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerReceivingLoadoutEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerReceivingLoadoutEventArgs.cs @@ -13,14 +13,14 @@ public class PlayerReceivingLoadoutEventArgs : EventArgs, IPlayerEvent, ICancell /// <summary> /// Initializes a new instance of the <see cref="PlayerReceivingLoadoutEventArgs"/> class. /// </summary> - /// <param name="player">The player instance.</param> + /// <param name="hub">The player instance.</param> /// <param name="items">The items which player received.</param> /// <param name="ammo">The ammo which player received.</param> /// <param name="inventoryReset">If players inventory will be cleared.</param> - public PlayerReceivingLoadoutEventArgs(ReferenceHub player, List<ItemType> items, Dictionary<ItemType, ushort> ammo, bool inventoryReset) + public PlayerReceivingLoadoutEventArgs(ReferenceHub hub, List<ItemType> items, Dictionary<ItemType, ushort> ammo, bool inventoryReset) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Items = items; Ammo = ammo; InventoryReset = inventoryReset; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerReloadedWeaponEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerReloadedWeaponEventArgs.cs index 8e050093..3cbfe389 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerReloadedWeaponEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerReloadedWeaponEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerReloadedWeaponEventArgs : EventArgs, IPlayerEvent, IFirearmIt /// <summary> /// Initializes a new instance of the <see cref="PlayerReloadedWeaponEventArgs"/> class. /// </summary> - /// <param name="player">The player who reloaded the weapon.</param> + /// <param name="hub">The player who reloaded the weapon.</param> /// <param name="weapon">The weapon that was reloaded.</param> - public PlayerReloadedWeaponEventArgs(ReferenceHub player, Firearm weapon) + public PlayerReloadedWeaponEventArgs(ReferenceHub hub, Firearm weapon) { - Player = Player.Get(player); + Player = Player.Get(hub); FirearmItem = FirearmItem.Get(weapon); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerReloadingWeaponEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerReloadingWeaponEventArgs.cs index f98f9781..061cdb11 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerReloadingWeaponEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerReloadingWeaponEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerReloadingWeaponEventArgs : EventArgs, IFirearmItemEvent, ICan /// <summary> /// Initializes a new instance of the <see cref="PlayerReloadingWeaponEventArgs"/> class. /// </summary> - /// <param name="player">The player who is reloading the weapon.</param> + /// <param name="hub">The player who is reloading the weapon.</param> /// <param name="weapon">The weapon that is being reloaded.</param> - public PlayerReloadingWeaponEventArgs(ReferenceHub player, Firearm weapon) + public PlayerReloadingWeaponEventArgs(ReferenceHub hub, Firearm weapon) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); FirearmItem = FirearmItem.Get(weapon); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerReportedCheaterEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerReportedCheaterEventArgs.cs index bab934f8..1fe80768 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerReportedCheaterEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerReportedCheaterEventArgs.cs @@ -12,12 +12,12 @@ public class PlayerReportedCheaterEventArgs : EventArgs, IPlayerEvent, ITargetEv /// <summary> /// Initializes a new instance of the <see cref="PlayerReportedCheaterEventArgs"/> class. /// </summary> - /// <param name="player">The player who sent the report.</param> + /// <param name="hub">The player who sent the report.</param> /// <param name="target">The reported player.</param> /// <param name="reason">The reason why is the player being reported.</param> - public PlayerReportedCheaterEventArgs(ReferenceHub player, ReferenceHub target, string reason) + public PlayerReportedCheaterEventArgs(ReferenceHub hub, ReferenceHub target, string reason) { - Player = Player.Get(player); + Player = Player.Get(hub); Target = Player.Get(target); Reason = reason; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerReportedPlayerEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerReportedPlayerEventArgs.cs index c2fa1535..bdf4c742 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerReportedPlayerEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerReportedPlayerEventArgs.cs @@ -12,12 +12,12 @@ public class PlayerReportedPlayerEventArgs : EventArgs, IPlayerEvent, ITargetEve /// <summary> /// Initializes a new instance of the <see cref="PlayerReportedPlayerEventArgs"/> class. /// </summary> - /// <param name="player">The player who sent reported.</param> + /// <param name="hub">The player who sent reported.</param> /// <param name="target">The player who was reported.</param> /// <param name="reason">The reason why was the player reported.</param> - public PlayerReportedPlayerEventArgs(ReferenceHub player, ReferenceHub target, string reason) + public PlayerReportedPlayerEventArgs(ReferenceHub hub, ReferenceHub target, string reason) { - Player = Player.Get(player); + Player = Player.Get(hub); Target = Player.Get(target); Reason = reason; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerReportingCheaterEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerReportingCheaterEventArgs.cs index a0415daa..8f0b4ac7 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerReportingCheaterEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerReportingCheaterEventArgs.cs @@ -12,13 +12,13 @@ public class PlayerReportingCheaterEventArgs : EventArgs, IPlayerEvent, ITargetE /// <summary> /// Initializes a new instance of the <see cref="PlayerReportingCheaterEventArgs"/> class. /// </summary> - /// <param name="player">The player who is reporting.</param> + /// <param name="hub">The player who is reporting.</param> /// <param name="target">The reported player.</param> /// <param name="reason">The reason why is the player being reported.</param> - public PlayerReportingCheaterEventArgs(ReferenceHub player, ReferenceHub target, string reason) + public PlayerReportingCheaterEventArgs(ReferenceHub hub, ReferenceHub target, string reason) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Target = Player.Get(target); Reason = reason; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerReportingPlayerEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerReportingPlayerEventArgs.cs index 11771f3e..aa5d5732 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerReportingPlayerEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerReportingPlayerEventArgs.cs @@ -12,13 +12,13 @@ public class PlayerReportingPlayerEventArgs : EventArgs, IPlayerEvent, ITargetEv /// <summary> /// Initializes a new instance of the <see cref="PlayerReportingPlayerEventArgs"/> class. /// </summary> - /// <param name="player">The player who is reporting.</param> + /// <param name="hub">The player who is reporting.</param> /// <param name="target">The player who is being reported.</param> /// <param name="reason">The reason why was player reported.</param> - public PlayerReportingPlayerEventArgs(ReferenceHub player, ReferenceHub target, string reason) + public PlayerReportingPlayerEventArgs(ReferenceHub hub, ReferenceHub target, string reason) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Target = Player.Get(target); Reason = reason; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchToyAbortedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchToyAbortedEventArgs.cs index f411f07b..314ce292 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchToyAbortedEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchToyAbortedEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerSearchToyAbortedEventArgs : EventArgs, IPlayerEvent, IInterac /// <summary> /// Initializes a new instance for the <see cref="PlayerSearchToyAbortedEventArgs"/> class. /// </summary> - /// <param name="player">The player that canceled the search on the toy.</param> + /// <param name="hub">The player that canceled the search on the toy.</param> /// <param name="toy">The toy that was being searched.</param> - public PlayerSearchToyAbortedEventArgs(ReferenceHub player, InvisibleInteractableToy toy) + public PlayerSearchToyAbortedEventArgs(ReferenceHub hub, InvisibleInteractableToy toy) { - Player = Player.Get(player); + Player = Player.Get(hub); Interactable = InteractableToy.Get(toy); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchedAmmoEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchedAmmoEventArgs.cs index 128adc66..430c46d3 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchedAmmoEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchedAmmoEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerSearchedAmmoEventArgs : EventArgs, IPlayerEvent, IAmmoPickupE /// <summary> /// Initializes a new instance of the <see cref="PlayerSearchedAmmoEventArgs"/> class. /// </summary> - /// <param name="player">The player who searched for ammo pickup.</param> + /// <param name="hub">The player who searched for ammo pickup.</param> /// <param name="pickup">The ammo pickup.</param> - public PlayerSearchedAmmoEventArgs(ReferenceHub player, BaseAmmoPickup pickup) + public PlayerSearchedAmmoEventArgs(ReferenceHub hub, BaseAmmoPickup pickup) { - Player = Player.Get(player); + Player = Player.Get(hub); AmmoPickup = AmmoPickup.Get(pickup); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchedArmorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchedArmorEventArgs.cs index 994d9456..9a2fc349 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchedArmorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchedArmorEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerSearchedArmorEventArgs : EventArgs, IPlayerEvent, IBodyArmorP /// <summary> /// Initializes a new instance of the <see cref="PlayerSearchedArmorEventArgs"/> class. /// </summary> - /// <param name="player">The player who searched for armor pickup.</param> + /// <param name="hub">The player who searched for armor pickup.</param> /// <param name="pickup">The armor pickup.</param> - public PlayerSearchedArmorEventArgs(ReferenceHub player, BaseBodyArmorPickup pickup) + public PlayerSearchedArmorEventArgs(ReferenceHub hub, BaseBodyArmorPickup pickup) { - Player = Player.Get(player); + Player = Player.Get(hub); BodyArmorPickup = BodyArmorPickup.Get(pickup); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchedPickupEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchedPickupEventArgs.cs index 38755804..a2533a9f 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchedPickupEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchedPickupEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerSearchedPickupEventArgs : EventArgs, IPlayerEvent, IPickupEve /// <summary> /// Initializes a new instance of the <see cref="PlayerSearchedPickupEventArgs"/> class. /// </summary> - /// <param name="player">The player who searched for pickup.</param> + /// <param name="hub">The player who searched for pickup.</param> /// <param name="pickup">The item pickup.</param> - public PlayerSearchedPickupEventArgs(ReferenceHub player, ItemPickupBase pickup) + public PlayerSearchedPickupEventArgs(ReferenceHub hub, ItemPickupBase pickup) { - Player = Player.Get(player); + Player = Player.Get(hub); Pickup = Pickup.Get(pickup); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchedToyEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchedToyEventArgs.cs index 50ed12f0..38af42cc 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchedToyEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchedToyEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerSearchedToyEventArgs : EventArgs, IPlayerEvent, IInteractable /// <summary> /// Initializes a new instance of the <see cref="PlayerSearchedToyEventArgs"/> class. /// </summary> - /// <param name="player">The player who searched the toy.</param> + /// <param name="hub">The player who searched the toy.</param> /// <param name="toy">The toy that was searched.</param> - public PlayerSearchedToyEventArgs(ReferenceHub player, InvisibleInteractableToy toy) + public PlayerSearchedToyEventArgs(ReferenceHub hub, InvisibleInteractableToy toy) { - Player = Player.Get(player); + Player = Player.Get(hub); Interactable = InteractableToy.Get(toy); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingAmmoEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingAmmoEventArgs.cs index 665d3a28..ecc5545e 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingAmmoEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingAmmoEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerSearchingAmmoEventArgs : EventArgs, IPlayerEvent, IAmmoPickup /// <summary> /// Initializes a new instance of the <see cref="PlayerSearchingAmmoEventArgs"/> class. /// </summary> - /// <param name="player">The player searching for ammo pickup.</param> + /// <param name="hub">The player searching for ammo pickup.</param> /// <param name="pickup">The ammo pickup.</param> - public PlayerSearchingAmmoEventArgs(ReferenceHub player, BaseAmmoPickup pickup) + public PlayerSearchingAmmoEventArgs(ReferenceHub hub, BaseAmmoPickup pickup) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); AmmoPickup = AmmoPickup.Get(pickup); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingArmorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingArmorEventArgs.cs index 7b921f4a..6d758e60 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingArmorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingArmorEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerSearchingArmorEventArgs : EventArgs, IPlayerEvent, IBodyArmor /// <summary> /// Initializes a new instance of the <see cref="PlayerSearchingArmorEventArgs"/> class. /// </summary> - /// <param name="player">The player searching for armor.</param> + /// <param name="hub">The player searching for armor.</param> /// <param name="pickup">The armor pickup.</param> - public PlayerSearchingArmorEventArgs(ReferenceHub player, BaseBodyArmorPickup pickup) + public PlayerSearchingArmorEventArgs(ReferenceHub hub, BaseBodyArmorPickup pickup) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); BodyArmorPickup = BodyArmorPickup.Get(pickup); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingPickupEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingPickupEventArgs.cs index dc12a500..de722ea4 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingPickupEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingPickupEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerSearchingPickupEventArgs : EventArgs, IPlayerEvent, IPickupEv /// <summary> /// Initializes a new instance of the <see cref="PlayerSearchingPickupEventArgs"/> class. /// </summary> - /// <param name="player">The player who is searching for the pickup.</param> + /// <param name="hub">The player who is searching for the pickup.</param> /// <param name="pickup">The pickup being searched.</param> - public PlayerSearchingPickupEventArgs(ReferenceHub player, ItemPickupBase pickup) + public PlayerSearchingPickupEventArgs(ReferenceHub hub, ItemPickupBase pickup) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Pickup = Pickup.Get(pickup); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingToyEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingToyEventArgs.cs index d6980cea..6000f09e 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingToyEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingToyEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerSearchingToyEventArgs : EventArgs, IPlayerEvent, IInteractabl /// <summary> /// Initializes a new instance of the <see cref="PlayerSearchingToyEventArgs"/> class. /// </summary> - /// <param name="player">The player who is searching the toy.</param> + /// <param name="hub">The player who is searching the toy.</param> /// <param name="toy">The toy that is going to be searched.</param> - public PlayerSearchingToyEventArgs(ReferenceHub player, InvisibleInteractableToy toy) + public PlayerSearchingToyEventArgs(ReferenceHub hub, InvisibleInteractableToy toy) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Interactable = InteractableToy.Get(toy); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerShootingWeaponEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerShootingWeaponEventArgs.cs index 28047a03..859a667a 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerShootingWeaponEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerShootingWeaponEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerShootingWeaponEventArgs : EventArgs, IPlayerEvent, IFirearmIt /// <summary> /// Initializes a new instance of the <see cref="PlayerShootingWeaponEventArgs"/> class. /// </summary> - /// <param name="player">The player who is shooting.</param> + /// <param name="hub">The player who is shooting.</param> /// <param name="weapon">The firearm that the player shooting from.</param> - public PlayerShootingWeaponEventArgs(ReferenceHub player, Firearm weapon) + public PlayerShootingWeaponEventArgs(ReferenceHub hub, Firearm weapon) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); FirearmItem = FirearmItem.Get(weapon); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerShotWeaponEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerShotWeaponEventArgs.cs index f502c47f..7d0e31dd 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerShotWeaponEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerShotWeaponEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerShotWeaponEventArgs : EventArgs, IPlayerEvent, IFirearmItemEv /// <summary> /// Initializes a new instance of the <see cref="PlayerShotWeaponEventArgs"/> class. /// </summary> - /// <param name="player">The player who shot.</param> + /// <param name="hub">The player who shot.</param> /// <param name="weapon">The firearm that the player shot from.</param> - public PlayerShotWeaponEventArgs(ReferenceHub player, Firearm weapon) + public PlayerShotWeaponEventArgs(ReferenceHub hub, Firearm weapon) { - Player = Player.Get(player); + Player = Player.Get(hub); FirearmItem = FirearmItem.Get(weapon); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSpawnedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSpawnedEventArgs.cs index 5196b166..d899d140 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSpawnedEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSpawnedEventArgs.cs @@ -14,14 +14,14 @@ public class PlayerSpawnedEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerSpawnedEventArgs"/> class. /// </summary> - /// <param name="player">The player who is being spawned.</param> + /// <param name="hub">The player who is being spawned.</param> /// <param name="role">The role that is being applied.</param> /// <param name="useSpawnPoint">If spawnpoint should be used.</param> /// <param name="spawnLocation">The default spawn location.</param> /// <param name="horizontalRotation">The default spawn horizontal rotation.</param> - public PlayerSpawnedEventArgs(ReferenceHub player, PlayerRoleBase role, bool useSpawnPoint, Vector3 spawnLocation, float horizontalRotation) + public PlayerSpawnedEventArgs(ReferenceHub hub, PlayerRoleBase role, bool useSpawnPoint, Vector3 spawnLocation, float horizontalRotation) { - Player = Player.Get(player); + Player = Player.Get(hub); Role = role; UseSpawnPoint = useSpawnPoint; SpawnLocation = spawnLocation; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSpawnedRagdollEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSpawnedRagdollEventArgs.cs index 7ccd0b9f..a5a88f48 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSpawnedRagdollEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSpawnedRagdollEventArgs.cs @@ -14,12 +14,12 @@ public class PlayerSpawnedRagdollEventArgs : EventArgs, IPlayerEvent, IRagdollEv /// <summary> /// Initializes a new instance of the <see cref="PlayerSpawnedRagdollEventArgs"/> class. /// </summary> - /// <param name="player">The player from who is ragdoll from.</param> + /// <param name="hub">The player from who is ragdoll from.</param> /// <param name="ragdoll">The spawned ragdoll.</param> /// <param name="damageHandler">The damage handler that caused the death of the player.</param> - public PlayerSpawnedRagdollEventArgs(ReferenceHub player, BasicRagdoll ragdoll, DamageHandlerBase damageHandler) + public PlayerSpawnedRagdollEventArgs(ReferenceHub hub, BasicRagdoll ragdoll, DamageHandlerBase damageHandler) { - Player = Player.Get(player); + Player = Player.Get(hub); Ragdoll = Ragdoll.Get(ragdoll); DamageHandler = damageHandler; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSpawningEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSpawningEventArgs.cs index ba75ad34..c3c5de99 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSpawningEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSpawningEventArgs.cs @@ -17,15 +17,15 @@ public class PlayerSpawningEventArgs : EventArgs, IPlayerEvent, ICancellableEven /// <summary> /// Initializes a new instance of the <see cref="PlayerSpawningEventArgs"/> class. /// </summary> - /// <param name="player">The player who is being spawned.</param> + /// <param name="hub">The player who is being spawned.</param> /// <param name="role">The role that is being applied.</param> /// <param name="useSpawnPoint">If spawnpoint should be used.</param> /// <param name="spawnLocation">The default spawn location.</param> /// <param name="horizontalRotation">The default spawn horizontal rotation.</param> - public PlayerSpawningEventArgs(ReferenceHub player, PlayerRoleBase role, bool useSpawnPoint, Vector3 spawnLocation, float horizontalRotation) + public PlayerSpawningEventArgs(ReferenceHub hub, PlayerRoleBase role, bool useSpawnPoint, Vector3 spawnLocation, float horizontalRotation) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Role = role; UseSpawnPoint = useSpawnPoint; _spawnLocation = spawnLocation; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSpawningRagdollEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSpawningRagdollEventArgs.cs index 82ae672c..b756b921 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSpawningRagdollEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSpawningRagdollEventArgs.cs @@ -14,13 +14,13 @@ public class PlayerSpawningRagdollEventArgs : EventArgs, IPlayerEvent, ICancella /// <summary> /// Initializes a new instance of the <see cref="PlayerSpawningRagdollEventArgs"/> class. /// </summary> - /// <param name="player">The player from who is ragdoll from.</param> + /// <param name="hub">The player from who is ragdoll from.</param> /// <param name="ragdoll">The ragdoll which being spawned.</param> /// <param name="damageHandler">The damage handler that caused the death of the player.</param> - public PlayerSpawningRagdollEventArgs(ReferenceHub player, BasicRagdoll ragdoll, DamageHandlerBase damageHandler) + public PlayerSpawningRagdollEventArgs(ReferenceHub hub, BasicRagdoll ragdoll, DamageHandlerBase damageHandler) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); RagdollPrefab = Ragdoll.Get(ragdoll); DamageHandler = damageHandler; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSpinnedRevolverEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSpinnedRevolverEventArgs.cs new file mode 100644 index 00000000..583bb90f --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSpinnedRevolverEventArgs.cs @@ -0,0 +1,32 @@ +using InventorySystem.Items.Firearms; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.SpinnedRevolver"/> event. +/// </summary> +public class PlayerSpinnedRevolverEventArgs : EventArgs, IPlayerEvent, IRevolverItemEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="PlayerSpinnedRevolverEventArgs"/> class. + /// </summary> + /// <param name="hub">The player who spinned the revolver.</param> + /// <param name="weapon">The revolver firearm.</param> + public PlayerSpinnedRevolverEventArgs(ReferenceHub hub, Firearm weapon) + { + Player = Player.Get(hub); + Revolver = (RevolverFirearm)FirearmItem.Get(weapon); + } + + /// <summary> + /// Gets the player who spinned the revolver. + /// </summary> + public Player Player { get; } + + /// <summary> + /// Gets the revolver item. + /// </summary> + public RevolverFirearm Revolver { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSpinningRevolverEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSpinningRevolverEventArgs.cs new file mode 100644 index 00000000..4fd37a6c --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSpinningRevolverEventArgs.cs @@ -0,0 +1,37 @@ +using InventorySystem.Items.Firearms; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.SpinningRevolver"/> event. +/// </summary> +public class PlayerSpinningRevolverEventArgs : EventArgs, IPlayerEvent, IRevolverItemEvent, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="PlayerSpinningRevolverEventArgs"/> class. + /// </summary> + /// <param name="hub">The player who is attempting to spin the revolver.</param> + /// <param name="weapon">The revolver firearm.</param> + public PlayerSpinningRevolverEventArgs(ReferenceHub hub, Firearm weapon) + { + Player = Player.Get(hub); + Revolver = (RevolverFirearm)FirearmItem.Get(weapon); + IsAllowed = true; + } + + /// <summary> + /// Gets the player who is attempting to spin the revolver. + /// </summary> + public Player Player { get; } + + /// <summary> + /// Gets the revolver item. + /// </summary> + public RevolverFirearm Revolver { get; } + + /// <inheritdoc/> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerThrewItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerThrewItemEventArgs.cs index 57d8fea4..45030a8d 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerThrewItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerThrewItemEventArgs.cs @@ -14,12 +14,12 @@ public class PlayerThrewItemEventArgs : EventArgs, IPlayerEvent, IPickupEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerThrewItemEventArgs"/> class. /// </summary> - /// <param name="player">The player who threw the item.</param> + /// <param name="hub">The player who threw the item.</param> /// <param name="item">The item that was thrown.</param> /// <param name="rigidbody">The rigidbody of the item.</param> - public PlayerThrewItemEventArgs(ReferenceHub player, ItemPickupBase item, Rigidbody rigidbody) + public PlayerThrewItemEventArgs(ReferenceHub hub, ItemPickupBase item, Rigidbody rigidbody) { - Player = Player.Get(player); + Player = Player.Get(hub); Pickup = Pickup.Get(item); Rigidbody = rigidbody; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerThrewProjectileEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerThrewProjectileEventArgs.cs index 7b048f8d..e683b115 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerThrewProjectileEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerThrewProjectileEventArgs.cs @@ -15,14 +15,14 @@ public class PlayerThrewProjectileEventArgs : EventArgs, IPlayerEvent, IThrowabl /// <summary> /// Initializes a new instance of the <see cref="PlayerThrewProjectileEventArgs"/> class. /// </summary> - /// <param name="player">The player who threw the throwable item.</param> + /// <param name="hub">The player who threw the throwable item.</param> /// <param name="item">The original item that was thrown.</param> /// <param name="projectile">The new projectile object created.</param> /// <param name="projectileSettings">Projectile settings at which throwable was thrown.</param> /// <param name="fullForce">Value whenever the throwable was thrown at full force (overhand).</param> - public PlayerThrewProjectileEventArgs(ReferenceHub player, BaseThrowableItem item, ThrownProjectile projectile, ProjectileSettings projectileSettings, bool fullForce) + public PlayerThrewProjectileEventArgs(ReferenceHub hub, BaseThrowableItem item, ThrownProjectile projectile, ProjectileSettings projectileSettings, bool fullForce) { - Player = Player.Get(player); + Player = Player.Get(hub); ThrowableItem = ThrowableItem.Get(item); Projectile = Projectile.Get(projectile); ProjectileSettings = projectileSettings; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerThrowingItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerThrowingItemEventArgs.cs index 03c518fc..842f76c1 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerThrowingItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerThrowingItemEventArgs.cs @@ -15,13 +15,13 @@ public class PlayerThrowingItemEventArgs : EventArgs, IPlayerEvent, IPickupEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerThrowingItemEventArgs"/> class. /// </summary> - /// <param name="player">The player who is throwing the item.</param> + /// <param name="hub">The player who is throwing the item.</param> /// <param name="item">The item that is being thrown.</param> /// <param name="rigidbody">The rigidbody of the item.</param> - public PlayerThrowingItemEventArgs(ReferenceHub player, ItemPickupBase item, Rigidbody rigidbody) + public PlayerThrowingItemEventArgs(ReferenceHub hub, ItemPickupBase item, Rigidbody rigidbody) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Pickup = Pickup.Get(item); Rigidbody = rigidbody; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerThrowingProjectileEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerThrowingProjectileEventArgs.cs index f33134bc..f25c7dcb 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerThrowingProjectileEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerThrowingProjectileEventArgs.cs @@ -14,14 +14,14 @@ public class PlayerThrowingProjectileEventArgs : EventArgs, IPlayerEvent, IThrow /// <summary> /// Initializes a new instance of the <see cref="PlayerThrowingProjectileEventArgs"/> class. /// </summary> - /// <param name="player">The player who threw the projectile.</param> + /// <param name="hub">The player who threw the projectile.</param> /// <param name="item">The original throwable item.</param> /// <param name="projectileSettings">Projectile settings at which is throwable being thrown.</param> /// <param name="fullForce">Value whenever the throwable is being thrown at full force (overhand).</param> - public PlayerThrowingProjectileEventArgs(ReferenceHub player, BaseThrowableItem item, ProjectileSettings projectileSettings, bool fullForce) + public PlayerThrowingProjectileEventArgs(ReferenceHub hub, BaseThrowableItem item, ProjectileSettings projectileSettings, bool fullForce) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); ThrowableItem = ThrowableItem.Get(item); ProjectileSettings = projectileSettings; FullForce = fullForce; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerToggledDisruptorFiringModeEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerToggledDisruptorFiringModeEventArgs.cs new file mode 100644 index 00000000..64c418d2 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerToggledDisruptorFiringModeEventArgs.cs @@ -0,0 +1,41 @@ +using InventorySystem.Items.Firearms; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.ToggledDisruptorFiringMode"/> event. +/// </summary> +public class PlayerToggledDisruptorFiringModeEventArgs : EventArgs, IPlayerEvent, IFirearmItemEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="PlayerToggledDisruptorFiringModeEventArgs"/> class. + /// </summary> + /// <param name="hub">The player who toggled the firing mode.</param> + /// <param name="weapon">The weapon that the player toggled.</param> + /// <param name="singleShot">Whether the mode is now single shot.</param> + public PlayerToggledDisruptorFiringModeEventArgs(ReferenceHub hub, Firearm weapon, bool singleShot) + { + Player = Player.Get(hub); + FirearmItem = FirearmItem.Get(weapon); + SingleShotMode = singleShot; + } + + /// <summary> + /// Gets the player who toggled the firing mode. + /// </summary> + public Player Player { get; } + + /// <summary> + /// Gets the weapon that the player toggled. + /// </summary> + public FirearmItem FirearmItem { get; } + + /// <summary> + /// Gets whether the disruptor is in single shot mode. + /// </summary> + public bool SingleShotMode { get; } +} + diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerToggledFlashlightEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerToggledFlashlightEventArgs.cs index 57bb3d14..90157e53 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerToggledFlashlightEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerToggledFlashlightEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerToggledFlashlightEventArgs : EventArgs, IPlayerEvent, ILightI /// <summary> /// Initializes a new instance of the <see cref="PlayerToggledFlashlightEventArgs"/> class. /// </summary> - /// <param name="player">The player who toggled the flashlight.</param> + /// <param name="hub">The player who toggled the flashlight.</param> /// <param name="item">The flashlight item.</param> /// <param name="newState">New state of the flashlight.</param> - public PlayerToggledFlashlightEventArgs(ReferenceHub player, ToggleableLightItemBase item, bool newState) + public PlayerToggledFlashlightEventArgs(ReferenceHub hub, ToggleableLightItemBase item, bool newState) { - Player = Player.Get(player); + Player = Player.Get(hub); LightItem = LightItem.Get(item); NewState = newState; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerToggledNoclipEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerToggledNoclipEventArgs.cs index a7a438bd..e9241d29 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerToggledNoclipEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerToggledNoclipEventArgs.cs @@ -12,11 +12,11 @@ public class PlayerToggledNoclipEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerToggledNoclipEventArgs"/> class. /// </summary> - /// <param name="player">The player who has toggled the noclip.</param> + /// <param name="hub">The player who has toggled the noclip.</param> /// <param name="isNoclipping">The new state of the noclip.</param> - public PlayerToggledNoclipEventArgs(ReferenceHub player, bool isNoclipping) + public PlayerToggledNoclipEventArgs(ReferenceHub hub, bool isNoclipping) { - Player = Player.Get(player); + Player = Player.Get(hub); IsNoclipping = isNoclipping; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerToggledRadioEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerToggledRadioEventArgs.cs index 8fd0ca4a..2e9f0ea4 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerToggledRadioEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerToggledRadioEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerToggledRadioEventArgs : EventArgs, IPlayerEvent, IRadioItemEv /// <summary> /// Initializes a new instance of the <see cref="PlayerToggledRadioEventArgs"/> class. /// </summary> - /// <param name="player">The player who toggled the radio.</param> + /// <param name="hub">The player who toggled the radio.</param> /// <param name="radio">The radio item.</param> /// <param name="newState">New state of the radio.</param> - public PlayerToggledRadioEventArgs(ReferenceHub player, BaseRadioItem radio, bool newState) + public PlayerToggledRadioEventArgs(ReferenceHub hub, BaseRadioItem radio, bool newState) { - Player = Player.Get(player); + Player = Player.Get(hub); RadioItem = RadioItem.Get(radio); NewState = newState; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerToggledWeaponFlashlightEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerToggledWeaponFlashlightEventArgs.cs index 2839f9e9..2c11ed2d 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerToggledWeaponFlashlightEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerToggledWeaponFlashlightEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerToggledWeaponFlashlightEventArgs : EventArgs, IPlayerEvent, I /// <summary> /// Initializes a new instance of the <see cref="PlayerToggledWeaponFlashlightEventArgs"/> class. /// </summary> - /// <param name="player">The player who toggled the flashlight.</param> + /// <param name="hub">The player who toggled the flashlight.</param> /// <param name="item">The flashlight item.</param> /// <param name="newState">The new state of the flashlight.</param> - public PlayerToggledWeaponFlashlightEventArgs(ReferenceHub player, Firearm item, bool newState) + public PlayerToggledWeaponFlashlightEventArgs(ReferenceHub hub, Firearm item, bool newState) { - Player = Player.Get(player); + Player = Player.Get(hub); FirearmItem = FirearmItem.Get(item); NewState = newState; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingFlashlightEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingFlashlightEventArgs.cs index 31612324..08d792d2 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingFlashlightEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingFlashlightEventArgs.cs @@ -13,13 +13,13 @@ public class PlayerTogglingFlashlightEventArgs : EventArgs, IPlayerEvent, ILight /// <summary> /// Initializes a new instance of the <see cref="PlayerTogglingFlashlightEventArgs"/> class. /// </summary> - /// <param name="player">The player who is toggling the flashlight.</param> + /// <param name="hub">The player who is toggling the flashlight.</param> /// <param name="item">The flashlight that is being toggled.</param> /// <param name="newState">Whenever the flashlight is being toggled to on or off state.</param> - public PlayerTogglingFlashlightEventArgs(ReferenceHub player, ToggleableLightItemBase item, bool newState) + public PlayerTogglingFlashlightEventArgs(ReferenceHub hub, ToggleableLightItemBase item, bool newState) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); LightItem = LightItem.Get(item); NewState = newState; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingNoclipEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingNoclipEventArgs.cs index 3257e209..9717ef60 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingNoclipEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingNoclipEventArgs.cs @@ -12,12 +12,12 @@ public class PlayerTogglingNoclipEventArgs : EventArgs, IPlayerEvent, ICancellab /// <summary> /// Initializes a new instance of <see cref=" PlayerTogglingNoclipEventArgs"/> clas. /// </summary> - /// <param name="player">The player who is attempting to toggle noclip.</param> + /// <param name="hub">The player who is attempting to toggle noclip.</param> /// <param name="newState">Whether the noclip state will be enabled or disabled.</param> - public PlayerTogglingNoclipEventArgs(ReferenceHub player, bool newState) + public PlayerTogglingNoclipEventArgs(ReferenceHub hub, bool newState) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); NewNoclipState = newState; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingRadioEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingRadioEventArgs.cs index 66a25d46..93d0d11c 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingRadioEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingRadioEventArgs.cs @@ -13,13 +13,13 @@ public class PlayerTogglingRadioEventArgs : EventArgs, IPlayerEvent, IRadioItemE /// <summary> /// Initializes a new instance of the <see cref="PlayerTogglingRadioEventArgs"/> class. /// </summary> - /// <param name="player">The player who is toggling a radio.</param> + /// <param name="hub">The player who is toggling a radio.</param> /// <param name="radio">The radio item.</param> /// <param name="newState">New state of the radio being turned off or on.</param> - public PlayerTogglingRadioEventArgs(ReferenceHub player, BaseRadioItem radio, bool newState) + public PlayerTogglingRadioEventArgs(ReferenceHub hub, BaseRadioItem radio, bool newState) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); RadioItem = RadioItem.Get(radio); NewState = newState; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingWeaponFlashlightEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingWeaponFlashlightEventArgs.cs index 7db324ab..35fb4b22 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingWeaponFlashlightEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingWeaponFlashlightEventArgs.cs @@ -13,13 +13,13 @@ public class PlayerTogglingWeaponFlashlightEventArgs : EventArgs, IPlayerEvent, /// <summary> /// Initializes a new instance of the <see cref="PlayerTogglingWeaponFlashlightEventArgs"/> class. /// </summary> - /// <param name="player">The player who is toggling the flashlight.</param> + /// <param name="hub">The player who is toggling the flashlight.</param> /// <param name="item">The flashlight item.</param> /// <param name="newState">The new state of the flashlight.</param> - public PlayerTogglingWeaponFlashlightEventArgs(ReferenceHub player, Firearm item, bool newState) + public PlayerTogglingWeaponFlashlightEventArgs(ReferenceHub hub, Firearm item, bool newState) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); FirearmItem = FirearmItem.Get(item); NewState = newState; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUncuffedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUncuffedEventArgs.cs index ad0c759d..eb8c6f62 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUncuffedEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUncuffedEventArgs.cs @@ -12,12 +12,12 @@ public class PlayerUncuffedEventArgs : EventArgs, IPlayerEvent, ITargetEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerUncuffedEventArgs"/> class. /// </summary> - /// <param name="player">The player who uncuffed target player.</param> + /// <param name="hub">The player who uncuffed target player.</param> /// <param name="target">The player who was uncuffed.</param> /// <param name="canUnDetainAsScp">Whenever the player can undetain as SCP player.</param> - public PlayerUncuffedEventArgs(ReferenceHub player, ReferenceHub target, bool canUnDetainAsScp) + public PlayerUncuffedEventArgs(ReferenceHub hub, ReferenceHub target, bool canUnDetainAsScp) { - Player = Player.Get(player); + Player = Player.Get(hub); Target = Player.Get(target); CanUnDetainAsScp = canUnDetainAsScp; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUncuffingEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUncuffingEventArgs.cs index 478b2a38..8d5eab54 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUncuffingEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUncuffingEventArgs.cs @@ -12,13 +12,13 @@ public class PlayerUncuffingEventArgs : EventArgs, IPlayerEvent, ITargetEvent, I /// <summary> /// Initializes a new instance of the <see cref="PlayerUncuffingEventArgs"/> class. /// </summary> - /// <param name="player">The player who is uncuffing another player.</param> + /// <param name="hub">The player who is uncuffing another player.</param> /// <param name="target">The player who is being uncuffed.</param> /// <param name="canUnDetainAsScp">Whenever the player can undetain as SCP player</param> - public PlayerUncuffingEventArgs(ReferenceHub player, ReferenceHub target, bool canUnDetainAsScp) + public PlayerUncuffingEventArgs(ReferenceHub hub, ReferenceHub target, bool canUnDetainAsScp) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Target = Player.Get(target); CanUnDetainAsScp = canUnDetainAsScp; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUnloadedWeaponEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUnloadedWeaponEventArgs.cs index 06fadf1d..894cdb89 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUnloadedWeaponEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUnloadedWeaponEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerUnloadedWeaponEventArgs : EventArgs, IPlayerEvent, IFirearmIt /// <summary> /// Initializes a new instance of the <see cref="PlayerUnloadedWeaponEventArgs"/> class. /// </summary> - /// <param name="player">The player who unloaded the weapon.</param> + /// <param name="hub">The player who unloaded the weapon.</param> /// <param name="weapon">The weapon that was unloaded.</param> - public PlayerUnloadedWeaponEventArgs(ReferenceHub player, Firearm weapon) + public PlayerUnloadedWeaponEventArgs(ReferenceHub hub, Firearm weapon) { - Player = Player.Get(player); + Player = Player.Get(hub); FirearmItem = FirearmItem.Get(weapon); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUnloadingWeaponEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUnloadingWeaponEventArgs.cs index 17c3a9df..aae73d46 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUnloadingWeaponEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUnloadingWeaponEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerUnloadingWeaponEventArgs : EventArgs, IPlayerEvent, IFirearmI /// <summary> /// Initializes a new instance of the <see cref="PlayerUnloadingWeaponEventArgs"/> class. /// </summary> - /// <param name="player">The player who is unloading a weapon.</param> + /// <param name="hub">The player who is unloading a weapon.</param> /// <param name="weapon">The weapon that is being unloaded.</param> - public PlayerUnloadingWeaponEventArgs(ReferenceHub player, Firearm weapon) + public PlayerUnloadingWeaponEventArgs(ReferenceHub hub, Firearm weapon) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); FirearmItem = FirearmItem.Get(weapon); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockedGeneratorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockedGeneratorEventArgs.cs index dfa00707..b63f3b25 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockedGeneratorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockedGeneratorEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerUnlockedGeneratorEventArgs : EventArgs, IPlayerEvent, IGenera /// <summary> /// Initializes a new instance of the <see cref="PlayerUnlockedGeneratorEventArgs"/> class. /// </summary> - /// <param name="player">The player who unlocked the generator.</param> + /// <param name="hub">The player who unlocked the generator.</param> /// <param name="generator">The generator that the player has unlocked.</param> - public PlayerUnlockedGeneratorEventArgs(ReferenceHub player, Scp079Generator generator) + public PlayerUnlockedGeneratorEventArgs(ReferenceHub hub, Scp079Generator generator) { - Player = Player.Get(player); + Player = Player.Get(hub); Generator = Generator.Get(generator); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockedWarheadButtonEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockedWarheadButtonEventArgs.cs index 445d543e..5e84393c 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockedWarheadButtonEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockedWarheadButtonEventArgs.cs @@ -12,10 +12,10 @@ public class PlayerUnlockedWarheadButtonEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerUnlockedWarheadButtonEventArgs"/> class. /// </summary> - /// <param name="player">The player who has unlocked the warhead button.</param> - public PlayerUnlockedWarheadButtonEventArgs(ReferenceHub player) + /// <param name="hub">The player who has unlocked the warhead button.</param> + public PlayerUnlockedWarheadButtonEventArgs(ReferenceHub hub) { - Player = Player.Get(player); + Player = Player.Get(hub); } /// <summary> diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockingGeneratorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockingGeneratorEventArgs.cs index 9cb18a10..6866f5e1 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockingGeneratorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockingGeneratorEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerUnlockingGeneratorEventArgs : EventArgs, IPlayerEvent, IGener /// <summary> /// Initializes a new instance of the <see cref="PlayerUnlockingGeneratorEventArgs"/> class. /// </summary> - /// <param name="player">The player who is unlocking the generator.</param> + /// <param name="hub">The player who is unlocking the generator.</param> /// <param name="generator">The generator that the player is unlocking.</param> /// <param name="canOpen">Whether the generator can be opened.</param> - public PlayerUnlockingGeneratorEventArgs(ReferenceHub player, Scp079Generator generator, bool canOpen) + public PlayerUnlockingGeneratorEventArgs(ReferenceHub hub, Scp079Generator generator, bool canOpen) { - Player = Player.Get(player); + Player = Player.Get(hub); Generator = Generator.Get(generator); IsAllowed = true; CanOpen = canOpen; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockingWarheadButtonEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockingWarheadButtonEventArgs.cs index 8e6a3980..f3bbfedf 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockingWarheadButtonEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockingWarheadButtonEventArgs.cs @@ -12,10 +12,10 @@ public class PlayerUnlockingWarheadButtonEventArgs : EventArgs, IPlayerEvent, IC /// <summary> /// Initializes a new instance of the <see cref="PlayerUnlockingWarheadButtonEventArgs"/> class. /// </summary> - /// <param name="player">The player who unlocking the warhead button.</param> - public PlayerUnlockingWarheadButtonEventArgs(ReferenceHub player) + /// <param name="hub">The player who unlocking the warhead button.</param> + public PlayerUnlockingWarheadButtonEventArgs(ReferenceHub hub) { - Player = Player.Get(player); + Player = Player.Get(hub); IsAllowed = true; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUnmutedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUnmutedEventArgs.cs index a6056c27..948931a0 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUnmutedEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUnmutedEventArgs.cs @@ -12,12 +12,12 @@ public class PlayerUnmutedEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerUnmutedEventArgs"/> class. /// </summary> - /// <param name="player">The player who was unmuted.</param> + /// <param name="hub">The player who was unmuted.</param> /// <param name="issuer">The player who issued the unmute.</param> /// <param name="isIntercom">Whenever the unmute was for intercom.</param> - public PlayerUnmutedEventArgs(ReferenceHub player, ReferenceHub issuer, bool isIntercom) + public PlayerUnmutedEventArgs(ReferenceHub hub, ReferenceHub issuer, bool isIntercom) { - Player = Player.Get(player); + Player = Player.Get(hub); Issuer = Player.Get(issuer); IsIntercom = isIntercom; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUnmutingEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUnmutingEventArgs.cs index f731e090..9b0d15e9 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUnmutingEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUnmutingEventArgs.cs @@ -12,13 +12,13 @@ public class PlayerUnmutingEventArgs : EventArgs, IPlayerEvent, ICancellableEven /// <summary> /// Initializes a new instance of the <see cref="PlayerUnmutingEventArgs"/> class. /// </summary> - /// <param name="player">The player who is being unmuted.</param> + /// <param name="hub">The player who is being unmuted.</param> /// <param name="issuer">The player who issued the unmute action.</param> /// <param name="isIntercom">Whenever is unmute for intercom.</param> - public PlayerUnmutingEventArgs(ReferenceHub player, ReferenceHub issuer, bool isIntercom) + public PlayerUnmutingEventArgs(ReferenceHub hub, ReferenceHub issuer, bool isIntercom) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Issuer = Player.Get(issuer); IsIntercom = isIntercom; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUsedIntercomEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUsedIntercomEventArgs.cs index e037a2de..cec2c8be 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUsedIntercomEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUsedIntercomEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerUsedIntercomEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerUsedIntercomEventArgs"/> class. /// </summary> - /// <param name="player">The player who used the intercom.</param> + /// <param name="hub">The player who used the intercom.</param> /// <param name="state">State of the intercom.</param> - public PlayerUsedIntercomEventArgs(ReferenceHub? player, IntercomState state) + public PlayerUsedIntercomEventArgs(ReferenceHub? hub, IntercomState state) { - Player = Player.Get(player); + Player = Player.Get(hub); State = state; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUsedItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUsedItemEventArgs.cs index 63766d64..885cc193 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUsedItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUsedItemEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerUsedItemEventArgs : EventArgs, IPlayerEvent, IUsableItemEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerUsedItemEventArgs"/> class. /// </summary> - /// <param name="player">The player who used the item.</param> + /// <param name="hub">The player who used the item.</param> /// <param name="item">Item that was used.</param> - public PlayerUsedItemEventArgs(ReferenceHub player, BaseUsableItem item) + public PlayerUsedItemEventArgs(ReferenceHub hub, BaseUsableItem item) { - Player = Player.Get(player); + Player = Player.Get(hub); UsableItem = UsableItem.Get(item); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUsedRadioEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUsedRadioEventArgs.cs index 2d7ab251..b7d2a960 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUsedRadioEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUsedRadioEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerUsedRadioEventArgs : EventArgs, IPlayerEvent, IRadioItemEvent /// <summary> /// Initializes a new instance of the <see cref="PlayerUsedRadioEventArgs"/> class. /// </summary> - /// <param name="player">Player that used the radio.</param> + /// <param name="hub">Player that used the radio.</param> /// <param name="radio">Radio that was being used.</param> /// <param name="drain">Drain amount of the battery per second.</param> - public PlayerUsedRadioEventArgs(ReferenceHub player, BaseRadioItem radio, float drain) + public PlayerUsedRadioEventArgs(ReferenceHub hub, BaseRadioItem radio, float drain) { - Player = Player.Get(player); + Player = Player.Get(hub); RadioItem = RadioItem.Get(radio); Drain = drain; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUsingIntercomEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUsingIntercomEventArgs.cs index ec7f93bb..81626ae1 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUsingIntercomEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUsingIntercomEventArgs.cs @@ -13,13 +13,13 @@ public class PlayerUsingIntercomEventArgs : EventArgs, IPlayerEvent, ICancellabl /// <summary> /// Initializes a new instance of the <see cref="PlayerUsingIntercomEventArgs"/> class. /// </summary> - /// <param name="player">The player that is using the intercom.</param> + /// <param name="hub">The player that is using the intercom.</param> /// <param name="state">State of the intercom.</param> //TODO: Add intercom class and ref it docs - public PlayerUsingIntercomEventArgs(ReferenceHub player, IntercomState state) + public PlayerUsingIntercomEventArgs(ReferenceHub hub, IntercomState state) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); State = state; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUsingItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUsingItemEventArgs.cs index 48158bdf..9e08bb98 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUsingItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUsingItemEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerUsingItemEventArgs : EventArgs, IPlayerEvent, IUsableItemEven /// <summary> /// Initializes a new instance of the <see cref="PlayerUsingItemEventArgs"/> class. /// </summary> - /// <param name="player">The player using the item.</param> + /// <param name="hub">The player using the item.</param> /// <param name="item">The item that is being used.</param> - public PlayerUsingItemEventArgs(ReferenceHub player, BaseUsableItem item) + public PlayerUsingItemEventArgs(ReferenceHub hub, BaseUsableItem item) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); UsableItem = UsableItem.Get(item); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUsingRadioEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUsingRadioEventArgs.cs index af5787ac..1e5abf67 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUsingRadioEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUsingRadioEventArgs.cs @@ -13,13 +13,13 @@ public class PlayerUsingRadioEventArgs : EventArgs, IPlayerEvent, IRadioItemEven /// <summary> /// Initializes a new instance of the <see cref="PlayerUsingRadioEventArgs"/> class. /// </summary> - /// <param name="player">The player who is using the radio.</param> + /// <param name="hub">The player who is using the radio.</param> /// <param name="radio">Radio item that is being used.</param> /// <param name="drain">Battery drain amount per second.</param> - public PlayerUsingRadioEventArgs(ReferenceHub player, BaseRadioItem radio, float drain) + public PlayerUsingRadioEventArgs(ReferenceHub hub, BaseRadioItem radio, float drain) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); RadioItem = RadioItem.Get(radio); Drain = drain; } diff --git a/LabApi/Events/Arguments/Scp049Events/Scp049ResurrectedBodyEventArgs.cs b/LabApi/Events/Arguments/Scp049Events/Scp049ResurrectedBodyEventArgs.cs index 7eba4f2d..2a4359d1 100644 --- a/LabApi/Events/Arguments/Scp049Events/Scp049ResurrectedBodyEventArgs.cs +++ b/LabApi/Events/Arguments/Scp049Events/Scp049ResurrectedBodyEventArgs.cs @@ -13,11 +13,11 @@ public class Scp049ResurrectedBodyEventArgs : EventArgs, IPlayerEvent, ITargetEv /// Initializes a new instance of the <see cref="Scp049ResurrectedBodyEventArgs"/> class. /// </summary> /// <param name="target">The player that SCP-049 has resurrected.</param> - /// <param name="player">The SCP-049 player instance.</param> - public Scp049ResurrectedBodyEventArgs(ReferenceHub target, ReferenceHub player) + /// <param name="hub">The SCP-049 player instance.</param> + public Scp049ResurrectedBodyEventArgs(ReferenceHub target, ReferenceHub hub) { Target = Player.Get(target); - Player = Player.Get(player); + Player = Player.Get(hub); } /// <summary> diff --git a/LabApi/Events/Arguments/Scp049Events/Scp049ResurrectingBodyEventArgs.cs b/LabApi/Events/Arguments/Scp049Events/Scp049ResurrectingBodyEventArgs.cs index dac207f0..0e54e263 100644 --- a/LabApi/Events/Arguments/Scp049Events/Scp049ResurrectingBodyEventArgs.cs +++ b/LabApi/Events/Arguments/Scp049Events/Scp049ResurrectingBodyEventArgs.cs @@ -14,12 +14,12 @@ public class Scp049ResurrectingBodyEventArgs : EventArgs, ICancellableEvent, IPl /// </summary> /// <param name="ragdoll">The ragdoll that SCP-049 is resurrecting.</param> /// <param name="target">The player that SCP-049 is resurrecting.</param> - /// <param name="player">The SCP-049 player instance.</param> - public Scp049ResurrectingBodyEventArgs(Ragdoll ragdoll, ReferenceHub target, ReferenceHub player) + /// <param name="hub">The SCP-049 player instance.</param> + public Scp049ResurrectingBodyEventArgs(Ragdoll ragdoll, ReferenceHub target, ReferenceHub hub) { Ragdoll = ragdoll; Target = Player.Get(target); - Player = Player.Get(player); + Player = Player.Get(hub); IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp049Events/Scp049StartingResurrectionEventArgs.cs b/LabApi/Events/Arguments/Scp049Events/Scp049StartingResurrectionEventArgs.cs index a8f04cf8..8775f681 100644 --- a/LabApi/Events/Arguments/Scp049Events/Scp049StartingResurrectionEventArgs.cs +++ b/LabApi/Events/Arguments/Scp049Events/Scp049StartingResurrectionEventArgs.cs @@ -16,13 +16,13 @@ public class Scp049StartingResurrectionEventArgs : EventArgs, ICancellableEvent, /// <param name="canResurrect">Whether SCP-049 can resurrect the ragdoll.</param> /// <param name="ragdoll">The ragdoll that SCP-049 is resurrecting.</param> /// <param name="target">The owner of the ragdoll that SCP-049 is resurrecting.</param> - /// <param name="player">The SCP-049 player instance.</param> - public Scp049StartingResurrectionEventArgs(bool canResurrect, BasicRagdoll ragdoll, ReferenceHub? target, ReferenceHub player) + /// <param name="hub">The SCP-049 player instance.</param> + public Scp049StartingResurrectionEventArgs(bool canResurrect, BasicRagdoll ragdoll, ReferenceHub? target, ReferenceHub hub) { CanResurrect = canResurrect; Ragdoll = Ragdoll.Get(ragdoll); Target = Player.Get(target); - Player = Player.Get(player); + Player = Player.Get(hub); IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp049Events/Scp049UsedDoctorsCallEventArgs.cs b/LabApi/Events/Arguments/Scp049Events/Scp049UsedDoctorsCallEventArgs.cs index d358388a..78ca5252 100644 --- a/LabApi/Events/Arguments/Scp049Events/Scp049UsedDoctorsCallEventArgs.cs +++ b/LabApi/Events/Arguments/Scp049Events/Scp049UsedDoctorsCallEventArgs.cs @@ -12,10 +12,10 @@ public class Scp049UsedDoctorsCallEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="Scp049UsedDoctorsCallEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-049 player instance.</param> - public Scp049UsedDoctorsCallEventArgs(ReferenceHub player) + /// <param name="hub">The SCP-049 player instance.</param> + public Scp049UsedDoctorsCallEventArgs(ReferenceHub hub) { - Player = Player.Get(player); + Player = Player.Get(hub); } /// <summary> diff --git a/LabApi/Events/Arguments/Scp049Events/Scp049UsedSenseEventArgs.cs b/LabApi/Events/Arguments/Scp049Events/Scp049UsedSenseEventArgs.cs index 14c13d37..2d116944 100644 --- a/LabApi/Events/Arguments/Scp049Events/Scp049UsedSenseEventArgs.cs +++ b/LabApi/Events/Arguments/Scp049Events/Scp049UsedSenseEventArgs.cs @@ -12,11 +12,11 @@ public class Scp049UsedSenseEventArgs : EventArgs, IPlayerEvent, ITargetEvent /// <summary> /// Initializes a new instance of the <see cref="Scp049UsedSenseEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-049 player instance.</param> + /// <param name="hub">The SCP-049 player instance.</param> /// <param name="target">The player that SCP-049 has used sense on.</param> - public Scp049UsedSenseEventArgs(ReferenceHub player, ReferenceHub target) + public Scp049UsedSenseEventArgs(ReferenceHub hub, ReferenceHub target) { - Player = Player.Get(player); + Player = Player.Get(hub); Target = Player.Get(target); } diff --git a/LabApi/Events/Arguments/Scp049Events/Scp049UsingDoctorsCallEventArgs.cs b/LabApi/Events/Arguments/Scp049Events/Scp049UsingDoctorsCallEventArgs.cs index a737c994..c3fbcb5a 100644 --- a/LabApi/Events/Arguments/Scp049Events/Scp049UsingDoctorsCallEventArgs.cs +++ b/LabApi/Events/Arguments/Scp049Events/Scp049UsingDoctorsCallEventArgs.cs @@ -12,10 +12,10 @@ public class Scp049UsingDoctorsCallEventArgs : EventArgs, IPlayerEvent, ICancell /// <summary> /// Initializes a new instance of the <see cref="Scp049UsingDoctorsCallEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-049 player instance.</param> - public Scp049UsingDoctorsCallEventArgs(ReferenceHub player) + /// <param name="hub">The SCP-049 player instance.</param> + public Scp049UsingDoctorsCallEventArgs(ReferenceHub hub) { - Player = Player.Get(player); + Player = Player.Get(hub); IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp049Events/Scp049UsingSenseEventArgs.cs b/LabApi/Events/Arguments/Scp049Events/Scp049UsingSenseEventArgs.cs index 57bb77cc..89f0b8db 100644 --- a/LabApi/Events/Arguments/Scp049Events/Scp049UsingSenseEventArgs.cs +++ b/LabApi/Events/Arguments/Scp049Events/Scp049UsingSenseEventArgs.cs @@ -12,11 +12,11 @@ public class Scp049UsingSenseEventArgs : EventArgs, IPlayerEvent, ITargetEvent, /// <summary> /// Initializes a new instance of the <see cref="Scp049UsingSenseEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-049 player instance.</param> + /// <param name="hub">The SCP-049 player instance.</param> /// <param name="target">The player that SCP-049 is using sense on.</param> - public Scp049UsingSenseEventArgs(ReferenceHub player, ReferenceHub target) + public Scp049UsingSenseEventArgs(ReferenceHub hub, ReferenceHub target) { - Player = Player.Get(player); + Player = Player.Get(hub); Target = Player.Get(target); IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079BlackedOutRoomEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079BlackedOutRoomEventArgs.cs index 1bc79797..1f74417a 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079BlackedOutRoomEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079BlackedOutRoomEventArgs.cs @@ -13,11 +13,11 @@ public class Scp079BlackedOutRoomEventArgs : EventArgs, IPlayerEvent, IRoomEvent /// <summary> /// Initializes a new instance of the <see cref="Scp079BlackedOutRoomEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-079 player instance.</param> + /// <param name="hub">The SCP-079 player instance.</param> /// <param name="room">The affected room instance.</param> - public Scp079BlackedOutRoomEventArgs(ReferenceHub player, RoomIdentifier room) + public Scp079BlackedOutRoomEventArgs(ReferenceHub hub, RoomIdentifier room) { - Player = Player.Get(player); + Player = Player.Get(hub); Room = Room.Get(room); } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079BlackedOutZoneEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079BlackedOutZoneEventArgs.cs index 112c7fe6..b2e17fa6 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079BlackedOutZoneEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079BlackedOutZoneEventArgs.cs @@ -13,11 +13,11 @@ public class Scp079BlackedOutZoneEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="Scp079BlackedOutRoomEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-079 player instance.</param> + /// <param name="hub">The SCP-079 player instance.</param> /// <param name="zone">The affected zone instance.</param> - public Scp079BlackedOutZoneEventArgs(ReferenceHub player, FacilityZone zone) + public Scp079BlackedOutZoneEventArgs(ReferenceHub hub, FacilityZone zone) { - Player = Player.Get(player); + Player = Player.Get(hub); Zone = zone; } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079BlackingOutRoomEventsArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079BlackingOutRoomEventsArgs.cs index c65a59cd..b719ba59 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079BlackingOutRoomEventsArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079BlackingOutRoomEventsArgs.cs @@ -13,11 +13,11 @@ public class Scp079BlackingOutRoomEventsArgs : EventArgs, IPlayerEvent, IRoomEve /// <summary> /// Initializes a new instance of the <see cref="Scp079BlackingOutRoomEventsArgs"/> class. /// </summary> - /// <param name="player">The SCP-079 player instance.</param> + /// <param name="hub">The SCP-079 player instance.</param> /// <param name="room">The affected room instance.</param> - public Scp079BlackingOutRoomEventsArgs(ReferenceHub player, RoomIdentifier room) + public Scp079BlackingOutRoomEventsArgs(ReferenceHub hub, RoomIdentifier room) { - Player = Player.Get(player); + Player = Player.Get(hub); Room = Room.Get(room); IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079BlackingOutZoneEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079BlackingOutZoneEventArgs.cs index 2c67fd05..aad04ab5 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079BlackingOutZoneEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079BlackingOutZoneEventArgs.cs @@ -13,11 +13,11 @@ public class Scp079BlackingOutZoneEventArgs : EventArgs, IPlayerEvent, ICancella /// <summary> /// Initializes a new instance of the <see cref="Scp079BlackingOutZoneEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-079 player instance.</param> + /// <param name="hub">The SCP-079 player instance.</param> /// <param name="zone">The affected zone instance.</param> - public Scp079BlackingOutZoneEventArgs(ReferenceHub player, FacilityZone zone) + public Scp079BlackingOutZoneEventArgs(ReferenceHub hub, FacilityZone zone) { - Player = Player.Get(player); + Player = Player.Get(hub); Zone = zone; IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079CancelledRoomLockdownEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079CancelledRoomLockdownEventArgs.cs index 5a0399e9..193ef375 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079CancelledRoomLockdownEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079CancelledRoomLockdownEventArgs.cs @@ -13,11 +13,11 @@ public class Scp079CancelledRoomLockdownEventArgs : EventArgs, IPlayerEvent, IRo /// <summary> /// Initializes a new instance of the <see cref="Scp079CancelledRoomLockdownEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-079 player instance.</param> + /// <param name="hub">The SCP-079 player instance.</param> /// <param name="room">The affected room instance.</param> - public Scp079CancelledRoomLockdownEventArgs(ReferenceHub player, RoomIdentifier room) + public Scp079CancelledRoomLockdownEventArgs(ReferenceHub hub, RoomIdentifier room) { - Player = Player.Get(player); + Player = Player.Get(hub); Room = Room.Get(room); } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079CancellingRoomLockdownEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079CancellingRoomLockdownEventArgs.cs index 756326e0..74e8c6d3 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079CancellingRoomLockdownEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079CancellingRoomLockdownEventArgs.cs @@ -13,11 +13,11 @@ public class Scp079CancellingRoomLockdownEventArgs : EventArgs, IPlayerEvent, IR /// <summary> /// Initializes a new instance of the <see cref="Scp079CancellingRoomLockdownEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-079 player instance.</param> + /// <param name="hub">The SCP-079 player instance.</param> /// <param name="room">The affected room instance.</param> - public Scp079CancellingRoomLockdownEventArgs(ReferenceHub player, RoomIdentifier room) + public Scp079CancellingRoomLockdownEventArgs(ReferenceHub hub, RoomIdentifier room) { - Player = Player.Get(player); + Player = Player.Get(hub); Room = Room.Get(room); IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079ChangedCameraEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079ChangedCameraEventArgs.cs index 743ccef1..856dacbd 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079ChangedCameraEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079ChangedCameraEventArgs.cs @@ -13,11 +13,11 @@ public class Scp079ChangedCameraEventArgs : EventArgs, IPlayerEvent, ICameraEven /// <summary> /// Initializes a new instance of the <see cref="Scp079ChangedCameraEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-079 player instance.</param> + /// <param name="hub">The SCP-079 player instance.</param> /// <param name="camera">The affected camera instance.</param> - public Scp079ChangedCameraEventArgs(ReferenceHub player, Scp079Camera camera) + public Scp079ChangedCameraEventArgs(ReferenceHub hub, Scp079Camera camera) { - Player = Player.Get(player); + Player = Player.Get(hub); Camera = Camera.Get(camera); } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079ChangingCameraEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079ChangingCameraEventArgs.cs index b6f14833..eab7b391 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079ChangingCameraEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079ChangingCameraEventArgs.cs @@ -13,11 +13,11 @@ public class Scp079ChangingCameraEventArgs : EventArgs, IPlayerEvent, ICameraEve /// <summary> /// Initializes a new instance of the <see cref="Scp079ChangingCameraEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-079 player instance.</param> + /// <param name="hub">The SCP-079 player instance.</param> /// <param name="camera">The affected camera instance.</param> - public Scp079ChangingCameraEventArgs(ReferenceHub player, Scp079Camera camera) + public Scp079ChangingCameraEventArgs(ReferenceHub hub, Scp079Camera camera) { - Player = Player.Get(player); + Player = Player.Get(hub); Camera = Camera.Get(camera); IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079GainedExperienceEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079GainedExperienceEventArgs.cs index bfcfe624..9ccfaaf4 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079GainedExperienceEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079GainedExperienceEventArgs.cs @@ -15,13 +15,13 @@ public class Scp079GainedExperienceEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="Scp079GainedExperienceEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-079 player instance.</param> + /// <param name="hub">The SCP-079 player instance.</param> /// <param name="amount">The amount of experience gained.</param> /// <param name="reason">The reason of experience gain shown in HUD.</param> /// <param name = "subject" > The optional subject of the notification, used as replacement to display which class has been terminated</param> - public Scp079GainedExperienceEventArgs(ReferenceHub player, float amount, Scp079HudTranslation reason, RoleTypeId subject) + public Scp079GainedExperienceEventArgs(ReferenceHub hub, float amount, Scp079HudTranslation reason, RoleTypeId subject) { - Player = Player.Get(player); + Player = Player.Get(hub); Amount = amount; Reason = reason; Subject = subject; diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079GainingExperienceEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079GainingExperienceEventArgs.cs index 75e26a99..c412a5fd 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079GainingExperienceEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079GainingExperienceEventArgs.cs @@ -14,13 +14,13 @@ public class Scp079GainingExperienceEventArgs : EventArgs, IPlayerEvent, ICancel /// <summary> /// Initializes a new instance of the <see cref="Scp079GainingExperienceEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-079 player instance.</param> + /// <param name="hub">The SCP-079 player instance.</param> /// <param name="amount">The amount of experience that is going to be gained.</param> /// <param name="reason">The reason of experience gain that is going to be shown in HUD.</param> /// <param name="subject">The optional subject of the notification, used as replacement to display which class has been terminated</param> - public Scp079GainingExperienceEventArgs(ReferenceHub player, float amount, Scp079HudTranslation reason, RoleTypeId subject) + public Scp079GainingExperienceEventArgs(ReferenceHub hub, float amount, Scp079HudTranslation reason, RoleTypeId subject) { - Player = Player.Get(player); + Player = Player.Get(hub); Amount = amount; Reason = reason; Subject = subject; diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079LeveledUpEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079LeveledUpEventArgs.cs index 2dfabc9a..c7611315 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079LeveledUpEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079LeveledUpEventArgs.cs @@ -12,11 +12,11 @@ public class Scp079LeveledUpEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="Scp079LeveledUpEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-079 player instance.</param> + /// <param name="hub">The SCP-079 player instance.</param> /// <param name="tier">The new SCP-079's tier.</param> - public Scp079LeveledUpEventArgs(ReferenceHub player, int tier) + public Scp079LeveledUpEventArgs(ReferenceHub hub, int tier) { - Player = Player.Get(player); + Player = Player.Get(hub); Tier = tier; } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079LevelingUpEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079LevelingUpEventArgs.cs index 704f5dd1..12988e42 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079LevelingUpEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079LevelingUpEventArgs.cs @@ -12,11 +12,11 @@ public class Scp079LevelingUpEventArgs : EventArgs, IPlayerEvent, ICancellableEv /// <summary> /// Initializes a new instance of the <see cref="Scp079LevelingUpEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-079 player instance.</param> + /// <param name="hub">The SCP-079 player instance.</param> /// <param name="tier">The new SCP-079's tier.</param> - public Scp079LevelingUpEventArgs(ReferenceHub player, int tier) + public Scp079LevelingUpEventArgs(ReferenceHub hub, int tier) { - Player = Player.Get(player); + Player = Player.Get(hub); Tier = tier; IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079LockedDoorEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079LockedDoorEventArgs.cs index 112e5afe..de58aa72 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079LockedDoorEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079LockedDoorEventArgs.cs @@ -13,11 +13,11 @@ public class Scp079LockedDoorEventArgs : EventArgs, IPlayerEvent, IDoorEvent /// <summary> /// Initializes a new instance of the <see cref="Scp079LockedDoorEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-079 player instance.</param> + /// <param name="hub">The SCP-079 player instance.</param> /// <param name="door">The affected door instance.</param> - public Scp079LockedDoorEventArgs(ReferenceHub player, DoorVariant door) + public Scp079LockedDoorEventArgs(ReferenceHub hub, DoorVariant door) { - Player = Player.Get(player); + Player = Player.Get(hub); Door = Door.Get(door); } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079LockedDownRoomEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079LockedDownRoomEventArgs.cs index 91279f7f..fbe90084 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079LockedDownRoomEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079LockedDownRoomEventArgs.cs @@ -13,11 +13,11 @@ public class Scp079LockedDownRoomEventArgs : EventArgs, IPlayerEvent, IRoomEvent /// <summary> /// Initializes a new instance of the <see cref="Scp079LockedDoorEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-079 player instance.</param> + /// <param name="hub">The SCP-079 player instance.</param> /// <param name="room">The affected room instance.</param> - public Scp079LockedDownRoomEventArgs(ReferenceHub player, RoomIdentifier room) + public Scp079LockedDownRoomEventArgs(ReferenceHub hub, RoomIdentifier room) { - Player = Player.Get(player); + Player = Player.Get(hub); Room = Room.Get(room); } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079LockingDoorEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079LockingDoorEventArgs.cs index ee1e7802..28a7a606 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079LockingDoorEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079LockingDoorEventArgs.cs @@ -13,11 +13,11 @@ public class Scp079LockingDoorEventArgs : EventArgs, IPlayerEvent, IDoorEvent, I /// <summary> /// Initializes a new instance of the <see cref="Scp079LockingDoorEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-079 player instance.</param> + /// <param name="hub">The SCP-079 player instance.</param> /// <param name="door">The affected door instance.</param> - public Scp079LockingDoorEventArgs(ReferenceHub player, DoorVariant door) + public Scp079LockingDoorEventArgs(ReferenceHub hub, DoorVariant door) { - Player = Player.Get(player); + Player = Player.Get(hub); Door = Door.Get(door); IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079LockingDownRoomEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079LockingDownRoomEventArgs.cs index a0aaa940..2e507b83 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079LockingDownRoomEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079LockingDownRoomEventArgs.cs @@ -13,11 +13,11 @@ public class Scp079LockingDownRoomEventArgs : EventArgs, IPlayerEvent, IRoomEven /// <summary> /// Initializes a new instance of the <see cref="Scp079LockingDownRoomEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-079 player instance.</param> + /// <param name="hub">The SCP-079 player instance.</param> /// <param name="room">The affected room instance.</param> - public Scp079LockingDownRoomEventArgs(ReferenceHub player, RoomIdentifier room) + public Scp079LockingDownRoomEventArgs(ReferenceHub hub, RoomIdentifier room) { - Player = Player.Get(player); + Player = Player.Get(hub); Room = Room.Get(room); IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079RecontainedEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079RecontainedEventArgs.cs index d519be81..7f542f49 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079RecontainedEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079RecontainedEventArgs.cs @@ -12,11 +12,11 @@ public class Scp079RecontainedEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="Scp079RecontainedEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-079 player instance.</param> + /// <param name="hub">The SCP-079 player instance.</param> /// <param name="activator">The player who activated the recontainment procedure.</param> - public Scp079RecontainedEventArgs(ReferenceHub player, ReferenceHub? activator) + public Scp079RecontainedEventArgs(ReferenceHub hub, ReferenceHub? activator) { - Player = Player.Get(player); + Player = Player.Get(hub); Activator = Player.Get(activator); } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079RecontainingEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079RecontainingEventArgs.cs index 9557b55d..e9bb3311 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079RecontainingEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079RecontainingEventArgs.cs @@ -12,12 +12,12 @@ public class Scp079RecontainingEventArgs : EventArgs, IPlayerEvent, ICancellable /// <summary> /// Initializes a new instance of the <see cref="Scp079RecontainingEventArgs"/> class. /// </summary> - /// <param name="player">THe SCP-079 player instance.</param> + /// <param name="hub">THe SCP-079 player instance.</param> /// <param name="activator">The player who activated the recontainment procedure.</param> - public Scp079RecontainingEventArgs(ReferenceHub player, ReferenceHub? activator) + public Scp079RecontainingEventArgs(ReferenceHub hub, ReferenceHub? activator) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Activator = Player.Get(activator); } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079UnlockedDoorEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079UnlockedDoorEventArgs.cs index ac2b2128..f6b6903e 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079UnlockedDoorEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079UnlockedDoorEventArgs.cs @@ -13,11 +13,11 @@ public class Scp079UnlockedDoorEventArgs : EventArgs, IPlayerEvent, IDoorEvent /// <summary> /// Initializes a new instance of the <see cref="Scp079UnlockedDoorEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-079 player instance.</param> + /// <param name="hub">The SCP-079 player instance.</param> /// <param name="door">The affected door instance.</param> - public Scp079UnlockedDoorEventArgs(ReferenceHub player, DoorVariant door) + public Scp079UnlockedDoorEventArgs(ReferenceHub hub, DoorVariant door) { - Player = Player.Get(player); + Player = Player.Get(hub); Door = Door.Get(door); } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079UnlockingDoorEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079UnlockingDoorEventArgs.cs index 9d55ab03..c6f00e44 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079UnlockingDoorEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079UnlockingDoorEventArgs.cs @@ -13,11 +13,11 @@ public class Scp079UnlockingDoorEventArgs : EventArgs, IPlayerEvent, IDoorEvent, /// <summary> /// Initializes a new instance of the <see cref="Scp079UnlockingDoorEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-079 player instance.</param> + /// <param name="hub">The SCP-079 player instance.</param> /// <param name="door">The affected door instance.</param> - public Scp079UnlockingDoorEventArgs(ReferenceHub player, DoorVariant door) + public Scp079UnlockingDoorEventArgs(ReferenceHub hub, DoorVariant door) { - Player = Player.Get(player); + Player = Player.Get(hub); Door = Door.Get(door); IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079UsedTeslaEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079UsedTeslaEventArgs.cs index ff26e05d..4e181848 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079UsedTeslaEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079UsedTeslaEventArgs.cs @@ -12,11 +12,11 @@ public class Scp079UsedTeslaEventArgs : EventArgs, IPlayerEvent, ITeslaEvent /// <summary> /// Initializes a new instance of the <see cref="Scp079UsedTeslaEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-079 player instance.</param> + /// <param name="hub">The SCP-079 player instance.</param> /// <param name="tesla">The affected tesla instance.</param> - public Scp079UsedTeslaEventArgs(ReferenceHub player, TeslaGate tesla) + public Scp079UsedTeslaEventArgs(ReferenceHub hub, TeslaGate tesla) { - Player = Player.Get(player); + Player = Player.Get(hub); Tesla = Tesla.Get(tesla); } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079UsingTeslaEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079UsingTeslaEventArgs.cs index fc4da733..41c31b69 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079UsingTeslaEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079UsingTeslaEventArgs.cs @@ -12,11 +12,11 @@ public class Scp079UsingTeslaEventArgs : EventArgs, IPlayerEvent, ITeslaEvent, I /// <summary> /// Initializes a new instance of the <see cref="Scp079UsingTeslaEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-079 player instance.</param> + /// <param name="hub">The SCP-079 player instance.</param> /// <param name="tesla">The affected tesla instance.</param> - public Scp079UsingTeslaEventArgs(ReferenceHub player, TeslaGate tesla) + public Scp079UsingTeslaEventArgs(ReferenceHub hub, TeslaGate tesla) { - Player = Player.Get(player); + Player = Player.Get(hub); Tesla = Tesla.Get(tesla); IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp096Events/Scp096AddedTargetEventArgs.cs b/LabApi/Events/Arguments/Scp096Events/Scp096AddedTargetEventArgs.cs index b90adbe1..fbd0beab 100644 --- a/LabApi/Events/Arguments/Scp096Events/Scp096AddedTargetEventArgs.cs +++ b/LabApi/Events/Arguments/Scp096Events/Scp096AddedTargetEventArgs.cs @@ -12,12 +12,12 @@ public class Scp096AddedTargetEventArgs : EventArgs, IPlayerEvent, ITargetEvent /// <summary> /// Initializes a new instance of the <see cref="Scp096AddedTargetEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-096 player instance.</param> + /// <param name="hub">The SCP-096 player instance.</param> /// <param name="target">The target player instance.</param> /// <param name="wasLooking">Whether the target looked at SCP-096.</param> - public Scp096AddedTargetEventArgs(ReferenceHub player, ReferenceHub target, bool wasLooking) + public Scp096AddedTargetEventArgs(ReferenceHub hub, ReferenceHub target, bool wasLooking) { - Player = Player.Get(player); + Player = Player.Get(hub); Target = Player.Get(target); WasLooking = wasLooking; } diff --git a/LabApi/Events/Arguments/Scp096Events/Scp096AddingTargetEventArgs.cs b/LabApi/Events/Arguments/Scp096Events/Scp096AddingTargetEventArgs.cs index afc74b28..38f81a47 100644 --- a/LabApi/Events/Arguments/Scp096Events/Scp096AddingTargetEventArgs.cs +++ b/LabApi/Events/Arguments/Scp096Events/Scp096AddingTargetEventArgs.cs @@ -12,12 +12,12 @@ public class Scp096AddingTargetEventArgs : EventArgs, IPlayerEvent, ITargetEvent /// <summary> /// Initializes a new instance of the <see cref="Scp096AddingTargetEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-096 player instance.</param> + /// <param name="hub">The SCP-096 player instance.</param> /// <param name="target">The target player instance.</param> /// <param name="wasLooking">Whether the target looked at SCP-096.</param> - public Scp096AddingTargetEventArgs(ReferenceHub player, ReferenceHub target, bool wasLooking) + public Scp096AddingTargetEventArgs(ReferenceHub hub, ReferenceHub target, bool wasLooking) { - Player = Player.Get(player); + Player = Player.Get(hub); Target = Player.Get(target); WasLooking = wasLooking; IsAllowed = true; diff --git a/LabApi/Events/Arguments/Scp096Events/Scp096ChangedStateEventArgs.cs b/LabApi/Events/Arguments/Scp096Events/Scp096ChangedStateEventArgs.cs index ac457100..eaa7c5f9 100644 --- a/LabApi/Events/Arguments/Scp096Events/Scp096ChangedStateEventArgs.cs +++ b/LabApi/Events/Arguments/Scp096Events/Scp096ChangedStateEventArgs.cs @@ -13,11 +13,11 @@ public class Scp096ChangedStateEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="Scp096ChangedStateEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-096 player instance.</param> + /// <param name="hub">The SCP-096 player instance.</param> /// <param name="state">The SCP-096's new rage state.</param> - public Scp096ChangedStateEventArgs(ReferenceHub player, Scp096RageState state) + public Scp096ChangedStateEventArgs(ReferenceHub hub, Scp096RageState state) { - Player = Player.Get(player); + Player = Player.Get(hub); State = state; } diff --git a/LabApi/Events/Arguments/Scp096Events/Scp096ChangingStateEventArgs.cs b/LabApi/Events/Arguments/Scp096Events/Scp096ChangingStateEventArgs.cs index d0e984f2..00304ecd 100644 --- a/LabApi/Events/Arguments/Scp096Events/Scp096ChangingStateEventArgs.cs +++ b/LabApi/Events/Arguments/Scp096Events/Scp096ChangingStateEventArgs.cs @@ -13,11 +13,11 @@ public class Scp096ChangingStateEventArgs : EventArgs, IPlayerEvent, ICancellabl /// <summary> /// Initializes a new instance of the <see cref="Scp096ChangingStateEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-096 player instance.</param> + /// <param name="hub">The SCP-096 player instance.</param> /// <param name="state">The SCP-096's new rage state.</param> - public Scp096ChangingStateEventArgs(ReferenceHub player, Scp096RageState state) + public Scp096ChangingStateEventArgs(ReferenceHub hub, Scp096RageState state) { - Player = Player.Get(player); + Player = Player.Get(hub); State = state; IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp096Events/Scp096ChargedEventArgs.cs b/LabApi/Events/Arguments/Scp096Events/Scp096ChargedEventArgs.cs index 013ba81c..88affc05 100644 --- a/LabApi/Events/Arguments/Scp096Events/Scp096ChargedEventArgs.cs +++ b/LabApi/Events/Arguments/Scp096Events/Scp096ChargedEventArgs.cs @@ -12,10 +12,10 @@ public class Scp096ChargedEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="Scp096ChargedEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-096 player instance.</param> - public Scp096ChargedEventArgs(ReferenceHub player) + /// <param name="hub">The SCP-096 player instance.</param> + public Scp096ChargedEventArgs(ReferenceHub hub) { - Player = Player.Get(player); + Player = Player.Get(hub); } /// <summary> diff --git a/LabApi/Events/Arguments/Scp096Events/Scp096ChargingEventArgs.cs b/LabApi/Events/Arguments/Scp096Events/Scp096ChargingEventArgs.cs index b5849b11..1fd348da 100644 --- a/LabApi/Events/Arguments/Scp096Events/Scp096ChargingEventArgs.cs +++ b/LabApi/Events/Arguments/Scp096Events/Scp096ChargingEventArgs.cs @@ -12,10 +12,10 @@ public class Scp096ChargingEventArgs : EventArgs, IPlayerEvent, ICancellableEven /// <summary> /// Initializes a new instance of the <see cref="Scp096ChargingEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-096 player instance.</param> - public Scp096ChargingEventArgs(ReferenceHub player) + /// <param name="hub">The SCP-096 player instance.</param> + public Scp096ChargingEventArgs(ReferenceHub hub) { - Player = Player.Get(player); + Player = Player.Get(hub); IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp096Events/Scp096EnragedEventArgs.cs b/LabApi/Events/Arguments/Scp096Events/Scp096EnragedEventArgs.cs index 330472a5..19709ebf 100644 --- a/LabApi/Events/Arguments/Scp096Events/Scp096EnragedEventArgs.cs +++ b/LabApi/Events/Arguments/Scp096Events/Scp096EnragedEventArgs.cs @@ -12,11 +12,11 @@ public class Scp096EnragedEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="Scp096ChargingEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-096 player instance.</param> + /// <param name="hub">The SCP-096 player instance.</param> /// <param name="initialDuration">The initial duration of the rage.</param> - public Scp096EnragedEventArgs(ReferenceHub player, float initialDuration) + public Scp096EnragedEventArgs(ReferenceHub hub, float initialDuration) { - Player = Player.Get(player); + Player = Player.Get(hub); InitialDuration = initialDuration; } diff --git a/LabApi/Events/Arguments/Scp096Events/Scp096EnragingEventArgs.cs b/LabApi/Events/Arguments/Scp096Events/Scp096EnragingEventArgs.cs index 21ff5fce..8b51af12 100644 --- a/LabApi/Events/Arguments/Scp096Events/Scp096EnragingEventArgs.cs +++ b/LabApi/Events/Arguments/Scp096Events/Scp096EnragingEventArgs.cs @@ -12,11 +12,11 @@ public class Scp096EnragingEventArgs : EventArgs, IPlayerEvent, ICancellableEven /// <summary> /// Initializes a new instance of the <see cref="Scp096EnragingEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-096 player instance.</param> + /// <param name="hub">The SCP-096 player instance.</param> /// <param name="initialDuration">The initial duration of the rage.</param> - public Scp096EnragingEventArgs(ReferenceHub player, float initialDuration) + public Scp096EnragingEventArgs(ReferenceHub hub, float initialDuration) { - Player = Player.Get(player); + Player = Player.Get(hub); InitialDuration = initialDuration; IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp096Events/Scp096PriedGateEventArgs.cs b/LabApi/Events/Arguments/Scp096Events/Scp096PriedGateEventArgs.cs index c7315e6d..f7c5fd06 100644 --- a/LabApi/Events/Arguments/Scp096Events/Scp096PriedGateEventArgs.cs +++ b/LabApi/Events/Arguments/Scp096Events/Scp096PriedGateEventArgs.cs @@ -13,11 +13,11 @@ public class Scp096PriedGateEventArgs : EventArgs, IPlayerEvent, IGateEvent /// <summary> /// Initializes a new instance of the <see cref="Scp096PriedGateEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-096 player instance.</param> + /// <param name="hub">The SCP-096 player instance.</param> /// <param name="gate">The affected pryable door instance.</param> - public Scp096PriedGateEventArgs(ReferenceHub player, PryableDoor gate) + public Scp096PriedGateEventArgs(ReferenceHub hub, PryableDoor gate) { - Player = Player.Get(player); + Player = Player.Get(hub); Gate = Gate.Get(gate); } diff --git a/LabApi/Events/Arguments/Scp096Events/Scp096PryingGateEventArgs.cs b/LabApi/Events/Arguments/Scp096Events/Scp096PryingGateEventArgs.cs index aab475f7..2e225423 100644 --- a/LabApi/Events/Arguments/Scp096Events/Scp096PryingGateEventArgs.cs +++ b/LabApi/Events/Arguments/Scp096Events/Scp096PryingGateEventArgs.cs @@ -13,11 +13,11 @@ public class Scp096PryingGateEventArgs : EventArgs, IPlayerEvent, IGateEvent, IC /// <summary> /// Initializes a new instance of the <see cref="Scp096PryingGateEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-096 player instance.</param> + /// <param name="hub">The SCP-096 player instance.</param> /// <param name="gate">The affected pryable door instance.</param> - public Scp096PryingGateEventArgs(ReferenceHub player, PryableDoor gate) + public Scp096PryingGateEventArgs(ReferenceHub hub, PryableDoor gate) { - Player = Player.Get(player); + Player = Player.Get(hub); Gate = Gate.Get(gate); IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp096Events/Scp096StartCryingEventArgs.cs b/LabApi/Events/Arguments/Scp096Events/Scp096StartCryingEventArgs.cs index 8b50efaf..82580883 100644 --- a/LabApi/Events/Arguments/Scp096Events/Scp096StartCryingEventArgs.cs +++ b/LabApi/Events/Arguments/Scp096Events/Scp096StartCryingEventArgs.cs @@ -12,10 +12,10 @@ public class Scp096StartCryingEventArgs : EventArgs, IPlayerEvent, ICancellableE /// <summary> /// Initializes a new instance of the <see cref="Scp096StartCryingEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-096 player instance.</param> - public Scp096StartCryingEventArgs(ReferenceHub player) + /// <param name="hub">The SCP-096 player instance.</param> + public Scp096StartCryingEventArgs(ReferenceHub hub) { - Player = Player.Get(player); + Player = Player.Get(hub); IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp096Events/Scp096StartedCryingEventArgs.cs b/LabApi/Events/Arguments/Scp096Events/Scp096StartedCryingEventArgs.cs index e1dcede8..69aedd7a 100644 --- a/LabApi/Events/Arguments/Scp096Events/Scp096StartedCryingEventArgs.cs +++ b/LabApi/Events/Arguments/Scp096Events/Scp096StartedCryingEventArgs.cs @@ -12,10 +12,10 @@ public class Scp096StartedCryingEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="Scp096StartedCryingEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-096 player instance.</param> - public Scp096StartedCryingEventArgs(ReferenceHub player) + /// <param name="hub">The SCP-096 player instance.</param> + public Scp096StartedCryingEventArgs(ReferenceHub hub) { - Player = Player.Get(player); + Player = Player.Get(hub); } /// <summary> diff --git a/LabApi/Events/Arguments/Scp096Events/Scp096TriedNotToCryEventArgs.cs b/LabApi/Events/Arguments/Scp096Events/Scp096TriedNotToCryEventArgs.cs index 22fe4195..76b72dee 100644 --- a/LabApi/Events/Arguments/Scp096Events/Scp096TriedNotToCryEventArgs.cs +++ b/LabApi/Events/Arguments/Scp096Events/Scp096TriedNotToCryEventArgs.cs @@ -12,10 +12,10 @@ public class Scp096TriedNotToCryEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="Scp096TriedNotToCryEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-096 player instance.</param> - public Scp096TriedNotToCryEventArgs(ReferenceHub player) + /// <param name="hub">The SCP-096 player instance.</param> + public Scp096TriedNotToCryEventArgs(ReferenceHub hub) { - Player = Player.Get(player); + Player = Player.Get(hub); } /// <summary> diff --git a/LabApi/Events/Arguments/Scp096Events/Scp096TryingNotToCryEventArgs.cs b/LabApi/Events/Arguments/Scp096Events/Scp096TryingNotToCryEventArgs.cs index 7fb220b1..73428db7 100644 --- a/LabApi/Events/Arguments/Scp096Events/Scp096TryingNotToCryEventArgs.cs +++ b/LabApi/Events/Arguments/Scp096Events/Scp096TryingNotToCryEventArgs.cs @@ -12,10 +12,10 @@ public class Scp096TryingNotToCryEventArgs : EventArgs, IPlayerEvent, ICancellab /// <summary> /// Initializes a new instance of the <see cref="Scp096TryingNotToCryEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-096 player instance.</param> - public Scp096TryingNotToCryEventArgs(ReferenceHub player) + /// <param name="hub">The SCP-096 player instance.</param> + public Scp096TryingNotToCryEventArgs(ReferenceHub hub) { - Player = Player.Get(player); + Player = Player.Get(hub); IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp106Events/Scp106ChangedStalkModeEventArgs.cs b/LabApi/Events/Arguments/Scp106Events/Scp106ChangedStalkModeEventArgs.cs index 0fdca5de..3330fc25 100644 --- a/LabApi/Events/Arguments/Scp106Events/Scp106ChangedStalkModeEventArgs.cs +++ b/LabApi/Events/Arguments/Scp106Events/Scp106ChangedStalkModeEventArgs.cs @@ -12,11 +12,11 @@ public class Scp106ChangedStalkModeEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="Scp106ChangedStalkModeEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-106 player instance.</param> + /// <param name="hub">The SCP-106 player instance.</param> /// <param name="active">Whether the ability was activated or deactivated.</param> - public Scp106ChangedStalkModeEventArgs(ReferenceHub player, bool active) + public Scp106ChangedStalkModeEventArgs(ReferenceHub hub, bool active) { - Player = Player.Get(player); + Player = Player.Get(hub); IsStalkActive = active; } diff --git a/LabApi/Events/Arguments/Scp106Events/Scp106ChangedSubmersionStatusEventArgs.cs b/LabApi/Events/Arguments/Scp106Events/Scp106ChangedSubmersionStatusEventArgs.cs index d2645590..0bceb9b2 100644 --- a/LabApi/Events/Arguments/Scp106Events/Scp106ChangedSubmersionStatusEventArgs.cs +++ b/LabApi/Events/Arguments/Scp106Events/Scp106ChangedSubmersionStatusEventArgs.cs @@ -12,11 +12,11 @@ public class Scp106ChangedSubmersionStatusEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="Scp106ChangedSubmersionStatusEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-106 player instance.</param> + /// <param name="hub">The SCP-106 player instance.</param> /// <param name="isSubmerging">Whether the SCP-106 is submerging or emerging.</param> - public Scp106ChangedSubmersionStatusEventArgs(ReferenceHub player, bool isSubmerging) + public Scp106ChangedSubmersionStatusEventArgs(ReferenceHub hub, bool isSubmerging) { - Player = Player.Get(player); + Player = Player.Get(hub); IsSubmerging = isSubmerging; } diff --git a/LabApi/Events/Arguments/Scp106Events/Scp106ChangedVigorEventArgs.cs b/LabApi/Events/Arguments/Scp106Events/Scp106ChangedVigorEventArgs.cs index a94ed84b..2da64f8b 100644 --- a/LabApi/Events/Arguments/Scp106Events/Scp106ChangedVigorEventArgs.cs +++ b/LabApi/Events/Arguments/Scp106Events/Scp106ChangedVigorEventArgs.cs @@ -12,12 +12,12 @@ public class Scp106ChangedVigorEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="Scp106ChangedVigorEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-106 player instance.</param> + /// <param name="hub">The SCP-106 player instance.</param> /// <param name="oldVigor">The previous vigor value.</param> /// <param name="newVigor">The new vigor value.</param> - public Scp106ChangedVigorEventArgs(ReferenceHub player, float oldVigor, float newVigor) + public Scp106ChangedVigorEventArgs(ReferenceHub hub, float oldVigor, float newVigor) { - Player = Player.Get(player); + Player = Player.Get(hub); OldValue = oldVigor; Value = newVigor; } diff --git a/LabApi/Events/Arguments/Scp106Events/Scp106ChangingStalkModeEventArgs.cs b/LabApi/Events/Arguments/Scp106Events/Scp106ChangingStalkModeEventArgs.cs index dbf5be08..a6f07b91 100644 --- a/LabApi/Events/Arguments/Scp106Events/Scp106ChangingStalkModeEventArgs.cs +++ b/LabApi/Events/Arguments/Scp106Events/Scp106ChangingStalkModeEventArgs.cs @@ -12,12 +12,12 @@ public class Scp106ChangingStalkModeEventArgs : EventArgs, IPlayerEvent, ICancel /// <summary> /// Initializes a new instance of the <see cref="Scp106ChangingStalkModeEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-106 player instance.</param> + /// <param name="hub">The SCP-106 player instance.</param> /// <param name="active">Whether the ability is being activated or deactivated.</param> - public Scp106ChangingStalkModeEventArgs(ReferenceHub player, bool active) + public Scp106ChangingStalkModeEventArgs(ReferenceHub hub, bool active) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); IsStalkActive = active; } diff --git a/LabApi/Events/Arguments/Scp106Events/Scp106ChangingSubmersionStatusEventArgs.cs b/LabApi/Events/Arguments/Scp106Events/Scp106ChangingSubmersionStatusEventArgs.cs index ad9b800f..9fbc8b97 100644 --- a/LabApi/Events/Arguments/Scp106Events/Scp106ChangingSubmersionStatusEventArgs.cs +++ b/LabApi/Events/Arguments/Scp106Events/Scp106ChangingSubmersionStatusEventArgs.cs @@ -12,11 +12,11 @@ public class Scp106ChangingSubmersionStatusEventArgs : EventArgs, IPlayerEvent, /// <summary> /// Initializes a new instance of the <see cref="Scp106ChangingSubmersionStatusEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-106 player instance.</param> + /// <param name="hub">The SCP-106 player instance.</param> /// <param name="isSubmerging">Whether the SCP-106 is submerging or emerging.</param> - public Scp106ChangingSubmersionStatusEventArgs(ReferenceHub player, bool isSubmerging) + public Scp106ChangingSubmersionStatusEventArgs(ReferenceHub hub, bool isSubmerging) { - Player = Player.Get(player); + Player = Player.Get(hub); IsSubmerging = isSubmerging; IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp106Events/Scp106ChangingVigorEventArgs.cs b/LabApi/Events/Arguments/Scp106Events/Scp106ChangingVigorEventArgs.cs index bc174da0..9bc4bafe 100644 --- a/LabApi/Events/Arguments/Scp106Events/Scp106ChangingVigorEventArgs.cs +++ b/LabApi/Events/Arguments/Scp106Events/Scp106ChangingVigorEventArgs.cs @@ -12,12 +12,12 @@ public class Scp106ChangingVigorEventArgs : EventArgs, IPlayerEvent, ICancellabl /// <summary> /// Initializes a new instance of the <see cref="Scp106ChangingVigorEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-106 player instance.</param> + /// <param name="hub">The SCP-106 player instance.</param> /// <param name="oldValue">The previous vigor value.</param> /// <param name="value">The new vigor value.</param> - public Scp106ChangingVigorEventArgs(ReferenceHub player, float oldValue, float value) + public Scp106ChangingVigorEventArgs(ReferenceHub hub, float oldValue, float value) { - Player = Player.Get(player); + Player = Player.Get(hub); OldValue = oldValue; Value = value; IsAllowed = true; diff --git a/LabApi/Events/Arguments/Scp106Events/Scp106TeleportedPlayerEvent.cs b/LabApi/Events/Arguments/Scp106Events/Scp106TeleportedPlayerEvent.cs index a8e2f397..9e31aa3d 100644 --- a/LabApi/Events/Arguments/Scp106Events/Scp106TeleportedPlayerEvent.cs +++ b/LabApi/Events/Arguments/Scp106Events/Scp106TeleportedPlayerEvent.cs @@ -12,11 +12,11 @@ public class Scp106TeleportedPlayerEvent : EventArgs, IPlayerEvent, ITargetEvent /// <summary> /// Initializes a new instance of the <see cref="Scp106TeleportedPlayerEvent"/> class. /// </summary> - /// <param name="player">The SCP-106 player instance.</param> + /// <param name="hub">The SCP-106 player instance.</param> /// <param name="target">The player that was teleported.</param> - public Scp106TeleportedPlayerEvent(ReferenceHub player, ReferenceHub target) + public Scp106TeleportedPlayerEvent(ReferenceHub hub, ReferenceHub target) { - Player = Player.Get(player); + Player = Player.Get(hub); Target = Player.Get(target); } diff --git a/LabApi/Events/Arguments/Scp106Events/Scp106TeleportingPlayerEvent.cs b/LabApi/Events/Arguments/Scp106Events/Scp106TeleportingPlayerEvent.cs index 29de2333..8d0fcbf6 100644 --- a/LabApi/Events/Arguments/Scp106Events/Scp106TeleportingPlayerEvent.cs +++ b/LabApi/Events/Arguments/Scp106Events/Scp106TeleportingPlayerEvent.cs @@ -12,12 +12,12 @@ public class Scp106TeleportingPlayerEvent : EventArgs, IPlayerEvent, ITargetEven /// <summary> /// Initializes a new instance of the <see cref="Scp106TeleportingPlayerEvent"/> class. /// </summary> - /// <param name="player">The SCP-106 player instance.</param> + /// <param name="hub">The SCP-106 player instance.</param> /// <param name="target">The player that is being teleported.</param> - public Scp106TeleportingPlayerEvent(ReferenceHub player, ReferenceHub target) + public Scp106TeleportingPlayerEvent(ReferenceHub hub, ReferenceHub target) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Target = Player.Get(target); } diff --git a/LabApi/Events/Arguments/Scp106Events/Scp106UsedHunterAtlasEventArgs.cs b/LabApi/Events/Arguments/Scp106Events/Scp106UsedHunterAtlasEventArgs.cs index 7fac8b7c..ee7d0ec7 100644 --- a/LabApi/Events/Arguments/Scp106Events/Scp106UsedHunterAtlasEventArgs.cs +++ b/LabApi/Events/Arguments/Scp106Events/Scp106UsedHunterAtlasEventArgs.cs @@ -13,11 +13,11 @@ public class Scp106UsedHunterAtlasEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="Scp106UsedHunterAtlasEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-106 player instance.</param> + /// <param name="hub">The SCP-106 player instance.</param> /// <param name="originalPosition">The original position.</param> - public Scp106UsedHunterAtlasEventArgs(ReferenceHub player, Vector3 originalPosition) + public Scp106UsedHunterAtlasEventArgs(ReferenceHub hub, Vector3 originalPosition) { - Player = Player.Get(player); + Player = Player.Get(hub); OriginalPosition = originalPosition; } diff --git a/LabApi/Events/Arguments/Scp106Events/Scp106UsingHunterAtlasEventArgs.cs b/LabApi/Events/Arguments/Scp106Events/Scp106UsingHunterAtlasEventArgs.cs index 294699da..8b821b68 100644 --- a/LabApi/Events/Arguments/Scp106Events/Scp106UsingHunterAtlasEventArgs.cs +++ b/LabApi/Events/Arguments/Scp106Events/Scp106UsingHunterAtlasEventArgs.cs @@ -13,11 +13,11 @@ public class Scp106UsingHunterAtlasEventArgs : EventArgs, IPlayerEvent, ICancell /// <summary> /// Initializes a new instance of the <see cref="Scp106UsingHunterAtlasEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-106 player instance.</param> + /// <param name="hub">The SCP-106 player instance.</param> /// <param name="destinationPosition">The destination position.</param> - public Scp106UsingHunterAtlasEventArgs(ReferenceHub player, Vector3 destinationPosition) + public Scp106UsingHunterAtlasEventArgs(ReferenceHub hub, Vector3 destinationPosition) { - Player = Player.Get(player); + Player = Player.Get(hub); DestinationPosition = destinationPosition; IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp127Events/Scp127GainExperienceEventArgs.cs b/LabApi/Events/Arguments/Scp127Events/Scp127GainExperienceEventArgs.cs new file mode 100644 index 00000000..2e15869f --- /dev/null +++ b/LabApi/Events/Arguments/Scp127Events/Scp127GainExperienceEventArgs.cs @@ -0,0 +1,34 @@ +using InventorySystem.Items.Firearms; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Events.Arguments.Scp127Events; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp127Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp127Events.GainExperience"/> event. +/// </summary> +public class Scp127GainExperienceEventArgs : EventArgs, IScp127ItemEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp127GainExperienceEventArgs"/> class. + /// </summary> + /// <param name="weapon">The Scp-127 firearm.</param> + /// <param name="exp">The gained experience.</param> + public Scp127GainExperienceEventArgs(Firearm weapon, float exp) + { + Scp127Item = (Scp127Firearm)FirearmItem.Get(weapon); + ExperienceGain = exp; + } + + /// <summary> + /// Gets the SCP-127 firearm. + /// </summary> + public Scp127Firearm Scp127Item { get; } + + /// <summary> + /// Gets the amount of experience the SCP-127 gained. + /// </summary> + public float ExperienceGain { get; } +} diff --git a/LabApi/Events/Arguments/Scp127Events/Scp127GainingExperienceEventArgs.cs b/LabApi/Events/Arguments/Scp127Events/Scp127GainingExperienceEventArgs.cs new file mode 100644 index 00000000..2bec197f --- /dev/null +++ b/LabApi/Events/Arguments/Scp127Events/Scp127GainingExperienceEventArgs.cs @@ -0,0 +1,37 @@ +using InventorySystem.Items.Firearms; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp127Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp127Events.GainingExperience"/> event. +/// </summary> +public class Scp127GainingExperienceEventArgs : EventArgs, IScp127ItemEvent, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp127GainingExperienceEventArgs"/> class. + /// </summary> + /// <param name="weapon">The Scp-127 firearm.</param> + /// <param name="exp">The experience to be gained.</param> + public Scp127GainingExperienceEventArgs(Firearm weapon, float exp) + { + Scp127Item = (Scp127Firearm)FirearmItem.Get(weapon); + ExperienceGain = exp; + IsAllowed = true; + } + + /// <summary> + /// Gets the SCP-127 firearm. + /// </summary> + public Scp127Firearm Scp127Item { get; } + + /// <summary> + /// Gets or sets the amount of experience the SCP-127 will gain. + /// </summary> + public float ExperienceGain { get; set; } + + /// <inheritdoc/> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/Scp127Events/Scp127LevelUpEventArgs.cs b/LabApi/Events/Arguments/Scp127Events/Scp127LevelUpEventArgs.cs new file mode 100644 index 00000000..eb088b54 --- /dev/null +++ b/LabApi/Events/Arguments/Scp127Events/Scp127LevelUpEventArgs.cs @@ -0,0 +1,34 @@ +using InventorySystem.Items.Firearms.Modules.Scp127; +using InventorySystem.Items.Firearms; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp127Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp127Events.LevelUp"/> event. +/// </summary> +public class Scp127LevelUpEventArgs : EventArgs, IScp127ItemEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp127LevelUpEventArgs"/> class. + /// </summary> + /// <param name="weapon">The Scp-127 firearm.</param> + /// <param name="tier">The new tier.</param> + public Scp127LevelUpEventArgs(Firearm weapon, Scp127Tier tier) + { + Scp127Item = (Scp127Firearm)FirearmItem.Get(weapon); + Tier = tier; + } + + /// <summary> + /// Gets the SCP-127 firearm. + /// </summary> + public Scp127Firearm Scp127Item { get; } + + /// <summary> + /// Gets the new tier of SCP-127. + /// </summary> + public Scp127Tier Tier { get; } +} diff --git a/LabApi/Events/Arguments/Scp127Events/Scp127LevellingUpEventArgs.cs b/LabApi/Events/Arguments/Scp127Events/Scp127LevellingUpEventArgs.cs new file mode 100644 index 00000000..1f0ef45b --- /dev/null +++ b/LabApi/Events/Arguments/Scp127Events/Scp127LevellingUpEventArgs.cs @@ -0,0 +1,38 @@ +using InventorySystem.Items.Firearms; +using InventorySystem.Items.Firearms.Modules.Scp127; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp127Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp127Events.LevellingUp"/> event. +/// </summary> +public class Scp127LevellingUpEventArgs : EventArgs, IScp127ItemEvent, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp127LevellingUpEventArgs"/> class. + /// </summary> + /// <param name="weapon">The Scp-127 firearm.</param> + /// <param name="tier">The new tier.</param> + public Scp127LevellingUpEventArgs(Firearm weapon, Scp127Tier tier) + { + Scp127Item = (Scp127Firearm)FirearmItem.Get(weapon); + Tier = tier; + IsAllowed = true; + } + + /// <summary> + /// Gets the SCP-127 firearm. + /// </summary> + public Scp127Firearm Scp127Item { get; } + + /// <summary> + /// Gets the new tier of SCP-127.s + /// </summary> + public Scp127Tier Tier { get; } + + /// <inheritdoc/> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/Scp127Events/Scp127TalkedEventArgs.cs b/LabApi/Events/Arguments/Scp127Events/Scp127TalkedEventArgs.cs new file mode 100644 index 00000000..184e3712 --- /dev/null +++ b/LabApi/Events/Arguments/Scp127Events/Scp127TalkedEventArgs.cs @@ -0,0 +1,42 @@ +using InventorySystem.Items.Firearms.Modules.Scp127; +using InventorySystem.Items.Firearms; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using static InventorySystem.Items.Firearms.Modules.Scp127.Scp127VoiceTriggerBase; + +namespace LabApi.Events.Arguments.Scp127Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp127Events.Talked"/> event. +/// </summary> +public class Scp127TalkedEventArgs : EventArgs, IScp127ItemEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp127TalkingEventArgs"/> class. + /// </summary> + /// <param name="weapon">The Scp-127 firearm.</param> + /// <param name="voiceLine">The voiceline to be played.</param> + /// <param name="priority">The priority of the voiceline.</param> + public Scp127TalkedEventArgs(Firearm weapon, Scp127VoiceLinesTranslation voiceLine, VoiceLinePriority priority) + { + Scp127Item = (Scp127Firearm)FirearmItem.Get(weapon); + VoiceLine = voiceLine; + Priority = priority; + } + + /// <summary> + /// Gets the SCP-127 firearm. + /// </summary> + public Scp127Firearm Scp127Item { get; } + + /// <summary> + /// Gets the voiceline the SCP-127 played. + /// </summary> + public Scp127VoiceLinesTranslation VoiceLine { get; } + + /// <summary> + /// Gets the priority the voiceline has been played with. + /// </summary> + public VoiceLinePriority Priority { get; } +} diff --git a/LabApi/Events/Arguments/Scp127Events/Scp127TalkingEventArgs.cs b/LabApi/Events/Arguments/Scp127Events/Scp127TalkingEventArgs.cs new file mode 100644 index 00000000..72500cf4 --- /dev/null +++ b/LabApi/Events/Arguments/Scp127Events/Scp127TalkingEventArgs.cs @@ -0,0 +1,46 @@ +using InventorySystem.Items.Firearms; +using InventorySystem.Items.Firearms.Modules.Scp127; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using static InventorySystem.Items.Firearms.Modules.Scp127.Scp127VoiceTriggerBase; + +namespace LabApi.Events.Arguments.Scp127Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp127Events.Talking"/> event. +/// </summary> +public class Scp127TalkingEventArgs : EventArgs, IScp127ItemEvent, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp127TalkingEventArgs"/> class. + /// </summary> + /// <param name="weapon">The Scp-127 firearm.</param> + /// <param name="voiceLine">The voiceline to be played.</param> + /// <param name="priority">The priority of the voiceline.</param> + public Scp127TalkingEventArgs(Firearm weapon, Scp127VoiceLinesTranslation voiceLine, VoiceLinePriority priority) + { + Scp127Item = (Scp127Firearm)FirearmItem.Get(weapon); + VoiceLine = voiceLine; + Priority = priority; + IsAllowed = true; + } + + /// <summary> + /// Gets the SCP-127 firearm. + /// </summary> + public Scp127Firearm Scp127Item { get; } + + /// <summary> + /// Gets or sets the voiceline the SCP-127 will play. + /// </summary> + public Scp127VoiceLinesTranslation VoiceLine { get; set; } + + /// <summary> + /// Gets or sets the priority the voiceline will be played with. + /// </summary> + public VoiceLinePriority Priority { get; set; } + + /// <inheritdoc/> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173AddedObserverEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173AddedObserverEventArgs.cs index c81cf17b..0c2e8535 100644 --- a/LabApi/Events/Arguments/Scp173Events/Scp173AddedObserverEventArgs.cs +++ b/LabApi/Events/Arguments/Scp173Events/Scp173AddedObserverEventArgs.cs @@ -13,11 +13,11 @@ public class Scp173AddedObserverEventArgs : EventArgs, IPlayerEvent, ITargetEven /// Initializes a new instance of the <see cref="Scp173AddedObserverEventArgs"/> class. /// </summary> /// <param name="target">The player that is observing the SCP-173 player.</param> - /// <param name="player">The SCP-173 player instance.</param> - public Scp173AddedObserverEventArgs(ReferenceHub target, ReferenceHub player) + /// <param name="hub">The SCP-173 player instance.</param> + public Scp173AddedObserverEventArgs(ReferenceHub target, ReferenceHub hub) { Target = Player.Get(target); - Player = Player.Get(player); + Player = Player.Get(hub); } /// <summary> diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173AddingObserverEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173AddingObserverEventArgs.cs index d1ab49b4..711b0ccb 100644 --- a/LabApi/Events/Arguments/Scp173Events/Scp173AddingObserverEventArgs.cs +++ b/LabApi/Events/Arguments/Scp173Events/Scp173AddingObserverEventArgs.cs @@ -13,12 +13,12 @@ public class Scp173AddingObserverEventArgs : EventArgs, IPlayerEvent, ITargetEve /// Initializes a new instance of the <see cref="Scp173AddingObserverEventArgs"/> class. /// </summary> /// <param name="target">The player that is observing the SCP-173 player.</param> - /// <param name="player">The SCP-173 player instance.</param> - public Scp173AddingObserverEventArgs(ReferenceHub target, ReferenceHub player) + /// <param name="hub">The SCP-173 player instance.</param> + public Scp173AddingObserverEventArgs(ReferenceHub target, ReferenceHub hub) { IsAllowed = true; Target = Player.Get(target); - Player = Player.Get(player); + Player = Player.Get(hub); } /// <summary> diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173BreakneckSpeedChangedEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173BreakneckSpeedChangedEventArgs.cs index 1fde5556..8fdfcf00 100644 --- a/LabApi/Events/Arguments/Scp173Events/Scp173BreakneckSpeedChangedEventArgs.cs +++ b/LabApi/Events/Arguments/Scp173Events/Scp173BreakneckSpeedChangedEventArgs.cs @@ -12,11 +12,11 @@ public class Scp173BreakneckSpeedChangedEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="Scp173BreakneckSpeedChangedEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-173 player instance.</param> + /// <param name="hub">The SCP-173 player instance.</param> /// <param name="active">The new breakneck speed state.</param> - public Scp173BreakneckSpeedChangedEventArgs(ReferenceHub player, bool active) + public Scp173BreakneckSpeedChangedEventArgs(ReferenceHub hub, bool active) { - Player = Player.Get(player); + Player = Player.Get(hub); Active = active; } diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173BreakneckSpeedChangingEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173BreakneckSpeedChangingEventArgs.cs index 2d55a31d..1665d7c9 100644 --- a/LabApi/Events/Arguments/Scp173Events/Scp173BreakneckSpeedChangingEventArgs.cs +++ b/LabApi/Events/Arguments/Scp173Events/Scp173BreakneckSpeedChangingEventArgs.cs @@ -12,12 +12,12 @@ public class Scp173BreakneckSpeedChangingEventArgs : EventArgs, IPlayerEvent, IC /// <summary> /// Initializes a new instance of the <see cref="Scp173BreakneckSpeedChangingEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-173 player instance.</param> + /// <param name="hub">The SCP-173 player instance.</param> /// <param name="active">The new breakneck speed state.</param> - public Scp173BreakneckSpeedChangingEventArgs(ReferenceHub player, bool active) + public Scp173BreakneckSpeedChangingEventArgs(ReferenceHub hub, bool active) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Active = active; } diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173CreatedTantrumEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173CreatedTantrumEventArgs.cs index 96381655..b7e12947 100644 --- a/LabApi/Events/Arguments/Scp173Events/Scp173CreatedTantrumEventArgs.cs +++ b/LabApi/Events/Arguments/Scp173Events/Scp173CreatedTantrumEventArgs.cs @@ -14,11 +14,11 @@ public class Scp173CreatedTantrumEventArgs : EventArgs, IPlayerEvent, ITantrumEv /// Initializes a new instance of the <see cref="Scp173CreatedTantrumEventArgs"/> class. /// </summary> /// <param name="tantrumInstance">The tantrum instance.</param> - /// <param name="player">The SCP-173 player instance.</param> - public Scp173CreatedTantrumEventArgs(TantrumEnvironmentalHazard tantrumInstance, ReferenceHub player) + /// <param name="hub">The SCP-173 player instance.</param> + public Scp173CreatedTantrumEventArgs(TantrumEnvironmentalHazard tantrumInstance, ReferenceHub hub) { Tantrum = TantrumHazard.Get(tantrumInstance); - Player = Player.Get(player); + Player = Player.Get(hub); } /// <summary> diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173CreatingTantrumEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173CreatingTantrumEventArgs.cs index 0fed36a0..e4d65fdb 100644 --- a/LabApi/Events/Arguments/Scp173Events/Scp173CreatingTantrumEventArgs.cs +++ b/LabApi/Events/Arguments/Scp173Events/Scp173CreatingTantrumEventArgs.cs @@ -12,11 +12,11 @@ public class Scp173CreatingTantrumEventArgs : EventArgs, IPlayerEvent, ICancella /// <summary> /// Initializes a new instance of the <see cref="Scp173CreatingTantrumEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-173 player instance.</param> - public Scp173CreatingTantrumEventArgs(ReferenceHub player) + /// <param name="hub">The SCP-173 player instance.</param> + public Scp173CreatingTantrumEventArgs(ReferenceHub hub) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); } /// <summary> diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173PlayedSoundEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173PlayedSoundEventArgs.cs index a53571f7..9540d278 100644 --- a/LabApi/Events/Arguments/Scp173Events/Scp173PlayedSoundEventArgs.cs +++ b/LabApi/Events/Arguments/Scp173Events/Scp173PlayedSoundEventArgs.cs @@ -13,11 +13,11 @@ public class Scp173PlayedSoundEventArgs : EventArgs, IPlayerEvent /// <summary> /// The sound id that is being played. /// </summary> - /// <param name="player">The SCP-173 player instance.</param> + /// <param name="hub">The SCP-173 player instance.</param> /// <param name="soundId">The sound id that is being played.</param> - public Scp173PlayedSoundEventArgs(ReferenceHub player, Scp173AudioPlayer.Scp173SoundId soundId) + public Scp173PlayedSoundEventArgs(ReferenceHub hub, Scp173AudioPlayer.Scp173SoundId soundId) { - Player = Player.Get(player); + Player = Player.Get(hub); SoundId = soundId; } diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173PlayingSoundEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173PlayingSoundEventArgs.cs index 2d704082..d2d20812 100644 --- a/LabApi/Events/Arguments/Scp173Events/Scp173PlayingSoundEventArgs.cs +++ b/LabApi/Events/Arguments/Scp173Events/Scp173PlayingSoundEventArgs.cs @@ -13,12 +13,12 @@ public class Scp173PlayingSoundEventArgs : EventArgs, IPlayerEvent, ICancellable /// <summary> /// The sound id that is going to be played. /// </summary> - /// <param name="player">The SCP-173 player instance.</param> + /// <param name="hub">The SCP-173 player instance.</param> /// <param name="soundId">The sound id that is going to be played.</param> - public Scp173PlayingSoundEventArgs(ReferenceHub player, Scp173AudioPlayer.Scp173SoundId soundId) + public Scp173PlayingSoundEventArgs(ReferenceHub hub, Scp173AudioPlayer.Scp173SoundId soundId) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); SoundId = soundId; } diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173RemovedObserverEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173RemovedObserverEventArgs.cs index 788e5264..5f51f5a4 100644 --- a/LabApi/Events/Arguments/Scp173Events/Scp173RemovedObserverEventArgs.cs +++ b/LabApi/Events/Arguments/Scp173Events/Scp173RemovedObserverEventArgs.cs @@ -13,11 +13,11 @@ public class Scp173RemovedObserverEventArgs : EventArgs, IPlayerEvent, ITargetEv /// Initializes a new instance of the <see cref="Scp173RemovedObserverEventArgs"/> class. /// </summary> /// <param name="target">The player that was observing the SCP-173 player.</param> - /// <param name="player">The SCP-173 player instance.</param> - public Scp173RemovedObserverEventArgs(ReferenceHub target, ReferenceHub player) + /// <param name="hub">The SCP-173 player instance.</param> + public Scp173RemovedObserverEventArgs(ReferenceHub target, ReferenceHub hub) { Target = Player.Get(target); - Player = Player.Get(player); + Player = Player.Get(hub); } /// <summary> diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173RemovingObserverEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173RemovingObserverEventArgs.cs index 31a08021..d3d1a19a 100644 --- a/LabApi/Events/Arguments/Scp173Events/Scp173RemovingObserverEventArgs.cs +++ b/LabApi/Events/Arguments/Scp173Events/Scp173RemovingObserverEventArgs.cs @@ -13,12 +13,12 @@ public class Scp173RemovingObserverEventArgs : EventArgs, IPlayerEvent, ITargetE /// Initializes a new instance of the <see cref="Scp173RemovingObserverEventArgs"/> class. /// </summary> /// <param name="target">The player that was observing the SCP-173 player.</param> - /// <param name="player">The SCP-173 player instance.</param> - public Scp173RemovingObserverEventArgs(ReferenceHub target, ReferenceHub player) + /// <param name="hub">The SCP-173 player instance.</param> + public Scp173RemovingObserverEventArgs(ReferenceHub target, ReferenceHub hub) { IsAllowed = true; Target = Player.Get(target); - Player = Player.Get(player); + Player = Player.Get(hub); } /// <summary> diff --git a/LabApi/Events/Arguments/Scp914Events/Scp914ActivatedEventArgs.cs b/LabApi/Events/Arguments/Scp914Events/Scp914ActivatedEventArgs.cs index a740f898..60df6840 100644 --- a/LabApi/Events/Arguments/Scp914Events/Scp914ActivatedEventArgs.cs +++ b/LabApi/Events/Arguments/Scp914Events/Scp914ActivatedEventArgs.cs @@ -14,11 +14,11 @@ public class Scp914ActivatedEventArgs : EventArgs, IScp914Event, IPlayerEvent /// Initializes a new instance of the <see cref="Scp914ActivatedEventArgs"/> class. /// </summary> /// <param name="knobSetting">The knob setting of SCP-914.</param> - /// <param name="player">The player that activated SCP-914.</param> - public Scp914ActivatedEventArgs(Scp914KnobSetting knobSetting, ReferenceHub player) + /// <param name="hub">The player that activated SCP-914.</param> + public Scp914ActivatedEventArgs(Scp914KnobSetting knobSetting, ReferenceHub hub) { KnobSetting = knobSetting; - Player = Player.Get(player); + Player = Player.Get(hub); } /// <inheritdoc /> diff --git a/LabApi/Events/Arguments/Scp914Events/Scp914ActivatingEventArgs.cs b/LabApi/Events/Arguments/Scp914Events/Scp914ActivatingEventArgs.cs index 67edee0c..1b4f5973 100644 --- a/LabApi/Events/Arguments/Scp914Events/Scp914ActivatingEventArgs.cs +++ b/LabApi/Events/Arguments/Scp914Events/Scp914ActivatingEventArgs.cs @@ -14,12 +14,12 @@ public class Scp914ActivatingEventArgs : EventArgs, IScp914Event, IPlayerEvent, /// Initializes a new instance of the <see cref="Scp914ActivatingEventArgs"/> class. /// </summary> /// <param name="knobSetting">The knob setting of SCP-914.</param> - /// <param name="player">The player that is activating SCP-914.</param> - public Scp914ActivatingEventArgs(Scp914KnobSetting knobSetting, ReferenceHub player) + /// <param name="hub">The player that is activating SCP-914.</param> + public Scp914ActivatingEventArgs(Scp914KnobSetting knobSetting, ReferenceHub hub) { IsAllowed = true; KnobSetting = knobSetting; - Player = Player.Get(player); + Player = Player.Get(hub); } /// <inheritdoc /> diff --git a/LabApi/Events/Arguments/Scp914Events/Scp914KnobChangedEventArgs.cs b/LabApi/Events/Arguments/Scp914Events/Scp914KnobChangedEventArgs.cs index bcb0f4f9..e9ccec50 100644 --- a/LabApi/Events/Arguments/Scp914Events/Scp914KnobChangedEventArgs.cs +++ b/LabApi/Events/Arguments/Scp914Events/Scp914KnobChangedEventArgs.cs @@ -15,12 +15,12 @@ public class Scp914KnobChangedEventArgs : EventArgs, IScp914Event, IPlayerEvent /// </summary> /// <param name="oldKnobSetting">The old knob setting of SCP-914.</param> /// <param name="knobSetting">The new knob setting of SCP-914.</param> - /// <param name="player">The player that has changed the knob.</param> - public Scp914KnobChangedEventArgs(Scp914KnobSetting oldKnobSetting, Scp914KnobSetting knobSetting, ReferenceHub player) + /// <param name="hub">The player that has changed the knob.</param> + public Scp914KnobChangedEventArgs(Scp914KnobSetting oldKnobSetting, Scp914KnobSetting knobSetting, ReferenceHub hub) { OldKnobSetting = oldKnobSetting; KnobSetting = knobSetting; - Player = Player.Get(player); + Player = Player.Get(hub); } /// <summary> diff --git a/LabApi/Events/Arguments/Scp914Events/Scp914KnobChangingEventArgs.cs b/LabApi/Events/Arguments/Scp914Events/Scp914KnobChangingEventArgs.cs index 371740aa..fe89d86a 100644 --- a/LabApi/Events/Arguments/Scp914Events/Scp914KnobChangingEventArgs.cs +++ b/LabApi/Events/Arguments/Scp914Events/Scp914KnobChangingEventArgs.cs @@ -15,13 +15,13 @@ public class Scp914KnobChangingEventArgs : EventArgs, IScp914Event, IPlayerEvent /// </summary> /// <param name="oldKnobSetting">The old knob setting of SCP-914.</param> /// <param name="knobSetting">The new knob setting of SCP-914.</param> - /// <param name="player">The player that is changing the knob.</param> - public Scp914KnobChangingEventArgs(Scp914KnobSetting oldKnobSetting, Scp914KnobSetting knobSetting, ReferenceHub player) + /// <param name="hub">The player that is changing the knob.</param> + public Scp914KnobChangingEventArgs(Scp914KnobSetting oldKnobSetting, Scp914KnobSetting knobSetting, ReferenceHub hub) { IsAllowed = true; OldKnobSetting = oldKnobSetting; KnobSetting = knobSetting; - Player = Player.Get(player); + Player = Player.Get(hub); } /// <summary> diff --git a/LabApi/Events/Arguments/Scp914Events/Scp914ProcessedInventoryItemEventArgs.cs b/LabApi/Events/Arguments/Scp914Events/Scp914ProcessedInventoryItemEventArgs.cs index ceddecfe..b22cd3d8 100644 --- a/LabApi/Events/Arguments/Scp914Events/Scp914ProcessedInventoryItemEventArgs.cs +++ b/LabApi/Events/Arguments/Scp914Events/Scp914ProcessedInventoryItemEventArgs.cs @@ -17,13 +17,13 @@ public class Scp914ProcessedInventoryItemEventArgs : EventArgs, IScp914Event, II /// <param name="oldItemType">The old item type.</param> /// <param name="item">The new item that has been processed by SCP-914.</param> /// <param name="knobSetting">The knob setting of SCP-914.</param> - /// <param name="player">The owner of the item.</param> - public Scp914ProcessedInventoryItemEventArgs(ItemType oldItemType, ItemBase item, Scp914KnobSetting knobSetting, ReferenceHub player) + /// <param name="hub">The owner of the item.</param> + public Scp914ProcessedInventoryItemEventArgs(ItemType oldItemType, ItemBase item, Scp914KnobSetting knobSetting, ReferenceHub hub) { OldItemType = oldItemType; Item = Item.Get(item); KnobSetting = knobSetting; - Player = Player.Get(player); + Player = Player.Get(hub); } /// <summary> diff --git a/LabApi/Events/Arguments/Scp914Events/Scp914ProcessedPlayerEventArgs.cs b/LabApi/Events/Arguments/Scp914Events/Scp914ProcessedPlayerEventArgs.cs index a982ef84..d7915df9 100644 --- a/LabApi/Events/Arguments/Scp914Events/Scp914ProcessedPlayerEventArgs.cs +++ b/LabApi/Events/Arguments/Scp914Events/Scp914ProcessedPlayerEventArgs.cs @@ -16,12 +16,12 @@ public class Scp914ProcessedPlayerEventArgs : EventArgs, IScp914Event, IPlayerEv /// </summary> /// <param name="knobSetting">The knob setting of SCP-914.</param> /// <param name="newPosition">The new position that the player has been processed into.</param> - /// <param name="player">The player that has been processed by SCP-914.</param> - public Scp914ProcessedPlayerEventArgs(Vector3 newPosition, Scp914KnobSetting knobSetting, ReferenceHub player) + /// <param name="hub">The player that has been processed by SCP-914.</param> + public Scp914ProcessedPlayerEventArgs(Vector3 newPosition, Scp914KnobSetting knobSetting, ReferenceHub hub) { NewPosition = newPosition; KnobSetting = knobSetting; - Player = Player.Get(player); + Player = Player.Get(hub); } /// <summary> diff --git a/LabApi/Events/Arguments/Scp914Events/Scp914ProcessingInventoryItemEventArgs.cs b/LabApi/Events/Arguments/Scp914Events/Scp914ProcessingInventoryItemEventArgs.cs index 6e3dd7fd..5b66e6ea 100644 --- a/LabApi/Events/Arguments/Scp914Events/Scp914ProcessingInventoryItemEventArgs.cs +++ b/LabApi/Events/Arguments/Scp914Events/Scp914ProcessingInventoryItemEventArgs.cs @@ -16,13 +16,13 @@ public class Scp914ProcessingInventoryItemEventArgs : EventArgs, IScp914Event, I /// </summary> /// <param name="item">The item that is being processed by SCP-914.</param> /// <param name="knobSetting">The knob setting of SCP-914.</param> - /// <param name="player">The owner of the item.</param> - public Scp914ProcessingInventoryItemEventArgs(ItemBase item, Scp914KnobSetting knobSetting, ReferenceHub player) + /// <param name="hub">The owner of the item.</param> + public Scp914ProcessingInventoryItemEventArgs(ItemBase item, Scp914KnobSetting knobSetting, ReferenceHub hub) { IsAllowed = true; Item = Item.Get(item); KnobSetting = knobSetting; - Player = Player.Get(player); + Player = Player.Get(hub); } /// <inheritdoc /> diff --git a/LabApi/Events/Arguments/Scp914Events/Scp914ProcessingPlayerEventArgs.cs b/LabApi/Events/Arguments/Scp914Events/Scp914ProcessingPlayerEventArgs.cs index 8887d521..8920020f 100644 --- a/LabApi/Events/Arguments/Scp914Events/Scp914ProcessingPlayerEventArgs.cs +++ b/LabApi/Events/Arguments/Scp914Events/Scp914ProcessingPlayerEventArgs.cs @@ -16,13 +16,13 @@ public class Scp914ProcessingPlayerEventArgs : EventArgs, IScp914Event, IPlayerE /// </summary> /// <param name="newPosition">The new position that the player will be processed into.</param> /// <param name="knobSetting">The knob setting of SCP-914.</param> - /// <param name="player">The player that is being processed by SCP-914.</param> - public Scp914ProcessingPlayerEventArgs(Vector3 newPosition, Scp914KnobSetting knobSetting, ReferenceHub player) + /// <param name="hub">The player that is being processed by SCP-914.</param> + public Scp914ProcessingPlayerEventArgs(Vector3 newPosition, Scp914KnobSetting knobSetting, ReferenceHub hub) { IsAllowed = true; NewPosition = newPosition; KnobSetting = knobSetting; - Player = Player.Get(player); + Player = Player.Get(hub); } /// <summary> diff --git a/LabApi/Events/Arguments/Scp939Events/Scp939AttackedEventArgs.cs b/LabApi/Events/Arguments/Scp939Events/Scp939AttackedEventArgs.cs index 530a0efa..570d8226 100644 --- a/LabApi/Events/Arguments/Scp939Events/Scp939AttackedEventArgs.cs +++ b/LabApi/Events/Arguments/Scp939Events/Scp939AttackedEventArgs.cs @@ -12,12 +12,12 @@ public class Scp939AttackedEventArgs : EventArgs, IPlayerEvent, ITargetEvent /// <summary> /// Initializes a new instance of the <see cref="Scp939AttackedEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-939 player instance.</param> + /// <param name="hub">The SCP-939 player instance.</param> /// <param name="target">The destructible that was attacked.</param> /// <param name="damage">The damage dealt.</param> - public Scp939AttackedEventArgs(ReferenceHub player, ReferenceHub target, float damage) + public Scp939AttackedEventArgs(ReferenceHub hub, ReferenceHub target, float damage) { - Player = Player.Get(player); + Player = Player.Get(hub); Target = Player.Get(target); Damage = damage; } diff --git a/LabApi/Events/Arguments/Scp939Events/Scp939AttackingEventArgs.cs b/LabApi/Events/Arguments/Scp939Events/Scp939AttackingEventArgs.cs index 847686da..fe9692b9 100644 --- a/LabApi/Events/Arguments/Scp939Events/Scp939AttackingEventArgs.cs +++ b/LabApi/Events/Arguments/Scp939Events/Scp939AttackingEventArgs.cs @@ -12,13 +12,13 @@ public class Scp939AttackingEventArgs : EventArgs, IPlayerEvent, ITargetEvent, I /// <summary> /// Initializes a new instance of the <see cref="Scp939AttackingEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-939 player instance.</param> + /// <param name="hub">The SCP-939 player instance.</param> /// <param name="target">The destructible that is being attacked.</param> /// <param name="damage">The damage dealt.</param> - public Scp939AttackingEventArgs(ReferenceHub player, ReferenceHub target, float damage) + public Scp939AttackingEventArgs(ReferenceHub hub, ReferenceHub target, float damage) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Target = Player.Get(target); Damage = damage; } diff --git a/LabApi/Events/Arguments/Scp939Events/Scp939CreatedAmnesticCloudEventArgs.cs b/LabApi/Events/Arguments/Scp939Events/Scp939CreatedAmnesticCloudEventArgs.cs index e3d03225..5fbd6700 100644 --- a/LabApi/Events/Arguments/Scp939Events/Scp939CreatedAmnesticCloudEventArgs.cs +++ b/LabApi/Events/Arguments/Scp939Events/Scp939CreatedAmnesticCloudEventArgs.cs @@ -13,11 +13,11 @@ public class Scp939CreatedAmnesticCloudEventArgs : EventArgs, IPlayerEvent, IAmn /// <summary> /// Initializes a new instance of the <see cref="Scp939CreatedAmnesticCloudEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-939 player instance.</param> + /// <param name="hub">The SCP-939 player instance.</param> /// <param name="amnesticCloudInstance">The created amnestic cloud instance.</param> - public Scp939CreatedAmnesticCloudEventArgs(ReferenceHub player, Scp939AmnesticCloudInstance amnesticCloudInstance) + public Scp939CreatedAmnesticCloudEventArgs(ReferenceHub hub, Scp939AmnesticCloudInstance amnesticCloudInstance) { - Player = Player.Get(player); + Player = Player.Get(hub); AmnesticCloud = AmnesticCloudHazard.Get(amnesticCloudInstance); } diff --git a/LabApi/Events/Arguments/Scp939Events/Scp939CreatingAmnesticCloudEventArgs.cs b/LabApi/Events/Arguments/Scp939Events/Scp939CreatingAmnesticCloudEventArgs.cs index 3b11555a..823b3af6 100644 --- a/LabApi/Events/Arguments/Scp939Events/Scp939CreatingAmnesticCloudEventArgs.cs +++ b/LabApi/Events/Arguments/Scp939Events/Scp939CreatingAmnesticCloudEventArgs.cs @@ -12,11 +12,11 @@ public class Scp939CreatingAmnesticCloudEventArgs : EventArgs, IPlayerEvent, ICa /// <summary> /// Initializes a new instance of the <see cref="Scp939CreatingAmnesticCloudEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-939 player instance.</param> - public Scp939CreatingAmnesticCloudEventArgs(ReferenceHub player) + /// <param name="hub">The SCP-939 player instance.</param> + public Scp939CreatingAmnesticCloudEventArgs(ReferenceHub hub) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); } /// <inheritdoc /> diff --git a/LabApi/Events/Arguments/Scp939Events/Scp939LungedEventArgs.cs b/LabApi/Events/Arguments/Scp939Events/Scp939LungedEventArgs.cs index 971aac77..e22cf2f3 100644 --- a/LabApi/Events/Arguments/Scp939Events/Scp939LungedEventArgs.cs +++ b/LabApi/Events/Arguments/Scp939Events/Scp939LungedEventArgs.cs @@ -13,11 +13,11 @@ public class Scp939LungedEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="Scp939LungedEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-939 player instance.</param> + /// <param name="hub">The SCP-939 player instance.</param> /// <param name="lungeState">The SCP-939 lunge state.</param> - public Scp939LungedEventArgs(ReferenceHub player, Scp939LungeState lungeState) + public Scp939LungedEventArgs(ReferenceHub hub, Scp939LungeState lungeState) { - Player = Player.Get(player); + Player = Player.Get(hub); LungeState = lungeState; } diff --git a/LabApi/Events/Arguments/Scp939Events/Scp939LungingEventArgs.cs b/LabApi/Events/Arguments/Scp939Events/Scp939LungingEventArgs.cs index d10c4759..d5e2678c 100644 --- a/LabApi/Events/Arguments/Scp939Events/Scp939LungingEventArgs.cs +++ b/LabApi/Events/Arguments/Scp939Events/Scp939LungingEventArgs.cs @@ -13,12 +13,12 @@ public class Scp939LungingEventArgs : EventArgs, ICancellableEvent, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="Scp939LungingEventArgs"/> class. /// </summary> - /// <param name="player">The SCP-939 player instance.</param> + /// <param name="hub">The SCP-939 player instance.</param> /// <param name="lungeState">The SCP-939 lunge state.</param> - public Scp939LungingEventArgs(ReferenceHub player, Scp939LungeState lungeState) + public Scp939LungingEventArgs(ReferenceHub hub, Scp939LungeState lungeState) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); LungeState = lungeState; } diff --git a/LabApi/Events/Arguments/ServerEvents/CassieQueuedScpTerminationEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/CassieQueuedScpTerminationEventArgs.cs index e0c5011e..8ed5dad8 100644 --- a/LabApi/Events/Arguments/ServerEvents/CassieQueuedScpTerminationEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/CassieQueuedScpTerminationEventArgs.cs @@ -14,13 +14,13 @@ public class CassieQueuedScpTerminationEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="CassieQueuedScpTerminationEventArgs"/> class. /// </summary> - /// <param name="player">The SCP player the C.A.S.S.I.E termination announcement is for.</param> + /// <param name="hub">The SCP player the C.A.S.S.I.E termination announcement is for.</param> /// <param name="announcement">The message C.A.S.S.I.E is supposed to say.</param> /// <param name="subtitles">The subtitle part array of the message.</param> /// <param name="damageHandler">The damage handler that caused the termination of the SCP.</param> - public CassieQueuedScpTerminationEventArgs(ReferenceHub player, string announcement, SubtitlePart[] subtitles, DamageHandlerBase damageHandler) + public CassieQueuedScpTerminationEventArgs(ReferenceHub hub, string announcement, SubtitlePart[] subtitles, DamageHandlerBase damageHandler) { - Player = Player.Get(player); + Player = Player.Get(hub); Announcement = announcement; SubtitleParts = subtitles; DamageHandler = damageHandler; diff --git a/LabApi/Events/Arguments/ServerEvents/CassieQueuingScpTerminationEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/CassieQueuingScpTerminationEventArgs.cs index 88afe799..9957ea3c 100644 --- a/LabApi/Events/Arguments/ServerEvents/CassieQueuingScpTerminationEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/CassieQueuingScpTerminationEventArgs.cs @@ -14,14 +14,14 @@ public class CassieQueuingScpTerminationEventArgs : EventArgs, IPlayerEvent, ICa /// <summary> /// Initializes a new instance of the <see cref="CassieQueuingScpTerminationEventArgs"/> class. /// </summary> - /// <param name="player">The SCP player the C.A.S.S.I.E termination announcement is for.</param> + /// <param name="hub">The SCP player the C.A.S.S.I.E termination announcement is for.</param> /// <param name="announcement">The message C.A.S.S.I.E is supposed to say.</param> /// <param name="subtitles">The subtitle part array of the message.</param> /// <param name="damageHandler">The damage handler that caused the termination of the SCP.</param> - public CassieQueuingScpTerminationEventArgs(ReferenceHub player, string announcement, SubtitlePart[] subtitles, DamageHandlerBase damageHandler) + public CassieQueuingScpTerminationEventArgs(ReferenceHub hub, string announcement, SubtitlePart[] subtitles, DamageHandlerBase damageHandler) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Announcement = announcement; SubtitleParts = [.. subtitles]; DamageHandler = damageHandler; diff --git a/LabApi/Events/Arguments/ServerEvents/ExplosionSpawnedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/ExplosionSpawnedEventArgs.cs index fe56ed15..4d97ccd8 100644 --- a/LabApi/Events/Arguments/ServerEvents/ExplosionSpawnedEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/ExplosionSpawnedEventArgs.cs @@ -14,14 +14,14 @@ public class ExplosionSpawnedEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="ExplosionSpawnedEventArgs"/> class. /// </summary> - /// <param name="player">The player which caused this explosion.</param> + /// <param name="hub">The player which caused this explosion.</param> /// <param name="position">The position of explosion.</param> /// <param name="settingsReference">The projectile which caused explosion.</param> /// <param name="explosionType">The type of this explosion.</param> /// <param name="destroyDoors">Whether the explosion was allowed to destroy doors.</param> - public ExplosionSpawnedEventArgs(ReferenceHub? player, Vector3 position, ExplosionGrenade settingsReference, ExplosionType explosionType, bool destroyDoors) + public ExplosionSpawnedEventArgs(ReferenceHub? hub, Vector3 position, ExplosionGrenade settingsReference, ExplosionType explosionType, bool destroyDoors) { - Player = Player.Get(player); + Player = Player.Get(hub); Position = position; Settings = settingsReference; ExplosionType = explosionType; diff --git a/LabApi/Events/Arguments/ServerEvents/ExplosionSpawningEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/ExplosionSpawningEventArgs.cs index 29638552..a5eb2021 100644 --- a/LabApi/Events/Arguments/ServerEvents/ExplosionSpawningEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/ExplosionSpawningEventArgs.cs @@ -14,14 +14,14 @@ public class ExplosionSpawningEventArgs : EventArgs, IPlayerEvent, ICancellableE /// <summary> /// Initializes a new instance of the <see cref="ExplosionSpawningEventArgs"/> class. /// </summary> - /// <param name="player">The player which caused this explosion.</param> + /// <param name="hub">The player which caused this explosion.</param> /// <param name="position">The position of explosion.</param> /// <param name="settingsReference">The projectile which will cause the explosion.</param> /// <param name="explosionType">The type of this explosion.</param> /// <param name="destroyDoors">Whether the explosion should destroy doors.</param> - public ExplosionSpawningEventArgs(ReferenceHub? player, Vector3 position, ExplosionGrenade settingsReference, ExplosionType explosionType, bool destroyDoors) + public ExplosionSpawningEventArgs(ReferenceHub? hub, Vector3 position, ExplosionGrenade settingsReference, ExplosionType explosionType, bool destroyDoors) { - Player = Player.Get(player); + Player = Player.Get(hub); Position = position; Settings = settingsReference; ExplosionType = explosionType; diff --git a/LabApi/Events/Arguments/ServerEvents/ProjectileExplodedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/ProjectileExplodedEventArgs.cs index 6144ff08..832fe1f3 100644 --- a/LabApi/Events/Arguments/ServerEvents/ProjectileExplodedEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/ProjectileExplodedEventArgs.cs @@ -15,12 +15,12 @@ public class ProjectileExplodedEventArgs : EventArgs, IPlayerEvent, ITimedGrenad /// Initializes a new instance of the <see cref="ProjectileExplodedEventArgs"/> class. /// </summary> /// <param name="projectile">The projectile which will cause explosion.</param> - /// <param name="player">The player which threw that grenade.</param> + /// <param name="hub">The player which threw that grenade.</param> /// <param name="position">The position of explosion.</param> - public ProjectileExplodedEventArgs(TimeGrenade projectile, ReferenceHub player, Vector3 position) + public ProjectileExplodedEventArgs(TimeGrenade projectile, ReferenceHub hub, Vector3 position) { TimedGrenade = TimedGrenadeProjectile.Get(projectile); - Player = Player.Get(player); + Player = Player.Get(hub); Position = position; } diff --git a/LabApi/Events/Arguments/ServerEvents/ProjectileExplodingEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/ProjectileExplodingEventArgs.cs index ff5f3dff..31bdfed5 100644 --- a/LabApi/Events/Arguments/ServerEvents/ProjectileExplodingEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/ProjectileExplodingEventArgs.cs @@ -15,12 +15,12 @@ public class ProjectileExplodingEventArgs : EventArgs, IPlayerEvent, ITimedGrena /// Initializes a new instance of the <see cref="ProjectileExplodingEventArgs"/> class. /// </summary> /// <param name="grenade">The grenade which will cause explosion.</param> - /// <param name="player">The player which threw that grenade.</param> + /// <param name="hub">The player which threw that grenade.</param> /// <param name="position">The position of explosion.</param> - public ProjectileExplodingEventArgs(TimeGrenade grenade, ReferenceHub player, Vector3 position) + public ProjectileExplodingEventArgs(TimeGrenade grenade, ReferenceHub hub, Vector3 position) { TimedGrenade = TimedGrenadeProjectile.Get(grenade); - Player = Player.Get(player); + Player = Player.Get(hub); Position = position; IsAllowed = true; diff --git a/LabApi/Events/Arguments/WarheadEvents/WarheadDetonatedEventArgs.cs b/LabApi/Events/Arguments/WarheadEvents/WarheadDetonatedEventArgs.cs index 1dde8d35..77bf3c15 100644 --- a/LabApi/Events/Arguments/WarheadEvents/WarheadDetonatedEventArgs.cs +++ b/LabApi/Events/Arguments/WarheadEvents/WarheadDetonatedEventArgs.cs @@ -12,10 +12,10 @@ public class WarheadDetonatedEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="WarheadDetonatedEventArgs"/> class. /// </summary> - /// <param name="player">The player who detonated the warhead.</param> - public WarheadDetonatedEventArgs(ReferenceHub player) + /// <param name="hub">The player who detonated the warhead.</param> + public WarheadDetonatedEventArgs(ReferenceHub hub) { - Player = Player.Get(player); + Player = Player.Get(hub); } /// <summary> diff --git a/LabApi/Events/Arguments/WarheadEvents/WarheadDetonatingEventArgs.cs b/LabApi/Events/Arguments/WarheadEvents/WarheadDetonatingEventArgs.cs index b0b0710b..30341c7a 100644 --- a/LabApi/Events/Arguments/WarheadEvents/WarheadDetonatingEventArgs.cs +++ b/LabApi/Events/Arguments/WarheadEvents/WarheadDetonatingEventArgs.cs @@ -12,11 +12,11 @@ public class WarheadDetonatingEventArgs : EventArgs, IPlayerEvent, ICancellableE /// <summary> /// Initializes a new instance of the <see cref="WarheadDetonatingEventArgs"/> class. /// </summary> - /// <param name="player">The player who is detonating the warhead.</param> - public WarheadDetonatingEventArgs(ReferenceHub player) + /// <param name="hub">The player who is detonating the warhead.</param> + public WarheadDetonatingEventArgs(ReferenceHub hub) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); } /// <inheritdoc /> diff --git a/LabApi/Events/Arguments/WarheadEvents/WarheadStartedEventArgs.cs b/LabApi/Events/Arguments/WarheadEvents/WarheadStartedEventArgs.cs index 1d2c1e57..7a7ea1a2 100644 --- a/LabApi/Events/Arguments/WarheadEvents/WarheadStartedEventArgs.cs +++ b/LabApi/Events/Arguments/WarheadEvents/WarheadStartedEventArgs.cs @@ -12,13 +12,13 @@ public class WarheadStartedEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="WarheadStartedEventArgs"/> class. /// </summary> - /// <param name="player">The player who started the warhead.</param> + /// <param name="hub">The player who started the warhead.</param> /// <param name="isAutomatic">Whether the warhead is starting automatically.</param> /// <param name="suppressSubtitles">Whether subtitles should be suppressed.</param> /// <param name="warheadState">The current state of the alpha warhead.</param> - public WarheadStartedEventArgs(ReferenceHub player, bool isAutomatic, bool suppressSubtitles, AlphaWarheadSyncInfo warheadState) + public WarheadStartedEventArgs(ReferenceHub hub, bool isAutomatic, bool suppressSubtitles, AlphaWarheadSyncInfo warheadState) { - Player = Player.Get(player); + Player = Player.Get(hub); IsAutomatic = isAutomatic; SuppressSubtitles = suppressSubtitles; WarheadState = warheadState; diff --git a/LabApi/Events/Arguments/WarheadEvents/WarheadStartingEventArgs.cs b/LabApi/Events/Arguments/WarheadEvents/WarheadStartingEventArgs.cs index e9dd99eb..39953b1d 100644 --- a/LabApi/Events/Arguments/WarheadEvents/WarheadStartingEventArgs.cs +++ b/LabApi/Events/Arguments/WarheadEvents/WarheadStartingEventArgs.cs @@ -12,14 +12,14 @@ public class WarheadStartingEventArgs : EventArgs, IPlayerEvent, ICancellableEve /// <summary> /// Initializes a new instance of the <see cref="WarheadStartingEventArgs"/> class. /// </summary> - /// <param name="player">The player who is starting the warhead.</param> + /// <param name="hub">The player who is starting the warhead.</param> /// <param name="isAutomatic">Whether the warhead is starting automatically.</param> /// <param name="suppressSubtitles">Whether subtitles should be suppressed.</param> /// <param name="warheadState">The current state of the alpha warhead.</param> - public WarheadStartingEventArgs(ReferenceHub player, bool isAutomatic, bool suppressSubtitles, AlphaWarheadSyncInfo warheadState) + public WarheadStartingEventArgs(ReferenceHub hub, bool isAutomatic, bool suppressSubtitles, AlphaWarheadSyncInfo warheadState) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); IsAutomatic = isAutomatic; SuppressSubtitles = suppressSubtitles; WarheadState = warheadState; diff --git a/LabApi/Events/Arguments/WarheadEvents/WarheadStoppedEventArgs.cs b/LabApi/Events/Arguments/WarheadEvents/WarheadStoppedEventArgs.cs index 580ace8c..a2894c34 100644 --- a/LabApi/Events/Arguments/WarheadEvents/WarheadStoppedEventArgs.cs +++ b/LabApi/Events/Arguments/WarheadEvents/WarheadStoppedEventArgs.cs @@ -12,11 +12,11 @@ public class WarheadStoppedEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="WarheadStoppedEventArgs"/> class. /// </summary> - /// <param name="player">The player who stopped the warhead.</param> + /// <param name="hub">The player who stopped the warhead.</param> /// <param name="warheadState">The current state of the alpha warhead.</param> - public WarheadStoppedEventArgs(ReferenceHub player, AlphaWarheadSyncInfo warheadState) + public WarheadStoppedEventArgs(ReferenceHub hub, AlphaWarheadSyncInfo warheadState) { - Player = Player.Get(player); + Player = Player.Get(hub); WarheadState = warheadState; } diff --git a/LabApi/Events/Arguments/WarheadEvents/WarheadStoppingEventArgs.cs b/LabApi/Events/Arguments/WarheadEvents/WarheadStoppingEventArgs.cs index 2812562a..fc39a2ae 100644 --- a/LabApi/Events/Arguments/WarheadEvents/WarheadStoppingEventArgs.cs +++ b/LabApi/Events/Arguments/WarheadEvents/WarheadStoppingEventArgs.cs @@ -12,12 +12,12 @@ public class WarheadStoppingEventArgs : EventArgs, IPlayerEvent, ICancellableEve /// <summary> /// Initializes a new instance of the <see cref="WarheadStoppingEventArgs"/> class. /// </summary> - /// <param name="player">The player who is stopping the warhead.</param> + /// <param name="hub">The player who is stopping the warhead.</param> /// <param name="warheadState">The current state of the alpha warhead.</param> - public WarheadStoppingEventArgs(ReferenceHub player, AlphaWarheadSyncInfo warheadState) + public WarheadStoppingEventArgs(ReferenceHub hub, AlphaWarheadSyncInfo warheadState) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); WarheadState = warheadState; } diff --git a/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs b/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs index e5ee2733..5f97350b 100644 --- a/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs +++ b/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs @@ -426,6 +426,21 @@ public static partial class PlayerEvents /// </summary> public static event LabEventHandler<PlayerInspectedKeycardEventArgs>? InspectedKeycard; + /// <summary> + /// Gets called when the player requests to spin the revolver. + /// </summary> + public static event LabEventHandler<PlayerSpinningRevolverEventArgs>? SpinningRevolver; + + /// <summary> + /// Gets called when the player spinned the revolver. + /// </summary> + public static event LabEventHandler<PlayerSpinnedRevolverEventArgs>? SpinnedRevolver; + + /// <summary> + /// Gets called when the player toggled disruptor firing mode. + /// </summary> + public static event LabEventHandler<PlayerToggledDisruptorFiringModeEventArgs>? ToggledDisruptorFiringMode; + #endregion #region Item Actions and Interactions diff --git a/LabApi/Events/Handlers/Scp127Events.EventHandlers.cs b/LabApi/Events/Handlers/Scp127Events.EventHandlers.cs new file mode 100644 index 00000000..27058f3a --- /dev/null +++ b/LabApi/Events/Handlers/Scp127Events.EventHandlers.cs @@ -0,0 +1,39 @@ +using LabApi.Events.Arguments.Scp127Events; + +namespace LabApi.Events.Handlers; + +/// <summary> +/// Handles all the events related to the SCP-127. +/// </summary> +public static partial class Scp127Events +{ + /// <summary> + /// Gets called when the SCP-127 is gaining experience. + /// </summary> + public static event LabEventHandler<Scp127GainingExperienceEventArgs>? GainingExperience; + + /// <summary> + /// Gets called when the SCP-127 is gained experience. + /// </summary> + public static event LabEventHandler<Scp127GainExperienceEventArgs>? GainExperience; + + /// <summary> + /// Gets called when the SCP-127 is levelling up. + /// </summary> + public static event LabEventHandler<Scp127LevellingUpEventArgs>? LevellingUp; + + /// <summary> + /// Gets called when the SCP-127 level up. + /// </summary> + public static event LabEventHandler<Scp127LevelUpEventArgs>? LevelUp; + + /// <summary> + /// Gets called when SCP-127 is about to play a voiceline. + /// </summary> + public static event LabEventHandler<Scp127TalkingEventArgs>? Talking; + + /// <summary> + /// Gets called when SCP-127 played a voiceline. + /// </summary> + public static event LabEventHandler<Scp127TalkedEventArgs>? Talked; +} diff --git a/LabApi/Features/Wrappers/Facility/Doors/Door.cs b/LabApi/Features/Wrappers/Facility/Doors/Door.cs index 98dca4a0..03a24f24 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/Door.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/Door.cs @@ -67,6 +67,7 @@ internal static void Initialize() { "HID_CHAMBER", DoorName.HczHidChamber }, { "HID_UPPER", DoorName.HczHidUpper }, { "HID_LOWER", DoorName.HczHidLower }, + { "HID_LAB", DoorName.HczHidChamber }, { "NUKE_ARMORY", DoorName.HczNukeArmory }, { "106_PRIMARY", DoorName.Hcz106Primiary }, { "106_SECONDARY", DoorName.Hcz106Secondary }, diff --git a/LabApi/Features/Wrappers/Items/Firearm/FirearmItem.cs b/LabApi/Features/Wrappers/Items/Firearm/FirearmItem.cs index 14a0480d..c6bfeed1 100644 --- a/LabApi/Features/Wrappers/Items/Firearm/FirearmItem.cs +++ b/LabApi/Features/Wrappers/Items/Firearm/FirearmItem.cs @@ -1,14 +1,33 @@ -using InventorySystem.Items.Firearms; +using Generators; +using InventorySystem.Items.Firearms; +using InventorySystem.Items.Firearms.Attachments; +using InventorySystem.Items.Firearms.Attachments.Components; +using InventorySystem.Items.Firearms.Modules; +using LabApi.Features.Console; +using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; namespace LabApi.Features.Wrappers; /// <summary> -/// The wrapper representing <see cref="Firearm"/>. +/// The wrapper representing <see cref="Firearm"/>.<para/> +/// Firearms are functioning as they close as they would in real life. +/// This means that there are properties for whether the bolt is closed or opened, whether the hammer is cocked for specific firearms, whether the magazine is inserted and so many other properties you may need to be aware of when adjusting this firearm item. /// </summary> public class FirearmItem : Item { + /// <summary> + /// Initializes the <see cref="FirearmItem"/> class by subscribing to <see cref="Firearm"/> events and registers derived wrappers. + /// </summary> + [InitializeWrapper] + internal static void InitializeFirearmWrappers() + { + Register(ItemType.ParticleDisruptor, (x) => new ParticleDisruptorItem((ParticleDisruptor)x)); + Register(ItemType.GunRevolver, (x) => new RevolverFirearm(x)); + Register(ItemType.GunSCP127, (x) => new Scp127Firearm(x)); + Register(ItemType.GunShotgun, (x) => new ShotgunFirearm(x)); + } /// <summary> /// Contains all the cached firearm items, accessible through their <see cref="Firearm"/>. /// </summary> @@ -19,17 +38,478 @@ public class FirearmItem : Item /// </summary> public new static IReadOnlyCollection<FirearmItem> List => Dictionary.Values; + /// <summary> + /// Contains all the handlers for constructing wrappers for the associated base game types. + /// </summary> + private static readonly Dictionary<ItemType, Func<Firearm, FirearmItem>> typeWrappers = []; + /// <summary> /// An internal constructor to prevent external instantiation. /// </summary> /// <param name="firearm">The base <see cref="Firearm"/> object.</param> - internal FirearmItem(Firearm firearm) - : base(firearm) + internal FirearmItem(Firearm firearm) : base(firearm) { Base = firearm; if (CanCache) Dictionary.Add(firearm, this); + + CacheModules(); + } + + /// <summary> + /// The base <see cref="Firearm"/> object. + /// </summary> + public new Firearm Base { get; } + + /// <summary> + /// Gets the total firearm's weight including attachments in kilograms. + /// </summary> + public new float Weight => Base.Weight; + + /// <summary> + /// Gets the total length of this firearm in inches. + /// </summary> + public float Length => Base.Length; + + /// <summary> + /// Gets the weight of the firearm in kilograms without any attachments. + /// </summary> + public float BaseWeight => Base.BaseLength; + + /// <summary> + /// Gets the length of the firearm in inches without any attachments. + /// </summary> + public float BaseLength => Base.BaseLength; + + /// <summary> + /// Gets whether the player can reload this firearm. + /// </summary> + public bool CanReload => IReloadUnloadValidatorModule.ValidateReload(Base); + + /// <summary> + /// Gets whether the player can unload this firearm. + /// </summary> + public bool CanUnload => IReloadUnloadValidatorModule.ValidateUnload(Base); + + /// <summary> + /// Gets the firearm's ammo type. + /// </summary> + /// <remarks> + /// May be <see cref="ItemType.None"/> if the firearm item is no longer valid or this firearm is <see cref="ParticleDisruptorItem"/>. + /// </remarks> + public ItemType AmmoType + { + get + { + if (_ammoContainerModule == null) + return ItemType.None; + + return _ammoContainerModule.AmmoType; + } + } + + /// <summary> + /// Gets or sets whether the firearm's hammer is cocked. + /// </summary> + /// <remarks> + /// Every automatic firearm requires <see cref="Cocked"/> to be <see langword="true"/> and <see cref="BoltLocked"/> to be <see langword="false"/> to be fired properly with chambered ammo. + /// </remarks> + public virtual bool Cocked + { + get + { + if (_actionModule is AutomaticActionModule actionModule) + return actionModule.Cocked; + + return false; + } + set + { + if (_actionModule is not AutomaticActionModule actionModule) + { + Logger.Error($"Unable to set {nameof(Cocked)} as this firearm's {nameof(IActionModule)} is invalid"); + return; + } + + actionModule.Cocked = value; + actionModule.ServerResync(); + } + } + + /// <summary> + /// Gets or sets whether the firearm's bolt is in rear position.<para/> + /// This is only used by closed-bolt firearms. + /// </summary> + public virtual bool BoltLocked + { + get + { + if (_actionModule is AutomaticActionModule actionModule) + return actionModule.BoltLocked; + + return false; + } + set + { + if (_actionModule is not AutomaticActionModule actionModule) + { + Logger.Error($"Unable to set {nameof(BoltLocked)} as this firearm's {nameof(IActionModule)} is invalid"); + return; + } + + actionModule.BoltLocked = value; + actionModule.ServerResync(); + } + } + + /// <summary> + /// Gets if the firearm fires from an open bolt, that means the chambers are not capable of storing any ammo in <see cref="ChamberedAmmo"/>. + /// </summary> + public virtual bool OpenBolt + { + get + { + if (_actionModule is AutomaticActionModule actionModule) + return actionModule.OpenBolt; + + return false; + } + } + + /// <summary> + /// Gets the firerate with current attachment's modifiers applied. + /// </summary> + public float Firerate + { + get + { + if (_actionModule != null) + return _actionModule.DisplayCyclicRate; + + return 0; + } + } + + /// <summary> + /// Gets or sets the attachments code for this firearm.<br/> + /// Attachments code is a binary representation of <see cref="Attachments"/> which are enabled/disabled.<br/> + /// For validation, see <see cref="ValidateAttachmentsCode(uint)"/>. + /// </summary> + public uint AttachmentsCode + { + get => Base.GetCurrentAttachmentsCode(); + set + { + Base.ApplyAttachmentsCode(value, true); + Base.ServerResendAttachmentCode(); + } + } + + /// <summary> + /// Gets or sets whether this firearm has inserted magazine.<br/> + /// An empty magazine is inserted when set to <see langword="true"/>.<br/> + /// Remaining ammo from the magazine is inserted back into player's inventory when removed. + /// </summary> + /// <remarks> + /// Firearms with no external or internal magazine will always return <see langword="false"/>. + /// </remarks> + public virtual bool MagazineInserted + { + get + { + if (_magazineControllerModule == null) + return false; + + return _magazineControllerModule.MagazineInserted; + } + set + { + if (_magazineControllerModule is not MagazineModule magazineModule) + { + Logger.Error($"Unable to set {nameof(MagazineInserted)} as this firearm's {nameof(IMagazineControllerModule)} is null"); + return; + } + + if (value) + magazineModule.ServerInsertEmptyMagazine(); + else + magazineModule.ServerRemoveMagazine(); + } + } + + /// <summary> + /// Gets or sets the stored ammo in a <b>ammo container</b> for this firearm. + /// </summary> + /// <remarks> + /// Ammo in magazine beyond <see cref="MaxAmmo"/> when pickup up this firearm again from the ground is added back to player's inventory. + /// </remarks> + public virtual int StoredAmmo + { + get + { + if (_ammoContainerModule == null) + return 0; + + return _ammoContainerModule.AmmoStored; + } + set + { + if (_ammoContainerModule == null) + { + Logger.Error($"Unable to set {nameof(StoredAmmo)} as this firearm's {nameof(IPrimaryAmmoContainerModule)} is null"); + return; + } + + int toAdd = value - _ammoContainerModule.AmmoStored; + _ammoContainerModule.ServerModifyAmmo(toAdd); + } + } + + /// <summary> + /// Gets the maximum ammo the firearm can have in its <b>ammo container</b>. Attachment modifiers are taken into account when calculating it. + /// </summary> + public int MaxAmmo + { + get + { + if (_ammoContainerModule == null) + return 0; + + return _ammoContainerModule.AmmoMax; + } + } + + /// <summary> + /// Gets or sets the current ammo in the chamber. + /// <para><see cref="OpenBolt"/> firearms do not use this value and take ammo directly from it's ammo container.</para> + /// </summary> + public virtual int ChamberedAmmo + { + get + { + if (_actionModule is AutomaticActionModule actionModule) + return actionModule.AmmoStored; + + return 0; + } + set + { + if (_actionModule is not AutomaticActionModule actionModule) + { + Logger.Error($"Unable to set {nameof(ChamberedAmmo)} as this firearm's {nameof(IActionModule)} is not valid."); + return; + } + + actionModule.AmmoStored = value; + actionModule.ServerResync(); + } + } + + /// <summary> + /// Gets or sets the maximum ammo in chamber. + /// Visual side may be incorrect.<para/> + /// For automatic firearms, this value won't properly sync above 16 as only 4 bits are used for the chambered sync to the client. + /// </summary> + public virtual int ChamberMax + { + get + { + if (_actionModule is AutomaticActionModule actionModule) + return actionModule.ChamberSize; + + + return 0; + } + set + { + if (_actionModule is not AutomaticActionModule actionModule) + { + Logger.Error($"Unable to set {nameof(ChamberMax)} as this firearm's {nameof(IActionModule)} is not valid."); + return; + } + + actionModule.ChamberSize = value; + } + } + + /// <summary> + /// Gets or sets whether the firearm's flashlight attachment is enabled and is emitting light. + /// </summary> + public bool FlashlightEnabled + { + get + { + foreach (Attachment attachment in Attachments) + { + if (attachment is not FlashlightAttachment flashlightAttachment) + continue; + + return flashlightAttachment.IsEnabled && flashlightAttachment.IsEmittingLight; + } + + return false; + } + set + { + foreach (Attachment attachment in Attachments) + { + if (attachment is not FlashlightAttachment flashlightAttachment) + continue; + + flashlightAttachment.ServerSendStatus(value); + } + } + } + + /// <summary> + /// All attachment used by this firearm.<br/> + /// <b>Set the attachments status using <see cref="AttachmentsCode"/></b> + /// </summary> + public Attachment[] Attachments => Base.Attachments; + + /// <summary> + /// All modules used by this firearm. + /// Modules are the main scripts defining all of the functionality of a firearm. + /// </summary> + public ModuleBase[] Modules => Base.Modules; + + /// <summary> + /// Gets all available attachments names of this firearms. + /// </summary> + public IEnumerable<AttachmentName> AvailableAttachmentsNames + { + get + { + foreach (Attachment attachment in Attachments) + { + yield return attachment.Name; + } + } + } + + /// <summary> + /// Gets all enabled attachments of this firearm. + /// </summary> + public IEnumerable<Attachment> ActiveAttachments + { + get + { + foreach (Attachment attachment in Attachments) + { + if (attachment.IsEnabled) + yield return attachment; + } + } + } + + /// <summary> + /// Module for the magazine. + /// </summary> + protected IPrimaryAmmoContainerModule _ammoContainerModule; + + /// <summary> + /// Module for firearm's chamber. + /// </summary> + protected IActionModule _actionModule; + + /// <summary> + /// Module for handling gun's reloading and unloading. + /// </summary> + protected IReloaderModule _reloaderModule; + + /// <summary> + /// Module for handling gun's magazine. + /// </summary> + protected IMagazineControllerModule _magazineControllerModule; + + /// <summary> + /// Gets whether the provided attachments code is valid and can be applied. + /// </summary> + /// <param name="code">The code to validate.</param> + /// <returns>Whether the code is valid and can be applied.</returns> + public bool CheckAttachmentsCode(uint code) => ValidateAttachmentsCode(code) == code; + + /// <summary> + /// Gets whether the provided attachment names are valid together and only 1 belongs to each category. + /// </summary> + /// <param name="attachments">Attachment names.</param> + /// <returns>Whether the attachments can be applied together.</returns> + public bool CheckAttachmentsCode(params AttachmentName[] attachments) + { + uint rawCode = GetCodeFromAttachmentNamesRaw(attachments); + + return rawCode == ValidateAttachmentsCode(rawCode); + } + + /// <summary> + /// Gets validated attachments code. + /// Validation of the code is following: + /// <list type="bullet"> + /// <item>Only 1 attachments from the same <see cref="AttachmentSlot"/> is applied. If multiple ones are enabled, only the first one is selected.</item> + /// <item><see cref="AttachmentSlot"/> without any attachents assigned sets the first one to enabled.</item> + /// </list> + /// </summary> + /// <param name="code">The code to be validated.</param> + /// <returns>Validated code with missing attachments added for category and only 1 attachment per category selected.</returns> + public uint ValidateAttachmentsCode(uint code) => Base.ValidateAttachmentsCode(code); + + /// <inheritdoc cref="ValidateAttachmentsCode(uint)"/> + /// <param name="attachments">Array of attachment names to be applied and validated.</param> + public uint ValidateAttachmentsCode(params AttachmentName[] attachments) + { + return ValidateAttachmentsCode(GetCodeFromAttachmentNamesRaw(attachments)); + } + + /// <summary> + /// Gets attachments code from <see cref="AttachmentName"/>s. This value is NOT validated. + /// </summary> + /// <param name="attachments">Attachment names.</param> + /// <returns>Unchecked attachments code.</returns> + public uint GetCodeFromAttachmentNamesRaw(AttachmentName[] attachments) + { + uint resultCode = 0; + + uint bin = 1; + foreach (Attachment attachment in Attachments) + { + if (attachments.Contains(attachment.Name)) + resultCode += bin; + + bin *= 2; + } + + return resultCode; + } + + /// <summary> + /// Reloads the firearm if <see cref="CanReload"/> is <see langword="true"/>. + /// </summary> + /// <returns>Whether the player started to reload.</returns> + public bool Reload() + { + if (_reloaderModule is not AnimatorReloaderModuleBase animatorModule) + { + Logger.Error($"Unable to reload this firearm as it's animator module is invalid"); + return false; + } + + return animatorModule.ServerTryReload(); + } + + /// <summary> + /// Unloads the firearm if <see cref="CanUnload"/> is <see langword="true"/>. + /// </summary> + /// <returns>Whether the player started the unload.</returns> + public bool Unload() + { + if (_reloaderModule is not AnimatorReloaderModuleBase animatorModule) + { + Logger.Error($"Unable to unload this firearm as it's animator module is invalid"); + return false; + } + + return animatorModule.ServerTryUnload(); } /// <summary> @@ -42,15 +522,35 @@ internal override void OnRemove() } /// <summary> - /// The base <see cref="Firearm"/> object. + /// Caches modules used by the firearm. /// </summary> - public new Firearm Base { get; } + protected virtual void CacheModules() + { + foreach (ModuleBase module in Modules) + { + switch (module) + { + case IPrimaryAmmoContainerModule ammoModule: + _ammoContainerModule = ammoModule; + continue; + case IActionModule actionModule: + _actionModule = actionModule; + continue; + case IReloaderModule reloaderModule: + _reloaderModule = reloaderModule; + continue; + case IMagazineControllerModule magazineControllerModule: + _magazineControllerModule = magazineControllerModule; + continue; + } + } + } /// <summary> - /// Gets the firearm item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="Firearm"/> was not null. + /// Gets the firearm item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="Firearm"/> was not <see langword="null"/>. /// </summary> /// <param name="firearm">The <see cref="Base"/> of the item.</param> - /// <returns>The requested item or null.</returns> + /// <returns>The requested item or <see langword="null"/>.</returns> [return: NotNullIfNotNull(nameof(firearm))] public static FirearmItem? Get(Firearm? firearm) { @@ -59,4 +559,27 @@ internal override void OnRemove() return Dictionary.TryGetValue(firearm, out FirearmItem item) ? item : (FirearmItem)CreateItemWrapper(firearm); } + + /// <summary> + /// Creates a firearm wrapper or it's subtype. + /// </summary> + /// <param name="firearm">The base game firearm.</param> + /// <returns>Firearm wrapper object.</returns> + internal static FirearmItem CreateFirearmWrapper(Firearm firearm) + { + if (!typeWrappers.TryGetValue(firearm.ItemTypeId, out Func<Firearm, FirearmItem> ctor)) + return new FirearmItem(firearm); + + return ctor(firearm); + } + + /// <summary> + /// A private method to handle the addition of wrapper handlers. + /// </summary> + /// <param name="itemType">Item type of the target firearm.</param> + /// <param name="constructor">A handler to construct the wrapper with the base game instance.</param> + private static void Register(ItemType itemType, Func<Firearm, FirearmItem> constructor) + { + typeWrappers.Add(itemType, x => constructor(x)); + } } diff --git a/LabApi/Features/Wrappers/Items/Firearm/ParticleDisruptorItem.cs b/LabApi/Features/Wrappers/Items/Firearm/ParticleDisruptorItem.cs deleted file mode 100644 index f62c5933..00000000 --- a/LabApi/Features/Wrappers/Items/Firearm/ParticleDisruptorItem.cs +++ /dev/null @@ -1,62 +0,0 @@ -using InventorySystem.Items.Firearms; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; - -namespace LabApi.Features.Wrappers; - -/// <summary> -/// The wrapper representing <see cref="ParticleDisruptor"/>. -/// </summary> -public class ParticleDisruptorItem : FirearmItem -{ - /// <summary> - /// Contains all the cached particle disruptor items, accessible through their <see cref="ParticleDisruptor"/>. - /// </summary> - public new static Dictionary<ParticleDisruptor, ParticleDisruptorItem> Dictionary { get; } = []; - - /// <summary> - /// A reference to all instances of <see cref="ParticleDisruptorItem"/>. - /// </summary> - public new static IReadOnlyCollection<ParticleDisruptorItem> List => Dictionary.Values; - - /// <summary> - /// An internal constructor to prevent external instantiation. - /// </summary> - /// <param name="particleDisruptor">The base <see cref="ParticleDisruptor"/> object.</param> - internal ParticleDisruptorItem(ParticleDisruptor particleDisruptor) - : base(particleDisruptor) - { - Base = particleDisruptor; - - if (CanCache) - Dictionary.Add(particleDisruptor, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); - } - - /// <summary> - /// The base <see cref="ParticleDisruptor"/> object. - /// </summary> - public new ParticleDisruptor Base { get; } - - /// <summary> - /// Gets the particle disruptor item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="ParticleDisruptor"/> was not null. - /// </summary> - /// <param name="particleDisruptor">The <see cref="Base"/> of the item.</param> - /// <returns>The requested item or null.</returns> - [return: NotNullIfNotNull(nameof(particleDisruptor))] - public static ParticleDisruptorItem? Get(ParticleDisruptor? particleDisruptor) - { - if (particleDisruptor == null) - return null; - - return Dictionary.TryGetValue(particleDisruptor, out ParticleDisruptorItem item) ? item : (ParticleDisruptorItem)CreateItemWrapper(particleDisruptor); - } -} diff --git a/LabApi/Features/Wrappers/Items/Firearm/SpecialFirearms/ParticleDisruptorItem.cs b/LabApi/Features/Wrappers/Items/Firearm/SpecialFirearms/ParticleDisruptorItem.cs new file mode 100644 index 00000000..2fb9c24d --- /dev/null +++ b/LabApi/Features/Wrappers/Items/Firearm/SpecialFirearms/ParticleDisruptorItem.cs @@ -0,0 +1,155 @@ +using InventorySystem.Items.Firearms; +using InventorySystem.Items.Firearms.Modules; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using static InventorySystem.Items.Firearms.Modules.DisruptorActionModule; + +namespace LabApi.Features.Wrappers; + +/// <summary> +/// The wrapper representing <see cref="ParticleDisruptor"/>. +/// </summary> +public class ParticleDisruptorItem : FirearmItem +{ + /// <summary> + /// Contains all the cached particle disruptor items, accessible through their <see cref="ParticleDisruptor"/>. + /// </summary> + public new static Dictionary<ParticleDisruptor, ParticleDisruptorItem> Dictionary { get; } = []; + + /// <summary> + /// A reference to all instances of <see cref="ParticleDisruptorItem"/>. + /// </summary> + public new static IReadOnlyCollection<ParticleDisruptorItem> List => Dictionary.Values; + + /// <summary> + /// An internal constructor to prevent external instantiation. + /// </summary> + /// <param name="particleDisruptor">The base <see cref="ParticleDisruptor"/> object.</param> + internal ParticleDisruptorItem(ParticleDisruptor particleDisruptor) : base(particleDisruptor) + { + Base = particleDisruptor; + + if (CanCache) + Dictionary.Add(particleDisruptor, this); + } + + /// <summary> + /// An internal method to remove itself from the cache when the base object is destroyed. + /// </summary> + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); + } + + /// <summary> + /// The base <see cref="ParticleDisruptor"/> object. + /// </summary> + public new ParticleDisruptor Base { get; } + + /// <summary> + /// Gets the current firing state. + /// </summary> + public FiringState FiringState + { + get + { + if (_actionModule is DisruptorActionModule actionModule) + return actionModule.CurFiringState; + + return FiringState.None; + } + } + + /// <summary> + /// Gets whether the disruptor has single-shot mode selected. + /// </summary> + public bool SingleShotMode + { + get + { + if (_selectorModule is DisruptorModeSelector selectorModule) + return selectorModule.SingleShotSelected; + + return false; + } + } + + /// <summary> + /// Gets the amount of chambered ammo in the chamber. + /// </summary> + public override int ChamberedAmmo + { + get + { + if (_actionModule is DisruptorActionModule actionModule) + return actionModule.IsLoaded ? 1 : 0; + + return 0; + } + } + + /// <summary> + /// Gets the maximum chambered ammo. + /// </summary> + public override int ChamberMax + { + get => 1; + } + + /// <summary> + /// Gets whether the firearm is cocked and can fire. + /// </summary> + public override bool Cocked + { + get + { + if (_actionModule is DisruptorActionModule actionModule) + return actionModule.IsLoaded; + + return false; + } + } + + /// <inheritdoc/> + public override bool OpenBolt => true; + + private DisruptorModeSelector _selectorModule; + + /// <summary> + /// Destroys this disruptor and plays the destroy animation on the client. + /// </summary> + public void Destroy() + { + Base.ServerDestroyItem(); + } + + /// <inheritdoc/> + protected override void CacheModules() + { + base.CacheModules(); + + foreach (ModuleBase module in Modules) + { + if (module is DisruptorModeSelector selectorModule) + { + _selectorModule = selectorModule; + break; + } + } + } + + /// <summary> + /// Gets the particle disruptor item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="ParticleDisruptor"/> was not <see langword="null"/>. + /// </summary> + /// <param name="particleDisruptor">The <see cref="Base"/> of the item.</param> + /// <returns>The requested item or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(particleDisruptor))] + public static ParticleDisruptorItem? Get(ParticleDisruptor? particleDisruptor) + { + if (particleDisruptor == null) + return null; + + return Dictionary.TryGetValue(particleDisruptor, out ParticleDisruptorItem item) ? item : (ParticleDisruptorItem)CreateItemWrapper(particleDisruptor); + } +} diff --git a/LabApi/Features/Wrappers/Items/Firearm/SpecialFirearms/RevolverFirearm.cs b/LabApi/Features/Wrappers/Items/Firearm/SpecialFirearms/RevolverFirearm.cs new file mode 100644 index 00000000..69941631 --- /dev/null +++ b/LabApi/Features/Wrappers/Items/Firearm/SpecialFirearms/RevolverFirearm.cs @@ -0,0 +1,185 @@ +using InventorySystem.Items.Firearms; +using InventorySystem.Items.Firearms.Modules; +using LabApi.Features.Console; +using System.Collections.Generic; +using static InventorySystem.Items.Firearms.Modules.CylinderAmmoModule; + +namespace LabApi.Features.Wrappers; + +/// <summary> +/// Wrapper for revolver firearm. +/// </summary> +public class RevolverFirearm : FirearmItem +{ + /// <summary> + /// An internal constructor to prevent external instantiation. + /// </summary> + /// <param name="firearm">The base <see cref="Firearm"/> object.</param> + internal RevolverFirearm(Firearm firearm) : base(firearm) + { + } + + /// <inheritdoc/> + public override bool OpenBolt => false; + + /// <summary> + /// Gets collection of all active chambers. The first chamber is the one aligned with the barrel.<br/> + /// Each subsequent index corresponds to the next chambers that will become aligned with the barrel when the cylinder rotates in its intended direction.<br/> + /// <b>Note that double-action revolvers rotate the cylinder right before firing, which means the 0th element isn't necessarily the next round to be fired (unless the revolver is already cocked).</b><para/> + /// </summary> + public IEnumerable<Chamber> Chambers + { + get + { + if (_ammoContainerModule is CylinderAmmoModule) + return GetChambersArrayForSerial(Serial, MaxAmmo); + + return null; + } + } + + /// <inheritdoc/> + public override bool Cocked + { + get + { + if (_actionModule is DoubleActionModule actionModule) + return actionModule.Cocked; + + return false; + } + set + { + if (_actionModule is not DoubleActionModule actionModule) + { + Logger.Error($"Unable to set {nameof(Cocked)} as the {nameof(DoubleActionModule)} is null."); + return; + } + + actionModule.Cocked = value; + } + } + + /// <summary> + /// Gets or sets the stored ammo in a <b>ammo container</b> for this firearm. + /// </summary> + /// <remarks> + /// Stored ammo in revolver firearm cannot exceed its <see cref="FirearmItem.MaxAmmo"/> and any additional values are ignored. + /// </remarks> + public override int StoredAmmo + { + get + { + if (_ammoContainerModule is CylinderAmmoModule ammoModule) + return ammoModule.AmmoStored; + + return 0; + } + set + { + if (_ammoContainerModule is not CylinderAmmoModule ammoModule) + { + Logger.Error($"Unable to set {nameof(StoredAmmo)} as the {nameof(CylinderAmmoModule)} is null."); + return; + } + + foreach (Chamber chamber in Chambers) + { + chamber.ServerSyncState = ChamberState.Empty; + } + + ammoModule.ServerModifyAmmo(value); + } + } + + /// <summary> + /// Gets or sets the current ammo in the chamber.<para/> + /// Revolver's <see cref="ChamberedAmmo"/> only accounts for the currently aligned chamber with the barrel. Therefore the maximum of chambered ammo is 1 (live round) or 0 (empty / discharged). + /// Any value greater than 1 is counted as live round. + /// </summary> + public override int ChamberedAmmo + { + get + { + return GetChambersArrayForSerial(Serial, MaxAmmo)[0].ServerSyncState == ChamberState.Live ? 1 : 0; + } + set + { + if (_actionModule is not DoubleActionModule actionModule) + { + Logger.Error($"Unable to set {nameof(ChamberedAmmo)} as the {nameof(DoubleActionModule)} is null."); + return; + } + + SetChamberStatus(0, value == 0 ? ChamberState.Empty : ChamberState.Live); + } + } + + private RevolverRouletteModule _rouletteModule; + + /// <summary> + /// Sets the status of the chamber at <paramref name="index"/>. 0th element is the one currently aligned with the barrel.<para/> + /// <b>Indexes of each round are clockwise.</b> + /// </summary> + /// <param name="index">Index of the chamber clockwise. Starting at barrel aligned chamber.</param> + /// <param name="state">Target state of the chamber.</param> + public void SetChamberStatus(int index, ChamberState state) + { + if (_ammoContainerModule is not CylinderAmmoModule ammoModule) + { + Logger.Error($"Unable to set chamber status, this firearm doesn't have {nameof(CylinderAmmoModule)}!"); + return; + } + + Chamber[] chambers = GetChambersArrayForSerial(Serial, MaxAmmo); + chambers[index].ServerSyncState = state; + + ammoModule.ServerResync(); + } + + /// <summary> + /// Rotates the chamber counter-clockwise (positive numbers) or clockwise (negative numbers) <paramref name="amount"/> times. + /// No animation is played client-side. + /// </summary> + /// <param name="amount">The amount of times to rotate this cylinder.</param> + public void Rotate(int amount) + { + if (_ammoContainerModule is not CylinderAmmoModule ammoModule) + { + Logger.Error($"Unable to rotate this cylinder, this firearm doesn't have {nameof(CylinderAmmoModule)}!"); + return; + } + + ammoModule.RotateCylinder(amount); + } + + /// <summary> + /// Attempts to spin the revolver if the firearm is't busy doing something else. + /// </summary> + /// <returns>Whether the spin request was successful.</returns> + public bool TrySpin() + { + if (_rouletteModule is not RevolverRouletteModule ammoModule) + { + Logger.Error($"Unable to spin this cylinder, this firearm doesn't have {nameof(RevolverRouletteModule)}!"); + return false; + } + + return _rouletteModule.ServerTrySpin(); + } + + /// <inheritdoc/> + protected override void CacheModules() + { + base.CacheModules(); + + foreach (ModuleBase module in Modules) + { + if (module is RevolverRouletteModule rouletteModule) + { + _rouletteModule = rouletteModule; + break; + } + } + } +} diff --git a/LabApi/Features/Wrappers/Items/Firearm/SpecialFirearms/Scp127Firearm.cs b/LabApi/Features/Wrappers/Items/Firearm/SpecialFirearms/Scp127Firearm.cs new file mode 100644 index 00000000..748abb27 --- /dev/null +++ b/LabApi/Features/Wrappers/Items/Firearm/SpecialFirearms/Scp127Firearm.cs @@ -0,0 +1,213 @@ +using InventorySystem.Items.Firearms; +using InventorySystem.Items.Firearms.Modules; +using InventorySystem.Items.Firearms.Modules.Scp127; +using System.Collections.Generic; +using UnityEngine; +using static InventorySystem.Items.Firearms.Modules.Scp127.Scp127VoiceTriggerBase; +using Logger = LabApi.Features.Console.Logger; + +namespace LabApi.Features.Wrappers; + +/// <summary> +/// Wrapper for SCP-127. +/// </summary> +public class Scp127Firearm : FirearmItem +{ + /// <summary> + /// An internal constructor to prevent external instantiation. + /// </summary> + /// <param name="firearm">The base <see cref="Firearm"/> object.</param> + internal Scp127Firearm(Firearm firearm) : base(firearm) + { + } + + /// <inheritdoc/> + public override bool OpenBolt => false; + + /// <summary> + /// Gets all players who are friended with this SCP.<br/> + /// This means every player who talked with this SCP at least once and is still alive. + /// </summary> + public IEnumerable<Player> Friends + { + get + { + if (!Scp127VoiceLineManagerModule.FriendshipMemory.TryGetValue(Serial, out HashSet<uint> friendNetIds)) + yield break; + + foreach (uint netId in friendNetIds) + yield return Player.Get(netId); + } + } + + /// <summary> + /// Gets or sets the <see cref="Scp127Tier"/> the firearm has. + /// </summary> + public Scp127Tier Tier + { + get + { + if (_tierModule == null) + return Scp127Tier.Tier1; + + return _tierModule.CurTier; + } + set + { + if (_tierModule == null) + { + Logger.Error($"Unable to set {nameof(Tier)}, {nameof(Scp127TierManagerModule)} is null"); + return; + } + + _tierModule.CurTier = value; + } + } + + /// <summary> + /// Gets or sets the experience amount of this firearm. + /// </summary> + public float Experience + { + get + { + if (_tierModule == null) + return 0; + + return _tierModule.ServerExp; + } + set + { + if (_tierModule == null) + { + Logger.Error($"Unable to set {nameof(Experience)}, {nameof(Scp127TierManagerModule)} is null"); + return; + } + + _tierModule.ServerExp = value; + } + } + + /// <inheritdoc/> + public override int ChamberedAmmo + { + get + { + if (_actionModule is Scp127ActionModule actionModule) + return actionModule.AmmoStored; + + return 0; + } + set + { + if (_actionModule is not Scp127ActionModule actionModule) + { + Logger.Error($"Unable to set {nameof(ChamberedAmmo)} as the action module is null."); + return; + } + + actionModule.ChamberSize = value; + actionModule.ServerResync(); + } + } + + /// <inheritdoc/> + public override int ChamberMax + { + get + { + if (_actionModule is Scp127ActionModule actionModule) + return actionModule.ChamberSize; + + return 0; + } + set + { + if (_actionModule is not Scp127ActionModule actionModule) + { + Logger.Error($"Unable to set {nameof(ChamberMax)} as the action module is null."); + return; + } + + actionModule.ChamberSize = value; + } + } + + /// <inheritdoc/> + public override bool MagazineInserted + { + get + { + return true; + } + set + { + if (_magazineControllerModule is Scp127MagazineModule magazineModule) + { + Logger.Error($"Unable to set {nameof(MagazineInserted)} as SCP-127's magazine is not detachable."); + return; + } + } + } + + + /// <summary> + /// Gets or sets the stored ammo in a <b>ammo container</b> for this firearm. + /// </summary> + /// <remarks> + /// SCP-127 stored ammo is capped at <see cref="FirearmItem.MaxAmmo"/> and any values beyond are ignored. + /// </remarks> + public override int StoredAmmo + { + get => base.StoredAmmo; + set => base.StoredAmmo = value; + } + + private Scp127TierManagerModule _tierModule; + + private Scp127VoiceLineManagerModule _voiceModule; + + /// <summary> + /// Plays a specific voiceline defined by the <see cref="Scp127VoiceLinesTranslation"/>. + /// </summary> + /// <param name="voiceline">The target voiceline to play.</param> + /// <param name="priority">The priority to play this voice line with.</param> + public void PlayVoiceline(Scp127VoiceLinesTranslation voiceline, VoiceLinePriority priority = VoiceLinePriority.Normal) + { + if (_voiceModule == null) + { + Logger.Error($"Unable to play voiceline, {nameof(Scp127VoiceLineManagerModule)} is null"); + return; + } + + if (!_voiceModule.TryFindVoiceLine(voiceline, out Scp127VoiceTriggerBase trigger, out AudioClip clip)) + { + Logger.Error($"Unable to play voiceline {voiceline} as it wasn't found"); + return; + } + + _voiceModule.ServerSendVoiceLine(trigger, null, clip, (byte)priority); + + } + + /// <inheritdoc/> + protected override void CacheModules() + { + base.CacheModules(); + + foreach (ModuleBase module in Modules) + { + if (module is Scp127TierManagerModule tierModule) + { + _tierModule = tierModule; + continue; + } + + if (module is Scp127VoiceLineManagerModule voiceModule) + { + _voiceModule = voiceModule; + continue; + } + } + } +} diff --git a/LabApi/Features/Wrappers/Items/Firearm/SpecialFirearms/ShotgunFirearm.cs b/LabApi/Features/Wrappers/Items/Firearm/SpecialFirearms/ShotgunFirearm.cs new file mode 100644 index 00000000..20419b74 --- /dev/null +++ b/LabApi/Features/Wrappers/Items/Firearm/SpecialFirearms/ShotgunFirearm.cs @@ -0,0 +1,138 @@ +using InventorySystem.Items.Firearms; +using InventorySystem.Items.Firearms.Modules; +using LabApi.Features.Console; + +namespace LabApi.Features.Wrappers; + +/// <summary> +/// Wrapper for shotgun firearm. +/// </summary> +public class ShotgunFirearm : FirearmItem +{ + /// <summary> + /// An internal constructor to prevent external instantiation. + /// </summary> + /// <param name="firearm">The base <see cref="Firearm"/> object.</param> + internal ShotgunFirearm(Firearm firearm) : base(firearm) + { + } + + /// <inheritdoc/> + public override bool OpenBolt => false; + + /// <summary> + /// Gets whether any of the hammers is cocked. + /// Sets the cocked status of ALL hammers. + /// </summary> + public override bool Cocked + { + get + { + if (_actionModule is PumpActionModule actionModule) + return actionModule.SyncCocked == actionModule.Barrels; + + return false; + } + + set + { + if (_actionModule is not PumpActionModule actionModule) + { + Logger.Error($"Unable to set {nameof(Cocked)} as it is invalid."); + return; + } + + actionModule.SyncCocked = actionModule.Barrels; + } + } + + /// <summary> + /// Gets or sets the amount of currently cocked chambers. + /// </summary> + public int CockedChambers + { + get + { + if (_actionModule is PumpActionModule actionModule) + return actionModule.SyncCocked; + + return 0; + } + set + { + if (_actionModule is not PumpActionModule actionModule) + { + Logger.Error($"Unable to set {nameof(CockedChambers)} as it is invalid."); + return; + } + + actionModule.SyncCocked = value; + } + } + + /// <summary> + /// Gets or sets the amount of barrels this shotgun has. + /// Useful when creating custom weapons.<br/> + /// It is recommended to set this value before the shotgun has been pumped by the player, otherwise you might need to set <see cref="CockedChambers"/> and <see cref="ChamberedAmmo"/> to the correct value. + /// </summary> + public override int ChamberMax + { + get + { + if (_actionModule is PumpActionModule actionModule) + return actionModule.Barrels; + + return 0; + } + set + { + if (_actionModule is not PumpActionModule actionModule) + { + Logger.Error($"Unable to set {nameof(ChamberMax)} as it is invalid."); + return; + } + + actionModule.Barrels = value; + } + } + + /// <summary> + /// Gets or sets the current ammo in the barrels. + /// </summary> + public override int ChamberedAmmo + { + get + { + if (_actionModule is PumpActionModule actionModule) + return actionModule.AmmoStored; + + return 0; + } + set + { + if (_actionModule is not PumpActionModule actionModule) + { + Logger.Error($"Unable to set {nameof(ChamberedAmmo)} as it is null."); + return; + } + + actionModule.AmmoStored = value; + } + } + + /// <summary> + /// Schedules pumping for this firearm.<br/> + /// Value of 0 pumps the firearm instantly. Any value above 0 delays the pump by <paramref name="shotsFired"/> * 0.5 second. + /// </summary> + /// <param name="shotsFired">The amount of shots that has been fired. Pumping is delayed by <paramref name="shotsFired"/> * 0.5 second.</param> + public void Pump(int shotsFired = 0) + { + if (_actionModule is not PumpActionModule actionModule) + { + Logger.Error($"Unable to pump {nameof(PumpActionModule)} as it is null."); + return; + } + + actionModule.SchedulePumping(shotsFired); + } +} diff --git a/LabApi/Features/Wrappers/Items/Item.cs b/LabApi/Features/Wrappers/Items/Item.cs index 088c79f6..59defed4 100644 --- a/LabApi/Features/Wrappers/Items/Item.cs +++ b/LabApi/Features/Wrappers/Items/Item.cs @@ -51,8 +51,9 @@ internal static void Initialize() Register<Scp268>(x => new Scp268Item(x)); Register<InventorySystem.Items.Usables.Scp1344.Scp1344Item>(x => new Scp1344Item(x)); - Register<Firearm>(x => new FirearmItem(x)); - Register<ParticleDisruptor>(x => new ParticleDisruptorItem(x)); + Register<Firearm>(FirearmItem.CreateFirearmWrapper); + Register<ParticleDisruptor>(FirearmItem.CreateFirearmWrapper); + Register<InventorySystem.Items.Jailbird.JailbirdItem>(x => new JailbirdItem(x)); Register<Coin>(x => new CoinItem(x)); @@ -361,7 +362,7 @@ private static void AddItem(ItemBase item) } catch (Exception e) { - Console.Logger.InternalError($"Failed to handle item creation with error: {e}"); + Logger.InternalError($"Failed to handle item creation with error: {e}"); } } From 776126ea9956d5851e825ebad442b7e97ab397de Mon Sep 17 00:00:00 2001 From: Evelyn <85962933+Misfiy@users.noreply.github.com> Date: Thu, 24 Jul 2025 12:57:06 +0200 Subject: [PATCH 057/215] Player stuff (#204) --- LabApi/Features/Wrappers/Players/Player.cs | 38 ++++++++++++++++++- .../Wrappers/{Players => Server}/Server.cs | 0 2 files changed, 37 insertions(+), 1 deletion(-) rename LabApi/Features/Wrappers/{Players => Server}/Server.cs (100%) diff --git a/LabApi/Features/Wrappers/Players/Player.cs b/LabApi/Features/Wrappers/Players/Player.cs index 1d58a933..341503fb 100644 --- a/LabApi/Features/Wrappers/Players/Player.cs +++ b/LabApi/Features/Wrappers/Players/Player.cs @@ -25,6 +25,7 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; +using InventorySystem.Items.Usables.Scp330; using UnityEngine; using Utils.Networking; using Utils.NonAllocLINQ; @@ -1334,6 +1335,41 @@ public void ClearInventory(bool clearAmmo = true, bool clearItems = true) if (clearItems) ClearItems(); } + + /// <summary> + /// Gives a candy to the player. + /// </summary> + /// <param name="candy">The candy to give the player.</param> + /// <param name="reason">The reason to grant the candy bag.</param> + public void GiveCandy(CandyKindID candy, ItemAddReason reason) + => ReferenceHub.GrantCandy(candy, reason); + + /// <summary> + /// Gives a random candy to the player. + /// </summary> + /// <param name="reason">The reason to grant the candy bag.</param> + /// <remarks>This will use <see cref="Scp330Candies.GetRandom"/>, meaning it will use <see cref="ICandy.SpawnChanceWeight"/> to choose the candy.</remarks> + public void GiveRandomCandy(ItemAddReason reason = ItemAddReason.AdminCommand) + => GiveCandy(Scp330Candies.GetRandom(), reason); + + /// <summary> + /// Checks if a player has the specified <see cref="PlayerPermissions"/>. + /// </summary> + /// <param name="permission">The permission to check the player for.</param> + /// <returns>Whether the permission check was successful.</returns> + public bool HasPermission(PlayerPermissions permission) + { + PlayerPermissions currentPerms = (PlayerPermissions)ReferenceHub.serverRoles.Permissions; + return currentPerms.HasFlag(permission); + } + + /// <summary> + /// Adds regeneration to the player. + /// </summary> + /// <param name="rate">The rate to heal per second.</param> + /// <param name="duration">How long the regeneration should last.</param> + public void AddRegeneration(float rate, float duration) + => Scp330Bag.AddSimpleRegeneration(ReferenceHub, rate, duration); /// <summary> /// Heals the player by the specified amount. @@ -1342,7 +1378,7 @@ public void ClearInventory(bool clearAmmo = true, bool clearItems = true) public void Heal(float amount) => ReferenceHub.playerStats.GetModule<HealthStat>().ServerHeal(amount); /// <summary> - /// Creates and run a new AHP proccess. + /// Creates and run a new AHP process. /// </summary> /// <param name="amount">Amount of AHP to be added.</param> /// <param name="limit">Adds limit to the AHP.</param> diff --git a/LabApi/Features/Wrappers/Players/Server.cs b/LabApi/Features/Wrappers/Server/Server.cs similarity index 100% rename from LabApi/Features/Wrappers/Players/Server.cs rename to LabApi/Features/Wrappers/Server/Server.cs From f57e241a03798ae4d0fd4b9871532c57335a1194 Mon Sep 17 00:00:00 2001 From: Evelyn <85962933+Misfiy@users.noreply.github.com> Date: Thu, 24 Jul 2025 12:57:26 +0200 Subject: [PATCH 058/215] why david (#203) --- .../Yaml/CustomConverters/CustomColorConverter.cs | 8 ++------ .../Yaml/CustomConverters/CustomVectorConverter.cs | 9 +-------- LabApi/Loader/Features/Yaml/YamlConfigParser.cs | 4 ++-- 3 files changed, 5 insertions(+), 16 deletions(-) diff --git a/LabApi/Loader/Features/Yaml/CustomConverters/CustomColorConverter.cs b/LabApi/Loader/Features/Yaml/CustomConverters/CustomColorConverter.cs index d755c349..7f4014f1 100644 --- a/LabApi/Loader/Features/Yaml/CustomConverters/CustomColorConverter.cs +++ b/LabApi/Loader/Features/Yaml/CustomConverters/CustomColorConverter.cs @@ -30,20 +30,16 @@ public class CustomColorConverter : IYamlTypeConverter if (!parser.TryReadMapping(out string key, out string val)) throw new ArgumentException($"Unable to parse {nameof(Color)}, no component at index {i} provided"); - if (!(key is "r" or "g" or "b" or "a")) + if (key is not ("r" or "g" or "b" or "a")) throw new ArgumentException($"Unable to parse {nameof(Color)}, invalid component name {key}. Only 'r', 'g', 'b' and 'a' are allowed"); storedValues[key] = float.Parse(val, CultureInfo.InvariantCulture); } parser.Consume<MappingEnd>(); - Color value = new Color(storedValues["r"], storedValues["g"], storedValues["b"], storedValues["a"]); + Color value = new(storedValues["r"], storedValues["g"], storedValues["b"], storedValues["a"]); return value; } - catch (ArgumentException) - { - throw; - } finally { DictionaryPool<string, float>.Release(storedValues); diff --git a/LabApi/Loader/Features/Yaml/CustomConverters/CustomVectorConverter.cs b/LabApi/Loader/Features/Yaml/CustomConverters/CustomVectorConverter.cs index 59dcb3a2..e16012ed 100644 --- a/LabApi/Loader/Features/Yaml/CustomConverters/CustomVectorConverter.cs +++ b/LabApi/Loader/Features/Yaml/CustomConverters/CustomVectorConverter.cs @@ -31,15 +31,12 @@ public class CustomVectorConverter : IYamlTypeConverter if (!parser.TryReadMapping(out string key, out string val)) throw new ArgumentException($"Unable to parse Vector, no component at index {idx} provided"); - - if (!(key is "x" or "y" or "z" or "w")) + if (key is not ("x" or "y" or "z" or "w")) throw new ArgumentException($"Unable to parse Vector, invalid component name {key}. Only 'x' 'y' 'z' and 'w' are allowed"); - if (storedValues.ContainsKey(key)) throw new ArgumentException($"Unable to parse Vector, duplicate component {key}"); - storedValues[key] = float.Parse(val, CultureInfo.InvariantCulture); idx++; } @@ -58,10 +55,6 @@ public class CustomVectorConverter : IYamlTypeConverter return result; } - catch (ArgumentException) - { - throw; - } finally { DictionaryPool<string, float>.Release(storedValues); diff --git a/LabApi/Loader/Features/Yaml/YamlConfigParser.cs b/LabApi/Loader/Features/Yaml/YamlConfigParser.cs index 8b6f58ee..95dcf90a 100644 --- a/LabApi/Loader/Features/Yaml/YamlConfigParser.cs +++ b/LabApi/Loader/Features/Yaml/YamlConfigParser.cs @@ -15,8 +15,8 @@ public static class YamlConfigParser /// Static yaml serializer instance. /// </summary> public static ISerializer Serializer { get; } = new SerializerBuilder() - .WithEmissionPhaseObjectGraphVisitor((EmissionPhaseObjectGraphVisitorArgs visitor) => new CommentsObjectGraphVisitor(visitor.InnerVisitor)) - .WithTypeInspector((ITypeInspector typeInspector) => new CommentGatheringTypeInspector(typeInspector)) + .WithEmissionPhaseObjectGraphVisitor(visitor => new CommentsObjectGraphVisitor(visitor.InnerVisitor)) + .WithTypeInspector(typeInspector => new CommentGatheringTypeInspector(typeInspector)) .WithNamingConvention(UnderscoredNamingConvention.Instance) .DisableAliases() .IgnoreFields() From 5ef8d188a6e3b947d93f153220cb255915672c3f Mon Sep 17 00:00:00 2001 From: davidsebesta1 <david.sebesta@post.cz> Date: Thu, 24 Jul 2025 16:57:32 +0200 Subject: [PATCH 059/215] Fixed IsAllowed --- .../Events/Arguments/Scp173Events/Scp173TeleportingEventArgs.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173TeleportingEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173TeleportingEventArgs.cs index afa550e6..fc0158a5 100644 --- a/LabApi/Events/Arguments/Scp173Events/Scp173TeleportingEventArgs.cs +++ b/LabApi/Events/Arguments/Scp173Events/Scp173TeleportingEventArgs.cs @@ -19,6 +19,7 @@ public Scp173TeleportingEventArgs(ReferenceHub hub, Vector3 position) { IsAllowed = true; Player = Player.Get(hub); + IsAllowed = true; } /// <summary> From fe9285b166c7eea9324417e36c34c0fd4c4e6c55 Mon Sep 17 00:00:00 2001 From: davidsebesta1 <david.sebesta@post.cz> Date: Fri, 25 Jul 2025 17:39:57 +0200 Subject: [PATCH 060/215] Fix args --- .../Events/Arguments/Scp173Events/Scp173TeleportingEventArgs.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173TeleportingEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173TeleportingEventArgs.cs index fc0158a5..461814b9 100644 --- a/LabApi/Events/Arguments/Scp173Events/Scp173TeleportingEventArgs.cs +++ b/LabApi/Events/Arguments/Scp173Events/Scp173TeleportingEventArgs.cs @@ -17,8 +17,8 @@ public class Scp173TeleportingEventArgs : EventArgs, IPlayerEvent, ICancellableE /// <param name="position">The target position to teleport to.</param> public Scp173TeleportingEventArgs(ReferenceHub hub, Vector3 position) { - IsAllowed = true; Player = Player.Get(hub); + Position = position; IsAllowed = true; } From fda909a46bf01625fd2e9afe09bd46c845518bed Mon Sep 17 00:00:00 2001 From: davidsebesta1 <david.sebesta@post.cz> Date: Fri, 1 Aug 2025 19:15:51 +0200 Subject: [PATCH 061/215] Spectatable property --- LabApi/Features/Wrappers/Players/Player.cs | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/LabApi/Features/Wrappers/Players/Player.cs b/LabApi/Features/Wrappers/Players/Player.cs index 3c6b1100..56227133 100644 --- a/LabApi/Features/Wrappers/Players/Player.cs +++ b/LabApi/Features/Wrappers/Players/Player.cs @@ -465,6 +465,24 @@ public List<Player> CurrentSpectators } } + /// <summary> + /// Gets or sets whether this player can be spectated by other players. + /// </summary> + /// <remarks> + /// This property is reset when player leaves. + /// </remarks> + public bool IsSpectatable + { + get + { + return SpectatableVisibilityManager.IsHidden(ReferenceHub); + } + set + { + SpectatableVisibilityManager.SetHidden(ReferenceHub, value); + } + } + /// <summary> /// Gets or sets the player's current <see cref="Item">item</see>. /// </summary> @@ -483,7 +501,7 @@ public Item? CurrentItem /// <summary> /// Gets the player's currently active <see cref="StatusEffectBase">status effects</see>. /// </summary> - public IEnumerable<StatusEffectBase> ActiveEffects => ReferenceHub.playerEffectsController.AllEffects.Where(x => x.Intensity > 0); + public IEnumerable<StatusEffectBase> ActiveEffects => ReferenceHub.playerEffectsController.AllEffects.Where(static x => x.Intensity > 0); /// <summary> /// Gets the <see cref="LabApi.Features.Wrappers.Room"/> at the player's current position. @@ -1418,7 +1436,7 @@ public void ClearInventory(bool clearAmmo = true, bool clearItems = true) if (clearItems) ClearItems(); } - + /// <summary> /// Gives a candy to the player. /// </summary> From 78d95bee75c62df60b8cfce48fd3ddc8a556d895 Mon Sep 17 00:00:00 2001 From: davidsebesta <david.sebesta@post.cz> Date: Sun, 3 Aug 2025 12:36:22 +0200 Subject: [PATCH 062/215] Applied suggestions --- LabApi/Features/Wrappers/Facility/Structures/Window.cs | 4 +--- LabApi/Features/Wrappers/Pickups/MicroHIDPickup.cs | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Structures/Window.cs b/LabApi/Features/Wrappers/Facility/Structures/Window.cs index 6f54309c..7ca44b49 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/Window.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/Window.cs @@ -135,7 +135,7 @@ public override string ToString() /// </summary> /// <param name="breakableWindow">The <see cref="Base"/> of the window.</param> /// <param name="window">The requested window.</param> - /// <returns><see langword="True"/> of the structure exists, otherwise <see langword="false"/>.</returns> + /// <returns><see langword="true"/> of the structure exists, otherwise <see langword="false"/>.</returns> public static bool TryGet(BreakableWindow? breakableWindow, [NotNullWhen(true)] out Window? window) { window = Get(breakableWindow); @@ -161,6 +161,4 @@ private static void OnRemoved(BreakableWindow spawnableStructure) if (Dictionary.TryGetValue(spawnableStructure, out Window structure)) structure.OnRemove(); } - - } diff --git a/LabApi/Features/Wrappers/Pickups/MicroHIDPickup.cs b/LabApi/Features/Wrappers/Pickups/MicroHIDPickup.cs index 49415d36..b36a5cc4 100644 --- a/LabApi/Features/Wrappers/Pickups/MicroHIDPickup.cs +++ b/LabApi/Features/Wrappers/Pickups/MicroHIDPickup.cs @@ -75,7 +75,7 @@ public MicroHidFiringMode FiringMode /// <summary> /// Gets or sets the energy amount in this Micro-HID pickup.<para/> - /// Value for the energy is between 0f - 1f and is automatically clamped. + /// The energy value, automatically clamped, ranges from 0f to 1f. /// </summary> public float Energy { From ca3f5af996569117a323614419c12cc4f6d31bd4 Mon Sep 17 00:00:00 2001 From: davidsebesta1 <david.sebesta@post.cz> Date: Mon, 4 Aug 2025 18:14:39 +0200 Subject: [PATCH 063/215] IsDestroyed + role visibility method --- LabApi/Features/Wrappers/Players/Player.cs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/LabApi/Features/Wrappers/Players/Player.cs b/LabApi/Features/Wrappers/Players/Player.cs index 3c6b1100..214d1c27 100644 --- a/LabApi/Features/Wrappers/Players/Player.cs +++ b/LabApi/Features/Wrappers/Players/Player.cs @@ -8,6 +8,7 @@ using InventorySystem.Disarming; using InventorySystem.Items; using InventorySystem.Items.Pickups; +using InventorySystem.Items.Usables.Scp330; using LabApi.Features.Enums; using LabApi.Features.Stores; using MapGeneration; @@ -16,6 +17,7 @@ using NorthwoodLib.Pools; using PlayerRoles; using PlayerRoles.FirstPersonControl; +using PlayerRoles.FirstPersonControl.NetworkMessages; using PlayerRoles.PlayableScps.HumeShield; using PlayerRoles.Spectating; using PlayerRoles.Voice; @@ -25,7 +27,6 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; -using InventorySystem.Items.Usables.Scp330; using UnityEngine; using Utils.Networking; using Utils.NonAllocLINQ; @@ -211,6 +212,11 @@ internal Player(ReferenceHub referenceHub) [Obsolete("Use !IsDestroyed instead.")] public bool IsOnline => !IsOffline; + /// <summary> + /// Gets whether the player was destroyed. + /// </summary> + public bool IsDestroyed => !ReferenceHub; + /// <summary> /// Gets if the player is properly connected and authenticated. /// </summary> @@ -1418,7 +1424,7 @@ public void ClearInventory(bool clearAmmo = true, bool clearItems = true) if (clearItems) ClearItems(); } - + /// <summary> /// Gives a candy to the player. /// </summary> @@ -1486,6 +1492,13 @@ public void AddRegeneration(float rate, float duration) /// <param name="flags">The <see cref="RoleSpawnFlags"/> of role change.</param> public void SetRole(RoleTypeId newRole, RoleChangeReason reason = RoleChangeReason.RemoteAdmin, RoleSpawnFlags flags = RoleSpawnFlags.All) => ReferenceHub.roleManager.ServerSetRole(newRole, reason, flags); + /// <summary> + /// Determines if <paramref name="otherPlayer"/> is seen as spectator or their role based on visibility, permissions, and distance of this player. + /// </summary> + /// <param name="otherPlayer">The other player to check.</param> + /// <returns>The role this player sees for the other player.</returns> + public RoleTypeId GetRoleVisibilityFor(Player otherPlayer) => FpcServerPositionDistributor.GetVisibleRole(otherPlayer.ReferenceHub, ReferenceHub); + /// <summary> /// Disconnects the player from the server. /// </summary> From f3b7acfbfddea8e0bfa36463f7b08a4287296378 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Wed, 6 Aug 2025 12:23:06 +0930 Subject: [PATCH 064/215] waypoint bounds and update children methods --- .../Features/Wrappers/AdminToys/AdminToy.cs | 6 +- .../Wrappers/AdminToys/WaypointToy.cs | 64 ++++++++++++++++++- 2 files changed, 64 insertions(+), 6 deletions(-) diff --git a/LabApi/Features/Wrappers/AdminToys/AdminToy.cs b/LabApi/Features/Wrappers/AdminToys/AdminToy.cs index e891c506..90292a96 100644 --- a/LabApi/Features/Wrappers/AdminToys/AdminToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/AdminToy.cs @@ -103,7 +103,7 @@ internal virtual void OnRemove() /// <remarks> /// If <see cref="IsStatic"/> is <see langword="true"/> client wont update its position. /// </remarks> - public Vector3 Position + public virtual Vector3 Position { get => Transform.localPosition; set => Transform.localPosition = value; @@ -116,7 +116,7 @@ public Vector3 Position /// <remarks> /// If <see cref="IsStatic"/> is <see langword="true"/> client wont update its rotation. /// </remarks> - public Quaternion Rotation + public virtual Quaternion Rotation { get => Transform.localRotation; set => Transform.localRotation = value; @@ -129,7 +129,7 @@ public Quaternion Rotation /// <remarks> /// If <see cref="IsStatic"/> is <see langword="true"/> client wont update its scale. /// </remarks> - public Vector3 Scale + public virtual Vector3 Scale { get => Transform.localScale; set => Transform.localScale = value; diff --git a/LabApi/Features/Wrappers/AdminToys/WaypointToy.cs b/LabApi/Features/Wrappers/AdminToys/WaypointToy.cs index 9c5e0fa7..a2e44c24 100644 --- a/LabApi/Features/Wrappers/AdminToys/WaypointToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/WaypointToy.cs @@ -1,5 +1,4 @@ -using LabApi.Features.Wrappers; -using System.Collections.Generic; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using UnityEngine; using BaseWaypointToy = AdminToys.WaypointToy; @@ -21,11 +20,61 @@ public class WaypointToy : AdminToy /// </summary> public new static IReadOnlyCollection<WaypointToy> List => Dictionary.Values; + /// <inheritdoc /> + public override Vector3 Position + { + get => base.Position; + set + { + base.Position = value; + Base.UpdateWaypointChildren(); + } + } + + /// <inheritdoc /> + public override Quaternion Rotation + { + get => base.Rotation; + set + { + base.Rotation = value; + Base.UpdateWaypointChildren(); + } + } + + /// <summary> + /// Gets or sets the scale on the waypoint toy. + /// Does not effect the bounds of the waypoint, use <see cref="BoundsSize"/> instead. + /// </summary> + /// <remarks> + /// Scale can cause unindented side effects when used on a waypoint toy. + /// </remarks> + public override Vector3 Scale + { + get => base.Scale; + set + { + base.Scale = value; + + if (value != Vector3.one) + Console.Logger.Warn("Setting scale on WaypointToy is not supported and may causes problems."); + } + } + /// <summary> /// The <see cref="BaseWaypointToy"/> object. /// </summary> public new BaseWaypointToy Base { get; } + /// <summary> + /// Gets or sets + /// </summary> + public Vector3 BoundsSize + { + get => Base.BoundsSize; + set => Base.NetworkBoundsSize = value; + } + /// <summary> /// Gets or sets whether to visualize the waypoint's maximum bounds. /// </summary> @@ -68,10 +117,19 @@ internal override void OnRemove() Dictionary.Remove(Base); } + /// <summary> + /// Force update all waypoint children to be up to date with the current position and rotation of the waypoint. + /// Call this when ever the waypoint is moved by a parent object or the waypoint is moved using base game APIs or external APIs. + /// </summary> + /// <remarks> + /// Does not work if the waypoint is <see cref="AdminToy.IsStatic"/>. + /// </remarks> + public void UpdateWaypointChildren() => Base.UpdateWaypointChildren(); + /// <inheritdoc /> public override string ToString() { - return $"[WaypointToy: Position{Position}, VisualizeBounds:{VisualizeBounds}, PriorityBias:{PriorityBias}]"; + return $"[WaypointToy: Position{Position}, BoundsSize:{BoundsSize}, VisualizeBounds:{VisualizeBounds}, PriorityBias:{PriorityBias}]"; } /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> From a4629e1be78ab86bdacd9e6e6552a39652fa086a Mon Sep 17 00:00:00 2001 From: davidsebesta1 <david.sebesta@post.cz> Date: Sat, 9 Aug 2025 17:29:30 +0200 Subject: [PATCH 065/215] Fixed mute not using the correct base game class --- LabApi/Features/Wrappers/Players/Player.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LabApi/Features/Wrappers/Players/Player.cs b/LabApi/Features/Wrappers/Players/Player.cs index 3c6b1100..879a5942 100644 --- a/LabApi/Features/Wrappers/Players/Player.cs +++ b/LabApi/Features/Wrappers/Players/Player.cs @@ -617,12 +617,12 @@ public bool IsDisarmed /// <summary> /// Gets a value indicating whether the player is muted. /// </summary> - public bool IsMuted => VoiceChatMutes.QueryLocalMute(UserId); + public bool IsMuted => VoiceChatMutes.IsMuted(ReferenceHub); /// <summary> /// Gets a value indicating whether the player is muted from the intercom. /// </summary> - public bool IsIntercomMuted => VoiceChatMutes.QueryLocalMute(UserId, true); + public bool IsIntercomMuted => VoiceChatMutes.IsMuted(ReferenceHub, true); /// <summary> /// Gets a value indicating whether the player is talking through a radio. From 54ea9d7ab84ede56063bd9c0830735e0b9bfe795 Mon Sep 17 00:00:00 2001 From: davidsebesta1 <david.sebesta@post.cz> Date: Sun, 10 Aug 2025 09:45:35 +0200 Subject: [PATCH 066/215] Fix properties and position --- .../Wrappers/AdminToys/SpawnableCullingParent.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/LabApi/Features/Wrappers/AdminToys/SpawnableCullingParent.cs b/LabApi/Features/Wrappers/AdminToys/SpawnableCullingParent.cs index 078fd6d2..d2a04a17 100644 --- a/LabApi/Features/Wrappers/AdminToys/SpawnableCullingParent.cs +++ b/LabApi/Features/Wrappers/AdminToys/SpawnableCullingParent.cs @@ -79,8 +79,8 @@ protected SpawnableCullingParent(BaseCullingParent cullingBase) /// </summary> public Vector3 Position { - get => Base.BoundsPosition; - set => Base.BoundsPosition = value; + get => Base.NetworkBoundsPosition; + set => Base.NetworkBoundsPosition = value; } /// <summary> @@ -88,8 +88,8 @@ public Vector3 Position /// </summary> public Vector3 Size { - get => Base.BoundsSize; - set => Base.BoundsSize = value; + get => Base.NetworkBoundsSize; + set => Base.NetworkBoundsSize = value; } /// <summary> @@ -126,9 +126,9 @@ public static SpawnableCullingParent Create(Vector3 position, Vector3 size, bool PrefabCache<BaseCullingParent>.prefab = found; } - BaseCullingParent instance = UnityEngine.Object.Instantiate(PrefabCache<BaseCullingParent>.prefab); - instance.BoundsPosition = position; - instance.BoundsSize = size; + BaseCullingParent instance = UnityEngine.Object.Instantiate(PrefabCache<BaseCullingParent>.prefab, position, Quaternion.identity); + instance.NetworkBoundsPosition = position; + instance.NetworkBoundsSize = size; if (networkSpawn) NetworkServer.Spawn(instance.gameObject); @@ -175,7 +175,7 @@ private static void AddCullableParent(BaseCullingParent cullableParent) } catch (Exception e) { - Logger.InternalError($"Failed to handle admin toy creation with error: {e}"); + Logger.InternalError($"Failed to handle cullable parent creation with error: {e}"); } } From d6e33898bc6dae78d3291dfcbec73cbfe6797b40 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:39:12 +0930 Subject: [PATCH 067/215] updated args --- .../Interfaces/Hazards/IHazardEvent.cs | 1 - .../Arguments/Interfaces/IGroupEvent.cs | 1 + .../Arguments/Interfaces/IObjectiveEvent.cs | 1 - .../Interfaces/Items/IKeycardItemEvent.cs | 1 - .../EnemyKilledObjectiveEventArgs.cs | 3 +- .../EnemyKillingObjectiveEventArgs.cs | 3 +- .../EscapedObjectiveEventArgs.cs | 3 +- .../EscapingObjectiveEventArgs.cs | 3 +- .../GeneratorActivatedObjectiveEventArgs.cs | 3 +- .../GeneratorActivatingObjectiveEventArgs.cs | 3 +- .../ScpDamagedObjectiveEventArgs.cs | 9 +- .../ScpDamagingObjectiveEventArgs.cs | 3 +- .../ScpItemPickedObjectiveEventArgs.cs | 3 +- .../ScpItemPickingObjectiveEventArgs.cs | 3 +- .../PlayerAimingWeaponEventArgs.cs | 34 ++++--- .../PlayerEvents/PlayerBanningEventArgs.cs | 2 +- .../PlayerChangedAttachmentsEventArgs.cs | 4 +- .../PlayerChangingAttachmentsEventArgs.cs | 6 +- .../PlayerChangingNicknameEventArgs.cs | 2 +- .../PlayerEvents/PlayerDeathEventArgs.cs | 10 +- .../PlayerDryFiringWeaponEventArgs.cs | 1 - .../PlayerEnteredPocketDimensionEventArgs.cs | 2 +- .../PlayerEnteringHazardEventArgs.cs | 1 - .../PlayerEvents/PlayerEscapingEventArgs.cs | 2 +- .../PlayerEvents/PlayerIdledTeslaEventArgs.cs | 4 +- .../PlayerIdlingTeslaEventArgs.cs | 4 +- .../PlayerInteractedScp330EventArgs.cs | 8 +- .../PlayerInteractedWarheadLeverEventArgs.cs | 2 +- .../PlayerInteractingElevatorEventArgs.cs | 4 +- .../PlayerInteractingScp330EventArgs.cs | 8 +- .../PlayerLeavingHazardEventArgs.cs | 2 +- .../PlayerMovementStateChangedEventArgs.cs | 2 +- .../PlayerPickedUpScp330EventArgs.cs | 2 +- ....cs => PlayerPlacedBulletHoleEventArgs.cs} | 0 .../PlayerPreAuthenticatingEventArgs.cs | 4 +- ...PlayerProcessedJailbirdMessageEventArgs.cs | 1 - ...PlayerRaPlayerListAddingPlayerEventArgs.cs | 10 +- .../PlayerReceivingLoadoutEventArgs.cs | 10 +- .../PlayerReceivingVoiceMessageEventArgs.cs | 4 +- .../PlayerRequestedCustomRaInfoEventArgs.cs | 32 +++--- .../PlayerRequestedRaPlayerInfoEventArgs.cs | 11 ++- .../PlayerRequestedRaPlayersInfoEventArgs.cs | 14 ++- .../PlayerRequestingRaPlayerInfoEventArgs.cs | 9 +- .../PlayerRequestingRaPlayerListEventArgs.cs | 9 +- .../PlayerRequestingRaPlayersInfoEventArgs.cs | 11 ++- .../PlayerRoomChangedEventArgs.cs | 4 +- .../PlayerSearchingToyEventArgs.cs | 2 +- .../PlayerSendingAttachmentsPrefsEventArgs.cs | 6 +- .../PlayerSendingVoiceMessageEventArgs.cs | 4 +- .../PlayerSentAttachmentsPrefsEventArgs.cs | 7 +- .../PlayerEvents/PlayerSpawningEventArgs.cs | 4 +- .../PlayerThrowingItemEventArgs.cs | 3 +- .../PlayerToggledNoclipEventArgs.cs | 43 ++++---- .../PlayerTogglingNoclipEventArgs.cs | 2 +- .../PlayerTriggeredTeslaEventArgs.cs | 4 +- .../PlayerTriggeringTeslaEventArgs.cs | 4 +- .../PlayerEvents/PlayerUncuffingEventArgs.cs | 2 +- .../PlayerUnlockedGeneratorEventArgs.cs | 1 - .../PlayerUnlockedWarheadButtonEventArgs.cs | 1 - .../PlayerUnlockingGeneratorEventArgs.cs | 1 - .../PlayerUsingIntercomEventArgs.cs | 2 +- .../PlayerZoneChangedEventArgs.cs | 8 +- .../Scp0492ConsumedCorpseEventArgs.cs | 4 +- .../Scp0492ConsumingCorpseEventArgs.cs | 4 +- .../Scp0492StartedConsumingCorpseEventArgs.cs | 4 +- ...Scp0492StartingConsumingCorpseEventArgs.cs | 4 +- .../Scp079BlackedOutRoomEventArgs.cs | 2 +- .../Scp079BlackingOutRoomEventsArgs.cs | 2 +- .../Scp079CancelledRoomLockdownEventArgs.cs | 2 +- .../Scp079CancellingRoomLockdownEventArgs.cs | 2 +- .../Scp079GainedExperienceEventArgs.cs | 2 +- .../Scp079GainingExperienceEventArgs.cs | 2 +- .../Scp079Events/Scp079LockedDoorEventArgs.cs | 4 +- .../Scp079LockedDownRoomEventArgs.cs | 2 +- .../Scp079LockingDoorEventArgs.cs | 4 +- .../Scp079LockingDownRoomEventArgs.cs | 2 +- .../Scp079UnlockedDoorEventArgs.cs | 4 +- .../Scp079UnlockingDoorEventArgs.cs | 4 +- .../Scp079Events/Scp079UsedTeslaEventArgs.cs | 2 +- .../Scp096AddedTargetEventArgs.cs | 2 +- .../Scp096AddingTargetEventArgs.cs | 2 +- .../Scp106ChangedStalkModeEventArgs.cs | 6 +- .../Scp106ChangedSubmersionStatusEventArgs.cs | 6 +- .../Scp106ChangedVigorEventArgs.cs | 2 +- .../Scp106ChangingStalkModeEventArgs.cs | 8 +- ...Scp106ChangingSubmersionStatusEventArgs.cs | 2 +- .../Scp106ChangingVigorEventArgs.cs | 2 +- .../Scp106TeleportedPlayerEvent.cs | 4 +- .../Scp106TeleportingPlayerEvent.cs | 4 +- .../Scp106UsedHunterAtlasEventArgs.cs | 2 +- .../Scp106UsingHunterAtlasEventArgs.cs | 2 +- .../Scp173BreakneckSpeedChangingEventArgs.cs | 2 +- .../Scp173PlayedSoundEventArgs.cs | 3 +- .../Scp173PlayingSoundEventArgs.cs | 2 +- .../Scp3114DisguisedEventArgs.cs | 2 +- .../Scp3114DisguisingEventArgs.cs | 2 +- .../Scp3114Events/Scp3114RevealedEventArgs.cs | 2 +- .../Scp3114RevealingEventArgs.cs | 2 +- .../Scp3114StartedDanceEventArgs.cs | 2 +- .../Scp3114StartingDanceEventArgs.cs | 4 +- .../Scp914ProcessedInventoryItemEventArgs.cs | 2 +- .../Scp914ProcessedPickupEventArgs.cs | 2 +- .../Scp914ProcessingInventoryItemEventArgs.cs | 2 +- .../Scp914ProcessingPickupEventArgs.cs | 4 +- .../ServerEvents/CassieAnnouncedEventArgs.cs | 4 +- .../ServerEvents/CassieAnnouncingEventArgs.cs | 4 +- .../CassieQueuingScpTerminationEventArgs.cs | 4 +- .../ServerEvents/CommandExecutedEventArgs.cs | 4 +- .../ServerEvents/ExplosionSpawnedEventArgs.cs | 79 ++++++++------- .../ExplosionSpawningEventArgs.cs | 97 +++++++++---------- .../ServerEvents/ItemSpawningEventArgs.cs | 2 +- .../RoundEndingConditionsCheckEventArgs.cs | 2 +- .../ServerEvents/SentAdminChatEventArgs.cs | 2 +- .../ServerEvents/WaveRespawnedEventArgs.cs | 2 +- .../ServerEvents/WaveRespawningEventArgs.cs | 4 +- .../ServerEvents/WaveTeamSelectedEventArgs.cs | 4 +- .../WaveTeamSelectingEventArgs.cs | 2 +- 117 files changed, 372 insertions(+), 314 deletions(-) rename LabApi/Events/Arguments/PlayerEvents/{PlayerPlacedBulletHole.cs => PlayerPlacedBulletHoleEventArgs.cs} (100%) diff --git a/LabApi/Events/Arguments/Interfaces/Hazards/IHazardEvent.cs b/LabApi/Events/Arguments/Interfaces/Hazards/IHazardEvent.cs index 159767d3..b77c4717 100644 --- a/LabApi/Events/Arguments/Interfaces/Hazards/IHazardEvent.cs +++ b/LabApi/Events/Arguments/Interfaces/Hazards/IHazardEvent.cs @@ -12,4 +12,3 @@ public interface IHazardEvent /// </summary> public Hazard? Hazard { get; } } - diff --git a/LabApi/Events/Arguments/Interfaces/IGroupEvent.cs b/LabApi/Events/Arguments/Interfaces/IGroupEvent.cs index 0f1d3f9c..06164ad9 100644 --- a/LabApi/Events/Arguments/Interfaces/IGroupEvent.cs +++ b/LabApi/Events/Arguments/Interfaces/IGroupEvent.cs @@ -1,4 +1,5 @@ namespace LabApi.Events.Arguments.Interfaces; + /// <summary> /// Represents an event that involves a <see cref="UserGroup"/>. /// </summary> diff --git a/LabApi/Events/Arguments/Interfaces/IObjectiveEvent.cs b/LabApi/Events/Arguments/Interfaces/IObjectiveEvent.cs index b408ce12..2bec4f79 100644 --- a/LabApi/Events/Arguments/Interfaces/IObjectiveEvent.cs +++ b/LabApi/Events/Arguments/Interfaces/IObjectiveEvent.cs @@ -36,5 +36,4 @@ public interface IObjectiveEvent /// Gets whether the objective completion should be sent to players and visible on their screen. /// </summary> public bool SendToPlayers { get; } - } diff --git a/LabApi/Events/Arguments/Interfaces/Items/IKeycardItemEvent.cs b/LabApi/Events/Arguments/Interfaces/Items/IKeycardItemEvent.cs index c270c19c..2d3ebaae 100644 --- a/LabApi/Events/Arguments/Interfaces/Items/IKeycardItemEvent.cs +++ b/LabApi/Events/Arguments/Interfaces/Items/IKeycardItemEvent.cs @@ -15,4 +15,3 @@ public interface IKeycardItemEvent : IItemEvent /// </summary> public KeycardItem KeycardItem { get; } } - diff --git a/LabApi/Events/Arguments/ObjectiveEvents/EnemyKilledObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/EnemyKilledObjectiveEventArgs.cs index 96621342..c69a4071 100644 --- a/LabApi/Events/Arguments/ObjectiveEvents/EnemyKilledObjectiveEventArgs.cs +++ b/LabApi/Events/Arguments/ObjectiveEvents/EnemyKilledObjectiveEventArgs.cs @@ -17,7 +17,8 @@ public class EnemyKilledObjectiveEventArgs : ObjectiveCompletedBaseEventArgs /// <param name="timeToGrant">The time to reduce from the <paramref name="faction"/>.</param> /// <param name="sendToPlayers">Whether the objective completion has been sent to players.</param> /// <param name="targetHub">The player that has been killed.</param> - public EnemyKilledObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, bool sendToPlayers, ReferenceHub targetHub) : base(hub, faction, influenceToGrant, timeToGrant, sendToPlayers) + public EnemyKilledObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, bool sendToPlayers, ReferenceHub targetHub) + : base(hub, faction, influenceToGrant, timeToGrant, sendToPlayers) { Target = Player.Get(targetHub); } diff --git a/LabApi/Events/Arguments/ObjectiveEvents/EnemyKillingObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/EnemyKillingObjectiveEventArgs.cs index 57808169..fde1bb89 100644 --- a/LabApi/Events/Arguments/ObjectiveEvents/EnemyKillingObjectiveEventArgs.cs +++ b/LabApi/Events/Arguments/ObjectiveEvents/EnemyKillingObjectiveEventArgs.cs @@ -16,7 +16,8 @@ public class EnemyKillingObjectiveEventArgs : ObjectiveCompletingBaseEventArgs /// <param name="influenceToGrant">The influence points to grant to the <paramref name="faction"/>.</param> /// <param name="timeToGrant">The time to reduce from the <paramref name="faction"/>.</param> /// <param name="targetHub">The player that has been killed.</param> - public EnemyKillingObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, ReferenceHub targetHub) : base(hub, faction, influenceToGrant, timeToGrant) + public EnemyKillingObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, ReferenceHub targetHub) + : base(hub, faction, influenceToGrant, timeToGrant) { Target = Player.Get(targetHub); } diff --git a/LabApi/Events/Arguments/ObjectiveEvents/EscapedObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/EscapedObjectiveEventArgs.cs index 1bbe2127..09deb136 100644 --- a/LabApi/Events/Arguments/ObjectiveEvents/EscapedObjectiveEventArgs.cs +++ b/LabApi/Events/Arguments/ObjectiveEvents/EscapedObjectiveEventArgs.cs @@ -17,7 +17,8 @@ public class EscapedObjectiveEventArgs : ObjectiveCompletedBaseEventArgs /// <param name="newRole">The new role the player gets after escaping.</param> /// <param name="sendToPlayers">Whether the objective completion has been sent to players.</param> /// <param name="oldRole">The old role of the player.</param> - public EscapedObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, bool sendToPlayers, RoleTypeId oldRole, RoleTypeId newRole) : base(hub, faction, influenceToGrant, timeToGrant, sendToPlayers) + public EscapedObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, bool sendToPlayers, RoleTypeId oldRole, RoleTypeId newRole) + : base(hub, faction, influenceToGrant, timeToGrant, sendToPlayers) { OldRole = oldRole; NewRole = newRole; diff --git a/LabApi/Events/Arguments/ObjectiveEvents/EscapingObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/EscapingObjectiveEventArgs.cs index 830761ab..1b87beaa 100644 --- a/LabApi/Events/Arguments/ObjectiveEvents/EscapingObjectiveEventArgs.cs +++ b/LabApi/Events/Arguments/ObjectiveEvents/EscapingObjectiveEventArgs.cs @@ -16,7 +16,8 @@ public class EscapingObjectiveEventArgs : ObjectiveCompletingBaseEventArgs /// <param name="timeToGrant">The time to reduce from the <paramref name="faction"/>.</param> /// <param name="newRole">The new role the player gets after escaping.</param> /// <param name="oldRole">The old role of the player.</param> - public EscapingObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, RoleTypeId oldRole, RoleTypeId newRole) : base(hub, faction, influenceToGrant, timeToGrant) + public EscapingObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, RoleTypeId oldRole, RoleTypeId newRole) + : base(hub, faction, influenceToGrant, timeToGrant) { OldRole = oldRole; NewRole = newRole; diff --git a/LabApi/Events/Arguments/ObjectiveEvents/GeneratorActivatedObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/GeneratorActivatedObjectiveEventArgs.cs index e215245d..8cf18012 100644 --- a/LabApi/Events/Arguments/ObjectiveEvents/GeneratorActivatedObjectiveEventArgs.cs +++ b/LabApi/Events/Arguments/ObjectiveEvents/GeneratorActivatedObjectiveEventArgs.cs @@ -18,7 +18,8 @@ public class GeneratorActivatedObjectiveEventArgs : ObjectiveCompletedBaseEventA /// <param name="timeToGrant">The time to reduce from the <paramref name="faction"/>.</param> /// <param name="sendToPlayers">Whether the objective completion has been sent to players.</param> /// <param name="generator">The generator that has been activated.</param> - public GeneratorActivatedObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, bool sendToPlayers, Scp079Generator generator) : base(hub, faction, influenceToGrant, timeToGrant, sendToPlayers) + public GeneratorActivatedObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, bool sendToPlayers, Scp079Generator generator) + : base(hub, faction, influenceToGrant, timeToGrant, sendToPlayers) { Generator = Generator.Get(generator); } diff --git a/LabApi/Events/Arguments/ObjectiveEvents/GeneratorActivatingObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/GeneratorActivatingObjectiveEventArgs.cs index d1d21687..08eee63a 100644 --- a/LabApi/Events/Arguments/ObjectiveEvents/GeneratorActivatingObjectiveEventArgs.cs +++ b/LabApi/Events/Arguments/ObjectiveEvents/GeneratorActivatingObjectiveEventArgs.cs @@ -17,7 +17,8 @@ public class GeneratorActivatingObjectiveEventArgs : ObjectiveCompletingBaseEven /// <param name="influenceToGrant">The influence points to grant to the <paramref name="faction"/>.</param> /// <param name="timeToGrant">The time to reduce from the <paramref name="faction"/>.</param> /// <param name="generator">The generator that has been activated.</param> - public GeneratorActivatingObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, Scp079Generator generator) : base(hub, faction, influenceToGrant, timeToGrant) + public GeneratorActivatingObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, Scp079Generator generator) + : base(hub, faction, influenceToGrant, timeToGrant) { Generator = Generator.Get(generator); } diff --git a/LabApi/Events/Arguments/ObjectiveEvents/ScpDamagedObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/ScpDamagedObjectiveEventArgs.cs index c1bb7b3d..a856bf50 100644 --- a/LabApi/Events/Arguments/ObjectiveEvents/ScpDamagedObjectiveEventArgs.cs +++ b/LabApi/Events/Arguments/ObjectiveEvents/ScpDamagedObjectiveEventArgs.cs @@ -12,12 +12,13 @@ public class ScpDamagedObjectiveEventArgs : ObjectiveCompletedBaseEventArgs /// Initializes a new instance of the <see cref="ScpDamagedObjectiveEventArgs"/> class. /// </summary> /// <param name="hub">The player hub who triggered the objective.</param> - /// <param name="Faction">The Faction to grant the influence to.</param> - /// <param name="influenceToGrant">The influence points to grant to the <paramref name="Faction"/>.</param> - /// <param name="timeToGrant">The time to reduce from the <paramref name="Faction"/>.</param> + /// <param name="faction">The Faction to grant the influence to.</param> + /// <param name="influenceToGrant">The influence points to grant to the <paramref name="faction"/>.</param> + /// <param name="timeToGrant">The time to reduce from the <paramref name="faction"/>.</param> /// <param name="sendToPlayers">Whether the objective completion has been sent to players.</param> /// <param name="targetHub">The hub of the player SCP that has been damaged.</param> - public ScpDamagedObjectiveEventArgs(ReferenceHub hub, Faction Faction, float influenceToGrant, float timeToGrant, bool sendToPlayers, ReferenceHub targetHub) : base(hub, Faction, influenceToGrant, timeToGrant, sendToPlayers) + public ScpDamagedObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, bool sendToPlayers, ReferenceHub targetHub) + : base(hub, faction, influenceToGrant, timeToGrant, sendToPlayers) { Target = Player.Get(targetHub); } diff --git a/LabApi/Events/Arguments/ObjectiveEvents/ScpDamagingObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/ScpDamagingObjectiveEventArgs.cs index f04e0ea9..ba9b4cfa 100644 --- a/LabApi/Events/Arguments/ObjectiveEvents/ScpDamagingObjectiveEventArgs.cs +++ b/LabApi/Events/Arguments/ObjectiveEvents/ScpDamagingObjectiveEventArgs.cs @@ -16,7 +16,8 @@ public class ScpDamagingObjectiveEventArgs : ObjectiveCompletingBaseEventArgs /// <param name="influenceToGrant">The influence points to grant to the <paramref name="faction"/>.</param> /// <param name="timeToGrant">The time to reduce from the <paramref name="faction"/>.</param> /// <param name="targetHub">The hub of the player SCP that has been damaged.</param> - public ScpDamagingObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, ReferenceHub targetHub) : base(hub, faction, influenceToGrant, timeToGrant) + public ScpDamagingObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, ReferenceHub targetHub) + : base(hub, faction, influenceToGrant, timeToGrant) { Target = Player.Get(targetHub); } diff --git a/LabApi/Events/Arguments/ObjectiveEvents/ScpItemPickedObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/ScpItemPickedObjectiveEventArgs.cs index 0bf0d4a2..b5ad603d 100644 --- a/LabApi/Events/Arguments/ObjectiveEvents/ScpItemPickedObjectiveEventArgs.cs +++ b/LabApi/Events/Arguments/ObjectiveEvents/ScpItemPickedObjectiveEventArgs.cs @@ -18,7 +18,8 @@ public class ScpItemPickedObjectiveEventArgs : ObjectiveCompletedBaseEventArgs /// <param name="timeToGrant">The time to reduce from the <paramref name="faction"/>.</param> /// <param name="sendToPlayers">Whether the objective completion has been sent to players.</param> /// <param name="item">The item that has been picked up.</param> - public ScpItemPickedObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, bool sendToPlayers, ItemBase item) : base(hub, faction, influenceToGrant, timeToGrant, sendToPlayers) + public ScpItemPickedObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, bool sendToPlayers, ItemBase item) + : base(hub, faction, influenceToGrant, timeToGrant, sendToPlayers) { Item = Item.Get(item); } diff --git a/LabApi/Events/Arguments/ObjectiveEvents/ScpItemPickingObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/ScpItemPickingObjectiveEventArgs.cs index f2c1ba47..63efff01 100644 --- a/LabApi/Events/Arguments/ObjectiveEvents/ScpItemPickingObjectiveEventArgs.cs +++ b/LabApi/Events/Arguments/ObjectiveEvents/ScpItemPickingObjectiveEventArgs.cs @@ -17,7 +17,8 @@ public class ScpItemPickingObjectiveEventArgs : ObjectiveCompletingBaseEventArgs /// <param name="influenceToGrant">The influence points to grant to the <paramref name="faction"/>.</param> /// <param name="timeToGrant">The time to reduce from the <paramref name="faction"/>.</param> /// <param name="item">The item that has been picked up.</param> - public ScpItemPickingObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, ItemBase item) : base(hub, faction, influenceToGrant, timeToGrant) + public ScpItemPickingObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, ItemBase item) + : base(hub, faction, influenceToGrant, timeToGrant) { Item = Item.Get(item); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerAimingWeaponEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerAimingWeaponEventArgs.cs index 1bbf62cd..8d53a40c 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerAimingWeaponEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerAimingWeaponEventArgs.cs @@ -6,25 +6,26 @@ namespace LabApi.Events.Arguments.PlayerEvents; +#pragma warning disable SA1005 // Single line comments should begin with single space // TODO: implement cancellable aiming. ///// <summary> ///// Represents the arguments for the <see cref="Handlers.PlayerEvents.AimingWeapon"/> event. ///// </summary> -//public class PlayerAimingWeaponEventArgs : EventArgs, IPlayerEvent, IWeaponEvent, ICancellableEvent -//{ -// /// <summary> -// /// Initializes a new instance of the <see cref="PlayerAimingWeaponEventArgs"/> class. -// /// </summary> -// /// <param name="player">The player who is aiming the weapon.</param> -// /// <param name="weapon">The weapon that the player is aiming.</param> -// /// <param name="aiming">Whether or not the player is aiming or unaiming their weapon.</param> -// public PlayerAimingWeaponEventArgs(ReferenceHub player, ItemBase weapon, bool aiming) -// { -// IsAllowed = true; -// Player = Player.Get(player); -// Weapon = Item.Get(weapon); -// Aiming = aiming; -// } + //public class PlayerAimingWeaponEventArgs : EventArgs, IPlayerEvent, IWeaponEvent, ICancellableEvent + //{ + // /// <summary> + // /// Initializes a new instance of the <see cref="PlayerAimingWeaponEventArgs"/> class. + // /// </summary> + // /// <param name="player">The player who is aiming the weapon.</param> + // /// <param name="weapon">The weapon that the player is aiming.</param> + // /// <param name="aiming">Whether or not the player is aiming or unaiming their weapon.</param> + // public PlayerAimingWeaponEventArgs(ReferenceHub player, ItemBase weapon, bool aiming) + // { + // IsAllowed = true; + // Player = Player.Get(player); + // Weapon = Item.Get(weapon); + // Aiming = aiming; + // } // /// <summary> // /// Gets the player who is aiming the weapon. @@ -41,4 +42,5 @@ namespace LabApi.Events.Arguments.PlayerEvents; // /// <inheritdoc /> // public bool IsAllowed { get; set; } -//} \ No newline at end of file +//} +#pragma warning restore SA1005 // Single line comments should begin with single space \ No newline at end of file diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerBanningEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerBanningEventArgs.cs index 4358f492..68d81299 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerBanningEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerBanningEventArgs.cs @@ -31,7 +31,7 @@ public PlayerBanningEventArgs(ReferenceHub? player, string playerId, ReferenceHu /// Gets the player who is being banned. /// </summary> public Player? Player { get; } - + /// <summary> /// Gets the ID of the player who is being banned. /// </summary> diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangedAttachmentsEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedAttachmentsEventArgs.cs index c812663d..32304ec7 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerChangedAttachmentsEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedAttachmentsEventArgs.cs @@ -25,10 +25,10 @@ public PlayerChangedAttachmentsEventArgs(ReferenceHub player, Firearm firearm, u NewAttachments = newAttachments; } - /// <inheritdoc> + /// <inheritdoc /> public Player Player { get; } - /// <inheritdoc> + /// <inheritdoc /> public FirearmItem FirearmItem { get; } /// <summary> diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangingAttachmentsEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingAttachmentsEventArgs.cs index 09564cd0..669ff328 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerChangingAttachmentsEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingAttachmentsEventArgs.cs @@ -26,10 +26,10 @@ public PlayerChangingAttachmentsEventArgs(ReferenceHub player, Firearm firearm, IsAllowed = true; } - /// <inheritdoc/ > + /// <inheritdoc /> public Player Player { get; } - /// <inheritdoc/ > + /// <inheritdoc /> public FirearmItem FirearmItem { get; } /// <summary> @@ -42,6 +42,6 @@ public PlayerChangingAttachmentsEventArgs(ReferenceHub player, Firearm firearm, /// </summary> public uint NewAttachments { get; set; } - /// <inheritdoc/ > + /// <inheritdoc /> public bool IsAllowed { get; set; } } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangingNicknameEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingNicknameEventArgs.cs index 12a45c24..f2f75e21 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerChangingNicknameEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingNicknameEventArgs.cs @@ -33,7 +33,7 @@ public PlayerChangingNicknameEventArgs(ReferenceHub player, string? oldNickname, /// </summary> /// <remarks>Null means they did not have a custom display-name before.</remarks> public string? OldNickname { get; } - + /// <summary> /// Gets or sets the new nickname of the player. /// </summary> diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDeathEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDeathEventArgs.cs index d58359eb..b3dc4514 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDeathEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDeathEventArgs.cs @@ -22,8 +22,14 @@ public class PlayerDeathEventArgs : EventArgs, IPlayerEvent /// <param name="oldPosition">The previous world position of the player before death.</param> /// <param name="oldVelocity">The previous velocity of the player before death.</param> /// <param name="oldCameraRotation">The previous world rotation of the players camera before death.</param> - public PlayerDeathEventArgs(ReferenceHub player, ReferenceHub? attacker, DamageHandlerBase damageHandler, - RoleTypeId oldRole, Vector3 oldPosition, Vector3 oldVelocity, Quaternion oldCameraRotation) + public PlayerDeathEventArgs( + ReferenceHub player, + ReferenceHub? attacker, + DamageHandlerBase damageHandler, + RoleTypeId oldRole, + Vector3 oldPosition, + Vector3 oldVelocity, + Quaternion oldCameraRotation) { Player = Player.Get(player); Attacker = Player.Get(attacker); diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDryFiringWeaponEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDryFiringWeaponEventArgs.cs index 61d62ffe..231522ff 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDryFiringWeaponEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDryFiringWeaponEventArgs.cs @@ -38,5 +38,4 @@ public PlayerDryFiringWeaponEventArgs(ReferenceHub player, Firearm weapon) /// <inheritdoc cref="FirearmItem"/> [Obsolete($"Use {nameof(FirearmItem)} instead")] public Item Weapon => FirearmItem; - } \ No newline at end of file diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerEnteredPocketDimensionEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerEnteredPocketDimensionEventArgs.cs index 33047082..e55ef609 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerEnteredPocketDimensionEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerEnteredPocketDimensionEventArgs.cs @@ -21,5 +21,5 @@ public PlayerEnteredPocketDimensionEventArgs(ReferenceHub player) /// <summary> /// Gets the player who entered the pocket dimension. /// </summary> - public Player Player { get; } + public Player Player { get; } } \ No newline at end of file diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerEnteringHazardEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerEnteringHazardEventArgs.cs index 65c547a2..66716670 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerEnteringHazardEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerEnteringHazardEventArgs.cs @@ -38,4 +38,3 @@ public PlayerEnteringHazardEventArgs(ReferenceHub player, EnvironmentalHazard ha /// </summary> public bool IsAllowed { get; set; } } - diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerEscapingEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerEscapingEventArgs.cs index 7d35fc47..a4d36c62 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerEscapingEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerEscapingEventArgs.cs @@ -46,7 +46,7 @@ public PlayerEscapingEventArgs(ReferenceHub player, RoleTypeId oldRole, RoleType public RoleTypeId NewRole { get; set; } /// <summary> - /// Gets or sets the escape scenario + /// Gets or sets the escape scenario. /// </summary> public EscapeScenarioType EscapeScenario { get; set; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerIdledTeslaEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerIdledTeslaEventArgs.cs index 507e2f54..ba89ff61 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerIdledTeslaEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerIdledTeslaEventArgs.cs @@ -1,6 +1,6 @@ -using System; -using LabApi.Events.Arguments.Interfaces; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using System; namespace LabApi.Events.Arguments.PlayerEvents; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerIdlingTeslaEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerIdlingTeslaEventArgs.cs index a7085862..b7276ad1 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerIdlingTeslaEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerIdlingTeslaEventArgs.cs @@ -1,6 +1,6 @@ -using System; -using LabApi.Events.Arguments.Interfaces; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using System; namespace LabApi.Events.Arguments.PlayerEvents; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedScp330EventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedScp330EventArgs.cs index a357d661..c5a0e2f3 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedScp330EventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedScp330EventArgs.cs @@ -1,8 +1,8 @@ -using LabApi.Events.Arguments.Interfaces; +using CustomPlayerEffects; +using InventorySystem.Items.Usables.Scp330; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using System; -using CustomPlayerEffects; -using InventorySystem.Items.Usables.Scp330; namespace LabApi.Events.Arguments.PlayerEvents; @@ -49,7 +49,7 @@ public PlayerInteractedScp330EventArgs(ReferenceHub player, int uses, bool playS public bool AllowPunishment { get; } /// <summary> - /// Gets the type of the candy that has been given to the player. + /// Gets the type of the candy that has been given to the player. /// </summary> public CandyKindID CandyType { get; } } \ No newline at end of file diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedWarheadLeverEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedWarheadLeverEventArgs.cs index 8358f32a..2f165fd4 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedWarheadLeverEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedWarheadLeverEventArgs.cs @@ -20,7 +20,7 @@ public PlayerInteractedWarheadLeverEventArgs(ReferenceHub player, bool enabled) Enabled = enabled; } - /// <inheritdoc/ > + /// <inheritdoc /> public Player Player { get; } /// <summary> diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingElevatorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingElevatorEventArgs.cs index 8197b0a6..984ae444 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingElevatorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingElevatorEventArgs.cs @@ -1,7 +1,7 @@ -using LabApi.Events.Arguments.Interfaces; +using Interactables.Interobjects; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using System; -using Interactables.Interobjects; namespace LabApi.Events.Arguments.PlayerEvents; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingScp330EventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingScp330EventArgs.cs index f3f4c54f..b1cdde5e 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingScp330EventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingScp330EventArgs.cs @@ -1,8 +1,8 @@ -using LabApi.Events.Arguments.Interfaces; +using CustomPlayerEffects; +using InventorySystem.Items.Usables.Scp330; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using System; -using CustomPlayerEffects; -using InventorySystem.Items.Usables.Scp330; namespace LabApi.Events.Arguments.PlayerEvents; @@ -50,7 +50,7 @@ public PlayerInteractingScp330EventArgs(ReferenceHub player, int uses, bool play public bool AllowPunishment { get; set; } /// <summary> - /// Gets or sets the type of the candy that is given to the player. + /// Gets or sets the type of the candy that is given to the player. /// <para> /// Set <see cref="IsAllowed"/> or this to <see cref="CandyKindID.None"/> if you don't want to give candy to the player. /// </para> diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerLeavingHazardEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerLeavingHazardEventArgs.cs index 01e06192..16e89808 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerLeavingHazardEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerLeavingHazardEventArgs.cs @@ -34,7 +34,7 @@ public PlayerLeavingHazardEventArgs(ReferenceHub player, EnvironmentalHazard haz public Hazard Hazard { get; } /// <summary> - /// Gets or sets whether the player is allowed to leave the hazard. + /// Gets or sets whether the player is allowed to leave the hazard. /// Setting this to false will result in player keeping the hazard effects and the event will be fired again until it is allowed or the player is back within the hazard's range. /// </summary> public bool IsAllowed { get; set; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerMovementStateChangedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerMovementStateChangedEventArgs.cs index 68a519b4..81a69600 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerMovementStateChangedEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerMovementStateChangedEventArgs.cs @@ -14,7 +14,7 @@ public class PlayerMovementStateChangedEventArgs : EventArgs, IPlayerEvent /// Initializes a new instance of the <see cref="PlayerMovementStateChangedEventArgs"/> class. /// </summary> /// <param name="hub">The player whose movement state has changed.</param> - /// <param name="oldState">Old movement state of the player./param> + /// <param name="oldState">Old movement state of the player.</param> /// <param name="newState">New movement state of the player.</param> public PlayerMovementStateChangedEventArgs(ReferenceHub hub, PlayerMovementState oldState, PlayerMovementState newState) { diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpScp330EventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpScp330EventArgs.cs index e82caa6d..72892b43 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpScp330EventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpScp330EventArgs.cs @@ -1,8 +1,8 @@ using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using System; -using BaseScp330Pickup = InventorySystem.Items.Usables.Scp330.Scp330Pickup; using BaseScp330Bag = InventorySystem.Items.Usables.Scp330.Scp330Bag; +using BaseScp330Pickup = InventorySystem.Items.Usables.Scp330.Scp330Pickup; namespace LabApi.Events.Arguments.PlayerEvents; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBulletHole.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBulletHoleEventArgs.cs similarity index 100% rename from LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBulletHole.cs rename to LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBulletHoleEventArgs.cs diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPreAuthenticatingEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPreAuthenticatingEventArgs.cs index 7eace2d9..bda0c398 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPreAuthenticatingEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPreAuthenticatingEventArgs.cs @@ -37,7 +37,7 @@ public PlayerPreAuthenticatingEventArgs(bool canJoin, string userId, string ipAd } /// <summary> - /// Gets or sets whether the player should be able to join server. ( this value can be false if server is full ) + /// Gets or sets whether the player should be able to join server (this value can be false if server is full). /// </summary> public bool CanJoin { get; set; } @@ -92,7 +92,7 @@ public PlayerPreAuthenticatingEventArgs(bool canJoin, string userId, string ipAd /// <summary> /// Gets or sets the custom rejection writer. /// </summary> - //TODO: Write what exactly this does and how does it work + // TODO: Write what exactly this does and how does it work public NetDataWriter? CustomReject { get; set; } /// <summary> diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerProcessedJailbirdMessageEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerProcessedJailbirdMessageEventArgs.cs index 39c692bd..5cd7c4b4 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerProcessedJailbirdMessageEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerProcessedJailbirdMessageEventArgs.cs @@ -35,7 +35,6 @@ public PlayerProcessedJailbirdMessageEventArgs(ReferenceHub hub, BaseJailbirdIte /// </summary> public JailbirdItem JailbirdItem { get; } - /// <summary> /// The <see cref="JailbirdMessageType"/> processed. /// </summary> diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerRaPlayerListAddingPlayerEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerRaPlayerListAddingPlayerEventArgs.cs index c719f603..abe6a3a6 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerRaPlayerListAddingPlayerEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerRaPlayerListAddingPlayerEventArgs.cs @@ -20,8 +20,14 @@ public class PlayerRaPlayerListAddingPlayerEventArgs : EventArgs, IPlayerEvent, /// <param name="inOverwatch">Whether to include the overwatch icon in the list item.</param> /// <param name="isMuted">Whether to include the is muted icon and link in the list item.</param> /// <param name="body">The body string for the Ra list item.</param> - public PlayerRaPlayerListAddingPlayerEventArgs(CommandSender commandSender, ReferenceHub targetHub, - StringBuilder builder, string prefix, bool inOverwatch, bool isMuted, string body) + public PlayerRaPlayerListAddingPlayerEventArgs( + CommandSender commandSender, + ReferenceHub targetHub, + StringBuilder builder, + string prefix, + bool inOverwatch, + bool isMuted, + string body) { Player = Player.Get(commandSender)!; Target = Player.Get(targetHub); diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerReceivingLoadoutEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerReceivingLoadoutEventArgs.cs index 9e71d4bb..0cee6b3d 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerReceivingLoadoutEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerReceivingLoadoutEventArgs.cs @@ -50,7 +50,7 @@ public PlayerReceivingLoadoutEventArgs(ReferenceHub player, List<ItemType> items public bool IsAllowed { get; set; } /// <summary> - /// Adds item of specifc type to this loadout. + /// Adds item of specific type to this loadout. /// </summary> /// <param name="type">The type of item.</param> public void AddItem(ItemType type) => Items.Add(type); @@ -63,9 +63,13 @@ public PlayerReceivingLoadoutEventArgs(ReferenceHub player, List<ItemType> items public void AddAmmo(ItemType ammoType, ushort ammoAmount) { if (Ammo.ContainsKey(ammoType)) + { Ammo[ammoType] += ammoAmount; + } else + { Ammo.Add(ammoType, ammoAmount); + } } /// <summary> @@ -76,9 +80,13 @@ public void AddAmmo(ItemType ammoType, ushort ammoAmount) public void SetAmmo(ItemType ammoType, ushort ammoAmount) { if (Ammo.ContainsKey(ammoType)) + { Ammo[ammoType] = ammoAmount; + } else + { Ammo.Add(ammoType, ammoAmount); + } } /// <summary> diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerReceivingVoiceMessageEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerReceivingVoiceMessageEventArgs.cs index 900b07d7..8b60ebc5 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerReceivingVoiceMessageEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerReceivingVoiceMessageEventArgs.cs @@ -10,6 +10,8 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// </summary> public class PlayerReceivingVoiceMessageEventArgs : EventArgs, ICancellableEvent, IPlayerEvent, IVoiceMessageEvent { + private VoiceMessage _message; + /// <summary> /// Initializes a new instance of the <see cref="PlayerReceivingVoiceMessageEventArgs"/> class. /// </summary> @@ -45,6 +47,4 @@ public PlayerReceivingVoiceMessageEventArgs(ReferenceHub listener, ref VoiceMess /// <see cref="VoiceChat.VoiceChatChannel.None" /> this will be ignored. /// </remarks> public bool IsAllowed { get; set; } - - private VoiceMessage _message; } \ No newline at end of file diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedCustomRaInfoEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedCustomRaInfoEventArgs.cs index 7d21506a..c49cdd72 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedCustomRaInfoEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedCustomRaInfoEventArgs.cs @@ -17,6 +17,8 @@ public class PlayerRequestedCustomRaInfoEventArgs : EventArgs, IPlayerEvent /// </summary> public const int MaxClipboardCount = 3; + private string[]? _clipboardTexts = null; + /// <summary> /// Initializes a new instance of the <see cref="PlayerRequestedCustomRaInfoEventArgs"/> class. /// </summary> @@ -24,8 +26,11 @@ public class PlayerRequestedCustomRaInfoEventArgs : EventArgs, IPlayerEvent /// <param name="selectionArgs">The request arguments.</param> /// <param name="isSensitiveInfo">Whether the info being requested is sensitive.</param> /// <param name="infoBuilder">The <see cref="StringBuilder"/> use to build the response.</param> - public PlayerRequestedCustomRaInfoEventArgs(CommandSender commandSender, ArraySegment<string> selectionArgs, - bool isSensitiveInfo, StringBuilder infoBuilder) + public PlayerRequestedCustomRaInfoEventArgs( + CommandSender commandSender, + ArraySegment<string> selectionArgs, + bool isSensitiveInfo, + StringBuilder infoBuilder) { Player = Player.Get(commandSender)!; SelectedIdentifiers = selectionArgs.First().Split("."); @@ -54,25 +59,26 @@ public PlayerRequestedCustomRaInfoEventArgs(CommandSender commandSender, ArraySe /// </summary> public StringBuilder InfoBuilder { get; } - private string[]? clipboardTexts = null; - /// <summary> /// Creates a clipboard link for the RA. /// </summary> /// <remarks> - /// Usage <c>ev.InfoBuilder.Append(ev.SetClipboardText("Click Me", "Text to copy to clipboard on click", 0))</c> + /// Usage <c>ev.InfoBuilder.Append(ev.SetClipboardText("Click Me", "Text to copy to clipboard on click", 0));</c>. /// </remarks> /// <param name="linkText">Text to display as the link.</param> /// <param name="clipboardText">Text to copy to the clipboard when clicking on the link.</param> /// <param name="id">The id of the clipboard, must be between 0 and <see cref="MaxClipboardCount"/>.</param> /// <returns>The formated clipboard link text.</returns> + /// <exception cref="ArgumentOutOfRangeException">Thown when id is not between 0 and <see cref="MaxClipboardCount"/>.</exception> public string SetClipboardText(string linkText, string clipboardText, byte id) { if (id >= MaxClipboardCount) + { throw new ArgumentOutOfRangeException(nameof(id), id, $"id must be between 0 and {MaxClipboardCount}"); + } - clipboardTexts ??= new string[MaxClipboardCount]; - clipboardTexts[id] = clipboardText; + _clipboardTexts ??= new string[MaxClipboardCount]; + _clipboardTexts[id] = clipboardText; return $"<link={LinkIdForClipboardId(id)}>{linkText}</link>"; } @@ -83,18 +89,22 @@ public string SetClipboardText(string linkText, string clipboardText, byte id) /// <param name="id">The id associated with the clipboard text.</param> /// <param name="text">The found text, otherwise <see langword="null"/>.</param> /// <returns><see langword="true"/> if set and not empty, otherwise <see langword="false"/>.</returns> - /// <exception cref="ArgumentOutOfRangeException"></exception> + /// <exception cref="ArgumentOutOfRangeException">Thown when id is not between 0 and <see cref="MaxClipboardCount"/>.</exception> public bool TryGetClipboardText(byte id, [NotNullWhen(true)] out string? text) { if (id >= MaxClipboardCount) + { throw new ArgumentOutOfRangeException(nameof(id), id, $"id must be between 0 and {MaxClipboardCount}"); + } text = null; - if (clipboardTexts == null) + if (_clipboardTexts == null) + { return false; + } - text = clipboardTexts[id]; + text = _clipboardTexts[id]; return !string.IsNullOrEmpty(text); } @@ -103,6 +113,6 @@ public bool TryGetClipboardText(byte id, [NotNullWhen(true)] out string? text) 0 => "CP_ID", 1 => "CP_IP", 2 => "CP_USERID", - _ => throw new ArgumentOutOfRangeException(nameof(id), id, $"id must be between 0 and {MaxClipboardCount}") + _ => throw new ArgumentOutOfRangeException(nameof(id), id, $"id must be between 0 and {MaxClipboardCount}"), }; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedRaPlayerInfoEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedRaPlayerInfoEventArgs.cs index 6320199b..2fe49664 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedRaPlayerInfoEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedRaPlayerInfoEventArgs.cs @@ -21,8 +21,15 @@ public class PlayerRequestedRaPlayerInfoEventArgs : EventArgs, IPlayerEvent, ITa /// <param name="idBuilder">The <see cref="StringBuilder"/> used to construct the clipboard text of the targets player id.</param> /// <param name="ipBuilder">The <see cref="StringBuilder"/> used to construct the clipboard text of the targets ip address.</param> /// <param name="userIdBuilder">The <see cref="StringBuilder"/> used to construct the clipboard text of the targets user id.</param> - public PlayerRequestedRaPlayerInfoEventArgs(CommandSender commandSender, ReferenceHub targetHub, bool isSensitiveInfo, - bool hasUserIdPerms, StringBuilder infoBuilder, StringBuilder idBuilder, StringBuilder ipBuilder, StringBuilder userIdBuilder) + public PlayerRequestedRaPlayerInfoEventArgs( + CommandSender commandSender, + ReferenceHub targetHub, + bool isSensitiveInfo, + bool hasUserIdPerms, + StringBuilder infoBuilder, + StringBuilder idBuilder, + StringBuilder ipBuilder, + StringBuilder userIdBuilder) { Player = Player.Get(commandSender)!; Target = Player.Get(targetHub); diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedRaPlayersInfoEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedRaPlayersInfoEventArgs.cs index 376549d3..09c01901 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedRaPlayersInfoEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedRaPlayersInfoEventArgs.cs @@ -12,7 +12,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// </summary> public class PlayerRequestedRaPlayersInfoEventArgs : EventArgs, IPlayerEvent { - private IEnumerable<ReferenceHub> _targets; + private readonly IEnumerable<ReferenceHub> _targets; /// <summary> /// Initializes a new instance of the <see cref="PlayerRequestedRaPlayersInfoEventArgs"/> class. @@ -25,9 +25,15 @@ public class PlayerRequestedRaPlayersInfoEventArgs : EventArgs, IPlayerEvent /// <param name="idBuilder">The <see cref="StringBuilder"/> used to build the clipboard text for the targets ids.</param> /// <param name="ipBuilder">The <see cref="StringBuilder"/> used to build the clipboard text for the targets IPs.</param> /// <param name="userIdBuilder">The <see cref="StringBuilder"/> used to build the clipboard text for the targets user ids.</param> - public PlayerRequestedRaPlayersInfoEventArgs(CommandSender commandSender, IEnumerable<ReferenceHub> targets, - bool isSensitiveInfo, bool hasUserIdPerms, StringBuilder infoBuilder, StringBuilder idBuilder, - StringBuilder ipBuilder, StringBuilder userIdBuilder) + public PlayerRequestedRaPlayersInfoEventArgs( + CommandSender commandSender, + IEnumerable<ReferenceHub> targets, + bool isSensitiveInfo, + bool hasUserIdPerms, + StringBuilder infoBuilder, + StringBuilder idBuilder, + StringBuilder ipBuilder, + StringBuilder userIdBuilder) { Player = Player.Get(commandSender)!; IsSensitiveInfo = isSensitiveInfo; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerRequestingRaPlayerInfoEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestingRaPlayerInfoEventArgs.cs index e36d23e3..2d43c423 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerRequestingRaPlayerInfoEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestingRaPlayerInfoEventArgs.cs @@ -19,8 +19,13 @@ public class PlayerRequestingRaPlayerInfoEventArgs : EventArgs, IPlayerEvent, IT /// <param name="hasSensitiveInfoPerms">Whether the player has perms to view sensitive info.</param> /// <param name="hasUserIdPerms">Whether the player has perms to view the targets user id.</param> /// <param name="infoBuilder">The <see cref="StringBuilder"/> used to construct the response message.</param> - public PlayerRequestingRaPlayerInfoEventArgs(CommandSender commandSender, ReferenceHub targetHub, - bool isSensitiveInfo, bool hasSensitiveInfoPerms, bool hasUserIdPerms, StringBuilder infoBuilder) + public PlayerRequestingRaPlayerInfoEventArgs( + CommandSender commandSender, + ReferenceHub targetHub, + bool isSensitiveInfo, + bool hasSensitiveInfoPerms, + bool hasUserIdPerms, + StringBuilder infoBuilder) { Player = Player.Get(commandSender)!; Target = Player.Get(targetHub); diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerRequestingRaPlayerListEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestingRaPlayerListEventArgs.cs index 74e9fd57..069f42e1 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerRequestingRaPlayerListEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestingRaPlayerListEventArgs.cs @@ -20,8 +20,13 @@ public class PlayerRequestingRaPlayerListEventArgs : EventArgs, IPlayerEvent, IC /// <param name="sorting">The <see cref="PlayerSorting"/> mode to use.</param> /// <param name="viewHiddenLocalBadges">Whether the requester can view hidden local RA badges or not.</param> /// <param name="viewHiddenGlobalBadges">Whether the requester can view hidden global RA badges or not.</param> - public PlayerRequestingRaPlayerListEventArgs(CommandSender commandSender, StringBuilder builder, bool isDescending, - PlayerSorting sorting, bool viewHiddenLocalBadges, bool viewHiddenGlobalBadges) + public PlayerRequestingRaPlayerListEventArgs( + CommandSender commandSender, + StringBuilder builder, + bool isDescending, + PlayerSorting sorting, + bool viewHiddenLocalBadges, + bool viewHiddenGlobalBadges) { Player = Player.Get(commandSender)!; ListBuilder = builder; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerRequestingRaPlayersInfoEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestingRaPlayersInfoEventArgs.cs index 5b41587d..f35da228 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerRequestingRaPlayersInfoEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestingRaPlayersInfoEventArgs.cs @@ -12,7 +12,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// </summary> public class PlayerRequestingRaPlayersInfoEventArgs : EventArgs, IPlayerEvent, ICancellableEvent { - private IEnumerable<ReferenceHub> _targets; + private readonly IEnumerable<ReferenceHub> _targets; /// <summary> /// Initializes a new instance of the <see cref="PlayerRequestingRaPlayersInfoEventArgs"/> class. @@ -23,8 +23,13 @@ public class PlayerRequestingRaPlayersInfoEventArgs : EventArgs, IPlayerEvent, I /// <param name="hasSensitiveInfoPerms">Whether the player has perms to view sensitive info.</param> /// <param name="hasUserIdPerms">Whether the player has perms to view the user ids of the targets.</param> /// <param name="infoBuilder">The <see cref="StringBuilder"/> used to construct the response message.</param> - public PlayerRequestingRaPlayersInfoEventArgs(CommandSender commandSender, IEnumerable<ReferenceHub> targets, - bool isSensitiveInfo, bool hasSensitiveInfoPerms, bool hasUserIdPerms, StringBuilder infoBuilder) + public PlayerRequestingRaPlayersInfoEventArgs( + CommandSender commandSender, + IEnumerable<ReferenceHub> targets, + bool isSensitiveInfo, + bool hasSensitiveInfoPerms, + bool hasUserIdPerms, + StringBuilder infoBuilder) { Player = Player.Get(commandSender)!; IsSensitiveInfo = isSensitiveInfo; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerRoomChangedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerRoomChangedEventArgs.cs index 416e51c2..8dc27940 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerRoomChangedEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerRoomChangedEventArgs.cs @@ -15,7 +15,7 @@ public class PlayerRoomChangedEventArgs : EventArgs, IPlayerEvent /// </summary> /// <param name="player">The player whose room changed.</param> /// <param name="oldRoom">The old room.</param> - /// <param name="newRoom">The new room</param> + /// <param name="newRoom">The new room.</param> public PlayerRoomChangedEventArgs(ReferenceHub player, RoomIdentifier oldRoom, RoomIdentifier newRoom) { Player = Player.Get(player); @@ -34,7 +34,7 @@ public PlayerRoomChangedEventArgs(ReferenceHub player, RoomIdentifier oldRoom, R public Room? OldRoom { get; } /// <summary> - /// Gets the new rom. May be null if the player went into void, died and such. + /// Gets the new room. May be null if the player went into void, died and such. /// </summary> public Room? NewRoom { get; } } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingToyEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingToyEventArgs.cs index d6980cea..78c48f12 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingToyEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingToyEventArgs.cs @@ -6,7 +6,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> -/// Represents the arguments for the <see cref="Handlers.PlayerEvents.SearchingToy"/> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.SearchingToy"/>. /// </summary> public class PlayerSearchingToyEventArgs : EventArgs, IPlayerEvent, IInteractableEvent, ICancellableEvent { diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSendingAttachmentsPrefsEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSendingAttachmentsPrefsEventArgs.cs index d44aa215..59bb8401 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSendingAttachmentsPrefsEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSendingAttachmentsPrefsEventArgs.cs @@ -5,7 +5,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> -/// Represents the arguments for the <see cref="Handlers.PlayerEvents.ChangingAttachmentsPrefs"/> event. +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.SendingAttachmentsPrefs"/> event. /// </summary> public class PlayerSendingAttachmentsPrefsEventArgs : EventArgs, IPlayerEvent, ICancellableEvent { @@ -25,7 +25,7 @@ public PlayerSendingAttachmentsPrefsEventArgs(ReferenceHub player, ItemType fire IsAllowed = true; } - /// <inheritdoc/ > + /// <inheritdoc /> public Player Player { get; } /// <summary> @@ -43,6 +43,6 @@ public PlayerSendingAttachmentsPrefsEventArgs(ReferenceHub player, ItemType fire /// </summary> public uint NewAttachments { get; set; } - /// <inheritdoc/ > + /// <inheritdoc /> public bool IsAllowed { get; set; } } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSendingVoiceMessageEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSendingVoiceMessageEventArgs.cs index 30652ee1..883973c9 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSendingVoiceMessageEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSendingVoiceMessageEventArgs.cs @@ -10,6 +10,8 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// </summary> public class PlayerSendingVoiceMessageEventArgs : EventArgs, ICancellableEvent, IPlayerEvent, IVoiceMessageEvent { + private VoiceMessage _message; + /// <summary> /// Initializes a new instance of the <see cref="PlayerSendingVoiceMessageEventArgs"/> class. /// </summary> @@ -39,6 +41,4 @@ public PlayerSendingVoiceMessageEventArgs(ref VoiceMessage message) /// <see cref="VoiceChat.VoiceChatChannel.None" /> this will be ignored. /// </remarks> public bool IsAllowed { get; set; } - - private VoiceMessage _message; } \ No newline at end of file diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSentAttachmentsPrefsEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSentAttachmentsPrefsEventArgs.cs index 4c98624b..0afd29cd 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSentAttachmentsPrefsEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSentAttachmentsPrefsEventArgs.cs @@ -5,7 +5,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> -/// Represents the arguments for the <see cref="Handlers.PlayerEvents.ChangedAttachmentsPrefs"/> event. +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.SentAttachmentsPrefs"/> event. /// </summary> public class PlayerSentAttachmentsPrefsEventArgs : EventArgs, IPlayerEvent { @@ -24,7 +24,7 @@ public PlayerSentAttachmentsPrefsEventArgs(ReferenceHub player, ItemType firearm NewAttachments = newAttachments; } - /// <inheritdoc/ > + /// <inheritdoc /> public Player Player { get; } /// <summary> @@ -38,8 +38,7 @@ public PlayerSentAttachmentsPrefsEventArgs(ReferenceHub player, ItemType firearm public uint OldAttachments { get; } /// <summary> - /// Gets the new attachments code stored on the server. + /// Gets the new attachments code stored on the server. /// </summary> public uint NewAttachments { get; } - } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSpawningEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSpawningEventArgs.cs index ba75ad34..1ef134f2 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSpawningEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSpawningEventArgs.cs @@ -11,8 +11,8 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// </summary> public class PlayerSpawningEventArgs : EventArgs, IPlayerEvent, ICancellableEvent { - Vector3 _spawnLocation; - float _horizontalRotation; + private Vector3 _spawnLocation; + private float _horizontalRotation; /// <summary> /// Initializes a new instance of the <see cref="PlayerSpawningEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerThrowingItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerThrowingItemEventArgs.cs index 03c518fc..6ec955fd 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerThrowingItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerThrowingItemEventArgs.cs @@ -1,5 +1,4 @@ -using InventorySystem.Items; -using InventorySystem.Items.Pickups; +using InventorySystem.Items.Pickups; using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using System; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerToggledNoclipEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerToggledNoclipEventArgs.cs index a7a438bd..9dac9008 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerToggledNoclipEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerToggledNoclipEventArgs.cs @@ -2,32 +2,31 @@ using LabApi.Features.Wrappers; using System; -namespace LabApi.Events.Arguments.PlayerEvents +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.ToggledNoclip"/> event. +/// </summary> +public class PlayerToggledNoclipEventArgs : EventArgs, IPlayerEvent { /// <summary> - /// Represents the arguments for the <see cref="Handlers.PlayerEvents.ToggledNoclip"/> event. + /// Initializes a new instance of the <see cref="PlayerToggledNoclipEventArgs"/> class. /// </summary> - public class PlayerToggledNoclipEventArgs : EventArgs, IPlayerEvent + /// <param name="player">The player who has toggled the noclip.</param> + /// <param name="isNoclipping">The new state of the noclip.</param> + public PlayerToggledNoclipEventArgs(ReferenceHub player, bool isNoclipping) { - /// <summary> - /// Initializes a new instance of the <see cref="PlayerToggledNoclipEventArgs"/> class. - /// </summary> - /// <param name="player">The player who has toggled the noclip.</param> - /// <param name="isNoclipping">The new state of the noclip.</param> - public PlayerToggledNoclipEventArgs(ReferenceHub player, bool isNoclipping) - { - Player = Player.Get(player); - IsNoclipping = isNoclipping; - } + Player = Player.Get(player); + IsNoclipping = isNoclipping; + } - /// <summary> - /// Gets the player who toggled noclip. - /// </summary> - public Player Player { get; } + /// <summary> + /// Gets the player who toggled noclip. + /// </summary> + public Player Player { get; } - /// <summary> - /// Gets whether the player now has noclip enabled or not. - /// </summary> - public bool IsNoclipping { get; } - } + /// <summary> + /// Gets whether the player now has noclip enabled or not. + /// </summary> + public bool IsNoclipping { get; } } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingNoclipEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingNoclipEventArgs.cs index 3257e209..f11a8c9b 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingNoclipEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingNoclipEventArgs.cs @@ -10,7 +10,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; public class PlayerTogglingNoclipEventArgs : EventArgs, IPlayerEvent, ICancellableEvent { /// <summary> - /// Initializes a new instance of <see cref=" PlayerTogglingNoclipEventArgs"/> clas. + /// Initializes a new instance of <see cref=" PlayerTogglingNoclipEventArgs"/> class. /// </summary> /// <param name="player">The player who is attempting to toggle noclip.</param> /// <param name="newState">Whether the noclip state will be enabled or disabled.</param> diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerTriggeredTeslaEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerTriggeredTeslaEventArgs.cs index b007c9ff..05889a0f 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerTriggeredTeslaEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerTriggeredTeslaEventArgs.cs @@ -1,6 +1,6 @@ -using System; -using LabApi.Events.Arguments.Interfaces; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using System; namespace LabApi.Events.Arguments.PlayerEvents; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerTriggeringTeslaEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerTriggeringTeslaEventArgs.cs index 9c4ccf42..9faa14b0 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerTriggeringTeslaEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerTriggeringTeslaEventArgs.cs @@ -1,6 +1,6 @@ -using System; -using LabApi.Events.Arguments.Interfaces; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using System; namespace LabApi.Events.Arguments.PlayerEvents; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUncuffingEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUncuffingEventArgs.cs index 478b2a38..bee04a32 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUncuffingEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUncuffingEventArgs.cs @@ -14,7 +14,7 @@ public class PlayerUncuffingEventArgs : EventArgs, IPlayerEvent, ITargetEvent, I /// </summary> /// <param name="player">The player who is uncuffing another player.</param> /// <param name="target">The player who is being uncuffed.</param> - /// <param name="canUnDetainAsScp">Whenever the player can undetain as SCP player</param> + /// <param name="canUnDetainAsScp">Whenever the player can undetain as SCP player.</param> public PlayerUncuffingEventArgs(ReferenceHub player, ReferenceHub target, bool canUnDetainAsScp) { IsAllowed = true; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockedGeneratorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockedGeneratorEventArgs.cs index dfa00707..92db151c 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockedGeneratorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockedGeneratorEventArgs.cs @@ -29,4 +29,3 @@ public PlayerUnlockedGeneratorEventArgs(ReferenceHub player, Scp079Generator gen /// <inheritdoc /> public Generator Generator { get; } } - diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockedWarheadButtonEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockedWarheadButtonEventArgs.cs index 445d543e..44ffa9fc 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockedWarheadButtonEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockedWarheadButtonEventArgs.cs @@ -23,4 +23,3 @@ public PlayerUnlockedWarheadButtonEventArgs(ReferenceHub player) /// </summary> public Player Player { get; } } - diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockingGeneratorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockingGeneratorEventArgs.cs index 9cb18a10..dadc2a6c 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockingGeneratorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockingGeneratorEventArgs.cs @@ -42,4 +42,3 @@ public PlayerUnlockingGeneratorEventArgs(ReferenceHub player, Scp079Generator ge /// </summary> public bool IsAllowed { get; set; } } - diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUsingIntercomEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUsingIntercomEventArgs.cs index ec7f93bb..3879a03c 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUsingIntercomEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUsingIntercomEventArgs.cs @@ -15,7 +15,7 @@ public class PlayerUsingIntercomEventArgs : EventArgs, IPlayerEvent, ICancellabl /// </summary> /// <param name="player">The player that is using the intercom.</param> /// <param name="state">State of the intercom.</param> - //TODO: Add intercom class and ref it docs + // TODO: Add intercom class and ref it docs public PlayerUsingIntercomEventArgs(ReferenceHub player, IntercomState state) { IsAllowed = true; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerZoneChangedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerZoneChangedEventArgs.cs index cde8413a..ff5fb9f1 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerZoneChangedEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerZoneChangedEventArgs.cs @@ -15,7 +15,7 @@ public class PlayerZoneChangedEventArgs : EventArgs, IPlayerEvent /// </summary> /// <param name="player">The player whose zone changed.</param> /// <param name="oldZone">The old zone.</param> - /// <param name="newZone">The new zone</param> + /// <param name="newZone">The new zone.</param> public PlayerZoneChangedEventArgs(ReferenceHub player, FacilityZone oldZone, FacilityZone newZone) { Player = Player.Get(player); @@ -31,10 +31,10 @@ public PlayerZoneChangedEventArgs(ReferenceHub player, FacilityZone oldZone, Fac /// <summary> /// Gets the old zone. May be <see cref="FacilityZone.None"/> if the player just spawned, went through void and such. /// </summary> - public FacilityZone OldZone; + public FacilityZone OldZone { get; } /// <summary> - /// Gets the new rom. May be <see cref="FacilityZone.None"/> if the player went into void, died and such. + /// Gets the new room. May be <see cref="FacilityZone.None"/> if the player went into void, died and such. /// </summary> - public FacilityZone NewZone; + public FacilityZone NewZone { get; } } diff --git a/LabApi/Events/Arguments/Scp0492Events/Scp0492ConsumedCorpseEventArgs.cs b/LabApi/Events/Arguments/Scp0492Events/Scp0492ConsumedCorpseEventArgs.cs index cbb3b2ae..62019aec 100644 --- a/LabApi/Events/Arguments/Scp0492Events/Scp0492ConsumedCorpseEventArgs.cs +++ b/LabApi/Events/Arguments/Scp0492Events/Scp0492ConsumedCorpseEventArgs.cs @@ -1,7 +1,7 @@ -using System; -using LabApi.Events.Arguments.Interfaces; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using PlayerRoles.Ragdolls; +using System; namespace LabApi.Events.Arguments.Scp0492Events; diff --git a/LabApi/Events/Arguments/Scp0492Events/Scp0492ConsumingCorpseEventArgs.cs b/LabApi/Events/Arguments/Scp0492Events/Scp0492ConsumingCorpseEventArgs.cs index fd87c9f9..ce42bd82 100644 --- a/LabApi/Events/Arguments/Scp0492Events/Scp0492ConsumingCorpseEventArgs.cs +++ b/LabApi/Events/Arguments/Scp0492Events/Scp0492ConsumingCorpseEventArgs.cs @@ -1,7 +1,7 @@ -using System; -using LabApi.Events.Arguments.Interfaces; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using PlayerRoles.Ragdolls; +using System; namespace LabApi.Events.Arguments.Scp0492Events; diff --git a/LabApi/Events/Arguments/Scp0492Events/Scp0492StartedConsumingCorpseEventArgs.cs b/LabApi/Events/Arguments/Scp0492Events/Scp0492StartedConsumingCorpseEventArgs.cs index 09b4374d..640188ae 100644 --- a/LabApi/Events/Arguments/Scp0492Events/Scp0492StartedConsumingCorpseEventArgs.cs +++ b/LabApi/Events/Arguments/Scp0492Events/Scp0492StartedConsumingCorpseEventArgs.cs @@ -1,7 +1,7 @@ -using System; -using LabApi.Events.Arguments.Interfaces; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using PlayerRoles.Ragdolls; +using System; namespace LabApi.Events.Arguments.Scp0492Events; diff --git a/LabApi/Events/Arguments/Scp0492Events/Scp0492StartingConsumingCorpseEventArgs.cs b/LabApi/Events/Arguments/Scp0492Events/Scp0492StartingConsumingCorpseEventArgs.cs index b696c4a2..fa3b9d47 100644 --- a/LabApi/Events/Arguments/Scp0492Events/Scp0492StartingConsumingCorpseEventArgs.cs +++ b/LabApi/Events/Arguments/Scp0492Events/Scp0492StartingConsumingCorpseEventArgs.cs @@ -1,8 +1,8 @@ -using System; -using LabApi.Events.Arguments.Interfaces; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using PlayerRoles.PlayableScps.Scp049.Zombies; using PlayerRoles.Ragdolls; +using System; namespace LabApi.Events.Arguments.Scp0492Events; diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079BlackedOutRoomEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079BlackedOutRoomEventArgs.cs index 1bc79797..bb90ee88 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079BlackedOutRoomEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079BlackedOutRoomEventArgs.cs @@ -1,7 +1,7 @@ using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; -using System; using MapGeneration; +using System; namespace LabApi.Events.Arguments.Scp079Events; diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079BlackingOutRoomEventsArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079BlackingOutRoomEventsArgs.cs index c65a59cd..e949c6ab 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079BlackingOutRoomEventsArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079BlackingOutRoomEventsArgs.cs @@ -1,7 +1,7 @@ using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; -using System; using MapGeneration; +using System; namespace LabApi.Events.Arguments.Scp079Events; diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079CancelledRoomLockdownEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079CancelledRoomLockdownEventArgs.cs index 5a0399e9..3a5e8d72 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079CancelledRoomLockdownEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079CancelledRoomLockdownEventArgs.cs @@ -1,7 +1,7 @@ using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; -using System; using MapGeneration; +using System; namespace LabApi.Events.Arguments.Scp079Events; diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079CancellingRoomLockdownEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079CancellingRoomLockdownEventArgs.cs index 756326e0..31380bd1 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079CancellingRoomLockdownEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079CancellingRoomLockdownEventArgs.cs @@ -1,7 +1,7 @@ using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; -using System; using MapGeneration; +using System; namespace LabApi.Events.Arguments.Scp079Events; diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079GainedExperienceEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079GainedExperienceEventArgs.cs index bfcfe624..432340dc 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079GainedExperienceEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079GainedExperienceEventArgs.cs @@ -18,7 +18,7 @@ public class Scp079GainedExperienceEventArgs : EventArgs, IPlayerEvent /// <param name="player">The SCP-079 player instance.</param> /// <param name="amount">The amount of experience gained.</param> /// <param name="reason">The reason of experience gain shown in HUD.</param> - /// <param name = "subject" > The optional subject of the notification, used as replacement to display which class has been terminated</param> + /// <param name = "subject" > The optional subject of the notification, used as replacement to display which class has been terminated.</param> public Scp079GainedExperienceEventArgs(ReferenceHub player, float amount, Scp079HudTranslation reason, RoleTypeId subject) { Player = Player.Get(player); diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079GainingExperienceEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079GainingExperienceEventArgs.cs index 75e26a99..7fa2f98c 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079GainingExperienceEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079GainingExperienceEventArgs.cs @@ -17,7 +17,7 @@ public class Scp079GainingExperienceEventArgs : EventArgs, IPlayerEvent, ICancel /// <param name="player">The SCP-079 player instance.</param> /// <param name="amount">The amount of experience that is going to be gained.</param> /// <param name="reason">The reason of experience gain that is going to be shown in HUD.</param> - /// <param name="subject">The optional subject of the notification, used as replacement to display which class has been terminated</param> + /// <param name="subject">The optional subject of the notification, used as replacement to display which class has been terminated.</param> public Scp079GainingExperienceEventArgs(ReferenceHub player, float amount, Scp079HudTranslation reason, RoleTypeId subject) { Player = Player.Get(player); diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079LockedDoorEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079LockedDoorEventArgs.cs index 112e5afe..3ea8d869 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079LockedDoorEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079LockedDoorEventArgs.cs @@ -1,7 +1,7 @@ -using LabApi.Events.Arguments.Interfaces; +using Interactables.Interobjects.DoorUtils; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using System; -using Interactables.Interobjects.DoorUtils; namespace LabApi.Events.Arguments.Scp079Events; diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079LockedDownRoomEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079LockedDownRoomEventArgs.cs index 91279f7f..30c6ca66 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079LockedDownRoomEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079LockedDownRoomEventArgs.cs @@ -1,7 +1,7 @@ using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; -using System; using MapGeneration; +using System; namespace LabApi.Events.Arguments.Scp079Events; diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079LockingDoorEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079LockingDoorEventArgs.cs index ee1e7802..bd1532ad 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079LockingDoorEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079LockingDoorEventArgs.cs @@ -1,7 +1,7 @@ -using LabApi.Events.Arguments.Interfaces; +using Interactables.Interobjects.DoorUtils; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using System; -using Interactables.Interobjects.DoorUtils; namespace LabApi.Events.Arguments.Scp079Events; diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079LockingDownRoomEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079LockingDownRoomEventArgs.cs index a0aaa940..910f09e1 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079LockingDownRoomEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079LockingDownRoomEventArgs.cs @@ -1,7 +1,7 @@ using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; -using System; using MapGeneration; +using System; namespace LabApi.Events.Arguments.Scp079Events; diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079UnlockedDoorEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079UnlockedDoorEventArgs.cs index ac2b2128..fa349fa0 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079UnlockedDoorEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079UnlockedDoorEventArgs.cs @@ -1,7 +1,7 @@ -using LabApi.Events.Arguments.Interfaces; +using Interactables.Interobjects.DoorUtils; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using System; -using Interactables.Interobjects.DoorUtils; namespace LabApi.Events.Arguments.Scp079Events; diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079UnlockingDoorEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079UnlockingDoorEventArgs.cs index 9d55ab03..164ba29f 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079UnlockingDoorEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079UnlockingDoorEventArgs.cs @@ -1,7 +1,7 @@ -using LabApi.Events.Arguments.Interfaces; +using Interactables.Interobjects.DoorUtils; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using System; -using Interactables.Interobjects.DoorUtils; namespace LabApi.Events.Arguments.Scp079Events; diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079UsedTeslaEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079UsedTeslaEventArgs.cs index ff26e05d..18da93e2 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079UsedTeslaEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079UsedTeslaEventArgs.cs @@ -24,7 +24,7 @@ public Scp079UsedTeslaEventArgs(ReferenceHub player, TeslaGate tesla) /// The SCP-079 player instance. /// </summary> public Player Player { get; } - + /// <inheritdoc /> public Tesla Tesla { get; } } diff --git a/LabApi/Events/Arguments/Scp096Events/Scp096AddedTargetEventArgs.cs b/LabApi/Events/Arguments/Scp096Events/Scp096AddedTargetEventArgs.cs index b90adbe1..9918d1fc 100644 --- a/LabApi/Events/Arguments/Scp096Events/Scp096AddedTargetEventArgs.cs +++ b/LabApi/Events/Arguments/Scp096Events/Scp096AddedTargetEventArgs.cs @@ -33,7 +33,7 @@ public Scp096AddedTargetEventArgs(ReferenceHub player, ReferenceHub target, bool public Player Target { get; } /// <summary> - /// Whether the target was looking at SCP-096 + /// Whether the target was looking at SCP-096. /// </summary> public bool WasLooking { get; } } diff --git a/LabApi/Events/Arguments/Scp096Events/Scp096AddingTargetEventArgs.cs b/LabApi/Events/Arguments/Scp096Events/Scp096AddingTargetEventArgs.cs index afc74b28..af12b4ab 100644 --- a/LabApi/Events/Arguments/Scp096Events/Scp096AddingTargetEventArgs.cs +++ b/LabApi/Events/Arguments/Scp096Events/Scp096AddingTargetEventArgs.cs @@ -34,7 +34,7 @@ public Scp096AddingTargetEventArgs(ReferenceHub player, ReferenceHub target, boo public Player Target { get; } /// <summary> - /// Whether the target was looking at SCP-096 + /// Whether the target was looking at SCP-096. /// </summary> public bool WasLooking { get; } diff --git a/LabApi/Events/Arguments/Scp106Events/Scp106ChangedStalkModeEventArgs.cs b/LabApi/Events/Arguments/Scp106Events/Scp106ChangedStalkModeEventArgs.cs index 0fdca5de..f32b021f 100644 --- a/LabApi/Events/Arguments/Scp106Events/Scp106ChangedStalkModeEventArgs.cs +++ b/LabApi/Events/Arguments/Scp106Events/Scp106ChangedStalkModeEventArgs.cs @@ -1,6 +1,6 @@ -using System; using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using System; namespace LabApi.Events.Arguments.Scp106Events; @@ -19,12 +19,12 @@ public Scp106ChangedStalkModeEventArgs(ReferenceHub player, bool active) Player = Player.Get(player); IsStalkActive = active; } - + /// <summary> /// Whether the ability was activated or deactivated. /// </summary> public bool IsStalkActive { get; } - + /// <summary> /// The SCP-106 player instance. /// </summary> diff --git a/LabApi/Events/Arguments/Scp106Events/Scp106ChangedSubmersionStatusEventArgs.cs b/LabApi/Events/Arguments/Scp106Events/Scp106ChangedSubmersionStatusEventArgs.cs index d2645590..044d5c75 100644 --- a/LabApi/Events/Arguments/Scp106Events/Scp106ChangedSubmersionStatusEventArgs.cs +++ b/LabApi/Events/Arguments/Scp106Events/Scp106ChangedSubmersionStatusEventArgs.cs @@ -1,6 +1,6 @@ -using System; using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using System; namespace LabApi.Events.Arguments.Scp106Events; @@ -19,12 +19,12 @@ public Scp106ChangedSubmersionStatusEventArgs(ReferenceHub player, bool isSubmer Player = Player.Get(player); IsSubmerging = isSubmerging; } - + /// <summary> /// Whether the SCP-106 is submerging or emerging. /// </summary> public bool IsSubmerging { get; } - + /// <summary> /// The SCP-106 player instance. /// </summary> diff --git a/LabApi/Events/Arguments/Scp106Events/Scp106ChangedVigorEventArgs.cs b/LabApi/Events/Arguments/Scp106Events/Scp106ChangedVigorEventArgs.cs index a94ed84b..c6334e43 100644 --- a/LabApi/Events/Arguments/Scp106Events/Scp106ChangedVigorEventArgs.cs +++ b/LabApi/Events/Arguments/Scp106Events/Scp106ChangedVigorEventArgs.cs @@ -1,6 +1,6 @@ -using System; using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using System; namespace LabApi.Events.Arguments.Scp106Events; diff --git a/LabApi/Events/Arguments/Scp106Events/Scp106ChangingStalkModeEventArgs.cs b/LabApi/Events/Arguments/Scp106Events/Scp106ChangingStalkModeEventArgs.cs index dbf5be08..19eaa4e6 100644 --- a/LabApi/Events/Arguments/Scp106Events/Scp106ChangingStalkModeEventArgs.cs +++ b/LabApi/Events/Arguments/Scp106Events/Scp106ChangingStalkModeEventArgs.cs @@ -1,6 +1,6 @@ -using System; using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using System; namespace LabApi.Events.Arguments.Scp106Events; @@ -20,17 +20,17 @@ public Scp106ChangingStalkModeEventArgs(ReferenceHub player, bool active) Player = Player.Get(player); IsStalkActive = active; } - + /// <summary> /// Whether the ability is being activated or deactivated. /// </summary> public bool IsStalkActive { get; } - + /// <summary> /// The SCP-106 player instance. /// </summary> public Player Player { get; } - + /// <inheritdoc /> public bool IsAllowed { get; set; } } \ No newline at end of file diff --git a/LabApi/Events/Arguments/Scp106Events/Scp106ChangingSubmersionStatusEventArgs.cs b/LabApi/Events/Arguments/Scp106Events/Scp106ChangingSubmersionStatusEventArgs.cs index ad9b800f..4e5489fa 100644 --- a/LabApi/Events/Arguments/Scp106Events/Scp106ChangingSubmersionStatusEventArgs.cs +++ b/LabApi/Events/Arguments/Scp106Events/Scp106ChangingSubmersionStatusEventArgs.cs @@ -1,6 +1,6 @@ -using System; using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using System; namespace LabApi.Events.Arguments.Scp106Events; diff --git a/LabApi/Events/Arguments/Scp106Events/Scp106ChangingVigorEventArgs.cs b/LabApi/Events/Arguments/Scp106Events/Scp106ChangingVigorEventArgs.cs index bc174da0..21be0ab2 100644 --- a/LabApi/Events/Arguments/Scp106Events/Scp106ChangingVigorEventArgs.cs +++ b/LabApi/Events/Arguments/Scp106Events/Scp106ChangingVigorEventArgs.cs @@ -1,6 +1,6 @@ -using System; using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using System; namespace LabApi.Events.Arguments.Scp106Events; diff --git a/LabApi/Events/Arguments/Scp106Events/Scp106TeleportedPlayerEvent.cs b/LabApi/Events/Arguments/Scp106Events/Scp106TeleportedPlayerEvent.cs index a8e2f397..2b8b567f 100644 --- a/LabApi/Events/Arguments/Scp106Events/Scp106TeleportedPlayerEvent.cs +++ b/LabApi/Events/Arguments/Scp106Events/Scp106TeleportedPlayerEvent.cs @@ -1,6 +1,6 @@ -using System; -using LabApi.Events.Arguments.Interfaces; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using System; namespace LabApi.Events.Arguments.Scp106Events; diff --git a/LabApi/Events/Arguments/Scp106Events/Scp106TeleportingPlayerEvent.cs b/LabApi/Events/Arguments/Scp106Events/Scp106TeleportingPlayerEvent.cs index 29de2333..cec4eb81 100644 --- a/LabApi/Events/Arguments/Scp106Events/Scp106TeleportingPlayerEvent.cs +++ b/LabApi/Events/Arguments/Scp106Events/Scp106TeleportingPlayerEvent.cs @@ -1,6 +1,6 @@ -using System; -using LabApi.Events.Arguments.Interfaces; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using System; namespace LabApi.Events.Arguments.Scp106Events; diff --git a/LabApi/Events/Arguments/Scp106Events/Scp106UsedHunterAtlasEventArgs.cs b/LabApi/Events/Arguments/Scp106Events/Scp106UsedHunterAtlasEventArgs.cs index 7fac8b7c..f1cef57c 100644 --- a/LabApi/Events/Arguments/Scp106Events/Scp106UsedHunterAtlasEventArgs.cs +++ b/LabApi/Events/Arguments/Scp106Events/Scp106UsedHunterAtlasEventArgs.cs @@ -1,6 +1,6 @@ -using System; using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using System; using UnityEngine; namespace LabApi.Events.Arguments.Scp106Events; diff --git a/LabApi/Events/Arguments/Scp106Events/Scp106UsingHunterAtlasEventArgs.cs b/LabApi/Events/Arguments/Scp106Events/Scp106UsingHunterAtlasEventArgs.cs index 294699da..9d9c934a 100644 --- a/LabApi/Events/Arguments/Scp106Events/Scp106UsingHunterAtlasEventArgs.cs +++ b/LabApi/Events/Arguments/Scp106Events/Scp106UsingHunterAtlasEventArgs.cs @@ -1,6 +1,6 @@ -using System; using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using System; using UnityEngine; namespace LabApi.Events.Arguments.Scp106Events; diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173BreakneckSpeedChangingEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173BreakneckSpeedChangingEventArgs.cs index 2d55a31d..6415b601 100644 --- a/LabApi/Events/Arguments/Scp173Events/Scp173BreakneckSpeedChangingEventArgs.cs +++ b/LabApi/Events/Arguments/Scp173Events/Scp173BreakneckSpeedChangingEventArgs.cs @@ -27,7 +27,7 @@ public Scp173BreakneckSpeedChangingEventArgs(ReferenceHub player, bool active) public bool Active { get; } /// <summary> - /// The SCP-173 player instance. + /// The SCP-173 player instance. /// </summary> public Player Player { get; } diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173PlayedSoundEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173PlayedSoundEventArgs.cs index a53571f7..93b88c5d 100644 --- a/LabApi/Events/Arguments/Scp173Events/Scp173PlayedSoundEventArgs.cs +++ b/LabApi/Events/Arguments/Scp173Events/Scp173PlayedSoundEventArgs.cs @@ -14,7 +14,7 @@ public class Scp173PlayedSoundEventArgs : EventArgs, IPlayerEvent /// The sound id that is being played. /// </summary> /// <param name="player">The SCP-173 player instance.</param> - /// <param name="soundId">The sound id that is being played.</param> + /// <param name="soundId">The sound id being played.</param> public Scp173PlayedSoundEventArgs(ReferenceHub player, Scp173AudioPlayer.Scp173SoundId soundId) { Player = Player.Get(player); @@ -30,5 +30,4 @@ public Scp173PlayedSoundEventArgs(ReferenceHub player, Scp173AudioPlayer.Scp173S /// The SCP-173 player instance. /// </summary> public Player Player { get; } - } \ No newline at end of file diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173PlayingSoundEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173PlayingSoundEventArgs.cs index 2d704082..07789f06 100644 --- a/LabApi/Events/Arguments/Scp173Events/Scp173PlayingSoundEventArgs.cs +++ b/LabApi/Events/Arguments/Scp173Events/Scp173PlayingSoundEventArgs.cs @@ -14,7 +14,7 @@ public class Scp173PlayingSoundEventArgs : EventArgs, IPlayerEvent, ICancellable /// The sound id that is going to be played. /// </summary> /// <param name="player">The SCP-173 player instance.</param> - /// <param name="soundId">The sound id that is going to be played.</param> + /// <param name="soundId">The sound id going to be played.</param> public Scp173PlayingSoundEventArgs(ReferenceHub player, Scp173AudioPlayer.Scp173SoundId soundId) { IsAllowed = true; diff --git a/LabApi/Events/Arguments/Scp3114Events/Scp3114DisguisedEventArgs.cs b/LabApi/Events/Arguments/Scp3114Events/Scp3114DisguisedEventArgs.cs index 969f98d7..2efb3651 100644 --- a/LabApi/Events/Arguments/Scp3114Events/Scp3114DisguisedEventArgs.cs +++ b/LabApi/Events/Arguments/Scp3114Events/Scp3114DisguisedEventArgs.cs @@ -13,7 +13,7 @@ public class Scp3114DisguisedEventArgs : EventArgs, IPlayerEvent, IRagdollEvent /// <summary> /// Initializes a new instance of the <see cref="Scp3114DisguisedEventArgs"/> class. /// </summary> - /// <param name="player">The player SCP who disguised./param> + /// <param name="player">The player SCP who disguised.</param> /// <param name="ragdoll">The ragdoll used for disguising purposes.</param> public Scp3114DisguisedEventArgs(ReferenceHub player, BasicRagdoll ragdoll) { diff --git a/LabApi/Events/Arguments/Scp3114Events/Scp3114DisguisingEventArgs.cs b/LabApi/Events/Arguments/Scp3114Events/Scp3114DisguisingEventArgs.cs index 148e13f6..d5f2e7a5 100644 --- a/LabApi/Events/Arguments/Scp3114Events/Scp3114DisguisingEventArgs.cs +++ b/LabApi/Events/Arguments/Scp3114Events/Scp3114DisguisingEventArgs.cs @@ -13,7 +13,7 @@ public class Scp3114DisguisingEventArgs : EventArgs, IPlayerEvent, IRagdollEvent /// <summary> /// Initializes a new instance of the <see cref="Scp3114DisguisedEventArgs"/> class. /// </summary> - /// <param name="player">The player SCP who is disguising./param> + /// <param name="player">The player SCP who is disguising.</param> /// <param name="ragdoll">The ragdoll used for disguising purposes.</param> public Scp3114DisguisingEventArgs(ReferenceHub player, BasicRagdoll ragdoll) { diff --git a/LabApi/Events/Arguments/Scp3114Events/Scp3114RevealedEventArgs.cs b/LabApi/Events/Arguments/Scp3114Events/Scp3114RevealedEventArgs.cs index f96a57ea..8c17004d 100644 --- a/LabApi/Events/Arguments/Scp3114Events/Scp3114RevealedEventArgs.cs +++ b/LabApi/Events/Arguments/Scp3114Events/Scp3114RevealedEventArgs.cs @@ -12,7 +12,7 @@ public class Scp3114RevealedEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance of the <see cref="Scp3114RevealedEventArgs"/> class. /// </summary> - /// <param name="player">The player SCP so is undisguised./param> + /// <param name="player">The player SCP so is undisguised.</param> /// <param name="forced">Bool whether the reveal is forced by timer running out or if it was player's request.</param> public Scp3114RevealedEventArgs(ReferenceHub player, bool forced) { diff --git a/LabApi/Events/Arguments/Scp3114Events/Scp3114RevealingEventArgs.cs b/LabApi/Events/Arguments/Scp3114Events/Scp3114RevealingEventArgs.cs index df7e4abb..9bba6944 100644 --- a/LabApi/Events/Arguments/Scp3114Events/Scp3114RevealingEventArgs.cs +++ b/LabApi/Events/Arguments/Scp3114Events/Scp3114RevealingEventArgs.cs @@ -12,7 +12,7 @@ public class Scp3114RevealingEventArgs : EventArgs, IPlayerEvent, ICancellableEv /// <summary> /// Initializes a new instance of the <see cref="Scp3114RevealingEventArgs"/> class. /// </summary> - /// <param name="player">The player SCP who is undisguising./param> + /// <param name="player">The player SCP who is undisguising.</param> /// <param name="forced">Bool whether the reveal is forced by timer running out or if it was player's request.</param> public Scp3114RevealingEventArgs(ReferenceHub player, bool forced) { diff --git a/LabApi/Events/Arguments/Scp3114Events/Scp3114StartedDanceEventArgs.cs b/LabApi/Events/Arguments/Scp3114Events/Scp3114StartedDanceEventArgs.cs index 515a1995..431a4784 100644 --- a/LabApi/Events/Arguments/Scp3114Events/Scp3114StartedDanceEventArgs.cs +++ b/LabApi/Events/Arguments/Scp3114Events/Scp3114StartedDanceEventArgs.cs @@ -21,7 +21,7 @@ public Scp3114StartedDanceEventArgs(ReferenceHub player, byte danceId) } /// <summary> - /// Gets or sets the index of the animation to play. + /// Gets or sets the index of the animation to play. /// </summary> public byte DanceId { get; } diff --git a/LabApi/Events/Arguments/Scp3114Events/Scp3114StartingDanceEventArgs.cs b/LabApi/Events/Arguments/Scp3114Events/Scp3114StartingDanceEventArgs.cs index a9a69170..9f3a8099 100644 --- a/LabApi/Events/Arguments/Scp3114Events/Scp3114StartingDanceEventArgs.cs +++ b/LabApi/Events/Arguments/Scp3114Events/Scp3114StartingDanceEventArgs.cs @@ -25,8 +25,8 @@ public Scp3114StartingDanceEventArgs(ReferenceHub player, byte danceId) public Player Player { get; } /// <summary> - /// Gets or sets the index of the animation to play. - /// Currently there are 7 dance variants in game. + /// Gets or sets the index of the animation to play. + /// Currently there are 7 dance variants in game. /// <para>Any value above max length will be moved to equal index via modulo (%) operator.</para> /// </summary> public byte DanceId { get; set; } diff --git a/LabApi/Events/Arguments/Scp914Events/Scp914ProcessedInventoryItemEventArgs.cs b/LabApi/Events/Arguments/Scp914Events/Scp914ProcessedInventoryItemEventArgs.cs index ceddecfe..c89fce77 100644 --- a/LabApi/Events/Arguments/Scp914Events/Scp914ProcessedInventoryItemEventArgs.cs +++ b/LabApi/Events/Arguments/Scp914Events/Scp914ProcessedInventoryItemEventArgs.cs @@ -1,8 +1,8 @@ +using InventorySystem.Items; using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using Scp914; using System; -using InventorySystem.Items; namespace LabApi.Events.Arguments.Scp914Events; diff --git a/LabApi/Events/Arguments/Scp914Events/Scp914ProcessedPickupEventArgs.cs b/LabApi/Events/Arguments/Scp914Events/Scp914ProcessedPickupEventArgs.cs index 441cc636..d8cd03d1 100644 --- a/LabApi/Events/Arguments/Scp914Events/Scp914ProcessedPickupEventArgs.cs +++ b/LabApi/Events/Arguments/Scp914Events/Scp914ProcessedPickupEventArgs.cs @@ -1,8 +1,8 @@ -using System; using InventorySystem.Items.Pickups; using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using Scp914; +using System; using UnityEngine; namespace LabApi.Events.Arguments.Scp914Events; diff --git a/LabApi/Events/Arguments/Scp914Events/Scp914ProcessingInventoryItemEventArgs.cs b/LabApi/Events/Arguments/Scp914Events/Scp914ProcessingInventoryItemEventArgs.cs index 6e3dd7fd..a3a42a2f 100644 --- a/LabApi/Events/Arguments/Scp914Events/Scp914ProcessingInventoryItemEventArgs.cs +++ b/LabApi/Events/Arguments/Scp914Events/Scp914ProcessingInventoryItemEventArgs.cs @@ -1,7 +1,7 @@ +using InventorySystem.Items; using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using Scp914; -using InventorySystem.Items; using System; namespace LabApi.Events.Arguments.Scp914Events; diff --git a/LabApi/Events/Arguments/Scp914Events/Scp914ProcessingPickupEventArgs.cs b/LabApi/Events/Arguments/Scp914Events/Scp914ProcessingPickupEventArgs.cs index 05cdf2b1..0939f9d5 100644 --- a/LabApi/Events/Arguments/Scp914Events/Scp914ProcessingPickupEventArgs.cs +++ b/LabApi/Events/Arguments/Scp914Events/Scp914ProcessingPickupEventArgs.cs @@ -1,9 +1,9 @@ -using System; +using InventorySystem.Items.Pickups; using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using Scp914; +using System; using UnityEngine; -using InventorySystem.Items.Pickups; namespace LabApi.Events.Arguments.Scp914Events; diff --git a/LabApi/Events/Arguments/ServerEvents/CassieAnnouncedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/CassieAnnouncedEventArgs.cs index 2aff367f..b6f3dcf9 100644 --- a/LabApi/Events/Arguments/ServerEvents/CassieAnnouncedEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/CassieAnnouncedEventArgs.cs @@ -13,7 +13,7 @@ public class CassieAnnouncedEventArgs : EventArgs /// <param name="words">The sentence C.A.S.S.I.E. is supposed to say.</param> /// <param name="makeHold">For most cases you wanna keep it true. Sets a minimal 3-second moment of silence before the announcement.</param> /// <param name="makeNoise">The background noises before playing.</param> - /// <param name="customAnnouncement">If thats custom announcement? Custom announcements show subtitles</param> + /// <param name="customAnnouncement">If thats custom announcement? Custom announcements show subtitles.</param> /// <param name="customSubtitles">Custom subtitles text.</param> public CassieAnnouncedEventArgs(string words, bool makeHold, bool makeNoise, bool customAnnouncement, string customSubtitles) { @@ -25,7 +25,7 @@ public CassieAnnouncedEventArgs(string words, bool makeHold, bool makeNoise, boo } /// <summary> - /// Gets sentece which C.A.S.S.I.E. said. + /// Gets sentence which C.A.S.S.I.E. said. /// </summary> public string Words { get; } diff --git a/LabApi/Events/Arguments/ServerEvents/CassieAnnouncingEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/CassieAnnouncingEventArgs.cs index 0ceb04ad..aac4eda1 100644 --- a/LabApi/Events/Arguments/ServerEvents/CassieAnnouncingEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/CassieAnnouncingEventArgs.cs @@ -14,7 +14,7 @@ public class CassieAnnouncingEventArgs : EventArgs, ICancellableEvent /// <param name="words">The sentence C.A.S.S.I.E. is supposed to say.</param> /// <param name="makeHold">For most cases you wanna keep it true. Sets a minimal 3-second moment of silence before the announcement.</param> /// <param name="makeNoise">The background noises before playing.</param> - /// <param name="customAnnouncement">If thats custom announcement? Custom announcements show subtitles</param> + /// <param name="customAnnouncement">If thats custom announcement? Custom announcements show subtitles.</param> /// <param name="customSubtitles">Custom subtitles text to appear instead of original text.</param> public CassieAnnouncingEventArgs(string words, bool makeHold, bool makeNoise, bool customAnnouncement, string customSubtitles) { @@ -27,7 +27,7 @@ public CassieAnnouncingEventArgs(string words, bool makeHold, bool makeNoise, bo } /// <summary> - /// Gets or sets sentece which C.A.S.S.I.E. will say. + /// Gets or sets sentence which C.A.S.S.I.E. will say. /// </summary> public string Words { get; set; } diff --git a/LabApi/Events/Arguments/ServerEvents/CassieQueuingScpTerminationEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/CassieQueuingScpTerminationEventArgs.cs index 88afe799..7ec3767a 100644 --- a/LabApi/Events/Arguments/ServerEvents/CassieQueuingScpTerminationEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/CassieQueuingScpTerminationEventArgs.cs @@ -40,11 +40,11 @@ public CassieQueuingScpTerminationEventArgs(ReferenceHub player, string announce /// <summary> /// Gets or sets the subtitle parts of the message. /// </summary> - public SubtitlePart[] SubtitleParts { get; set; } + public SubtitlePart[] SubtitleParts { get; set; } /// <inheritdoc /> public bool IsAllowed { get; set; } - + /// <summary> /// The Damage Handler responsible for the SCP Termination. /// </summary> diff --git a/LabApi/Events/Arguments/ServerEvents/CommandExecutedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/CommandExecutedEventArgs.cs index c14e0a37..af6d7f31 100644 --- a/LabApi/Events/Arguments/ServerEvents/CommandExecutedEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/CommandExecutedEventArgs.cs @@ -1,7 +1,7 @@ using CommandSystem; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Enums; using System; -using LabApi.Events.Arguments.Interfaces; namespace LabApi.Events.Arguments.ServerEvents; @@ -18,7 +18,7 @@ public class CommandExecutedEventArgs : EventArgs, ICommandSenderEvent /// <param name="command">The command.</param> /// <param name="arguments">The arguments of the command.</param> /// <param name="successful">Whether the command was executed successfully.</param> - /// <param name="response">The response of the command</param> + /// <param name="response">The response of the command.</param> public CommandExecutedEventArgs(CommandSender? sender, CommandType commandType, ICommand command, ArraySegment<string> arguments, bool successful, string response) { Sender = sender; diff --git a/LabApi/Events/Arguments/ServerEvents/ExplosionSpawnedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/ExplosionSpawnedEventArgs.cs index fe56ed15..260bce39 100644 --- a/LabApi/Events/Arguments/ServerEvents/ExplosionSpawnedEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/ExplosionSpawnedEventArgs.cs @@ -4,53 +4,52 @@ using System; using UnityEngine; -namespace LabApi.Events.Arguments.ServerEvents +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.ExplosionSpawned"/> event. +/// </summary> +public class ExplosionSpawnedEventArgs : EventArgs, IPlayerEvent { /// <summary> - /// Represents the arguments for the <see cref="Handlers.ServerEvents.ExplosionSpawned"/> event. + /// Initializes a new instance of the <see cref="ExplosionSpawnedEventArgs"/> class. /// </summary> - public class ExplosionSpawnedEventArgs : EventArgs, IPlayerEvent + /// <param name="player">The player which caused this explosion.</param> + /// <param name="position">The position of explosion.</param> + /// <param name="settingsReference">The projectile which caused explosion.</param> + /// <param name="explosionType">The type of this explosion.</param> + /// <param name="destroyDoors">Whether the explosion was allowed to destroy doors.</param> + public ExplosionSpawnedEventArgs(ReferenceHub? player, Vector3 position, ExplosionGrenade settingsReference, ExplosionType explosionType, bool destroyDoors) { - /// <summary> - /// Initializes a new instance of the <see cref="ExplosionSpawnedEventArgs"/> class. - /// </summary> - /// <param name="player">The player which caused this explosion.</param> - /// <param name="position">The position of explosion.</param> - /// <param name="settingsReference">The projectile which caused explosion.</param> - /// <param name="explosionType">The type of this explosion.</param> - /// <param name="destroyDoors">Whether the explosion was allowed to destroy doors.</param> - public ExplosionSpawnedEventArgs(ReferenceHub? player, Vector3 position, ExplosionGrenade settingsReference, ExplosionType explosionType, bool destroyDoors) - { - Player = Player.Get(player); - Position = position; - Settings = settingsReference; - ExplosionType = explosionType; - DestroyDoors = destroyDoors; - } + Player = Player.Get(player); + Position = position; + Settings = settingsReference; + ExplosionType = explosionType; + DestroyDoors = destroyDoors; + } - /// <summary> - /// Gets the player which caused this explosion. - /// </summary> - public Player? Player { get; } + /// <summary> + /// Gets the player which caused this explosion. + /// </summary> + public Player? Player { get; } - /// <summary> - /// Gets the position of explosion. - /// </summary> - public Vector3 Position { get; } + /// <summary> + /// Gets the position of explosion. + /// </summary> + public Vector3 Position { get; } - /// <summary> - /// Gets the projectile which will cause explosion. - /// </summary> - public ExplosionGrenade Settings { get; } + /// <summary> + /// Gets the projectile which will cause explosion. + /// </summary> + public ExplosionGrenade Settings { get; } - /// <summary> - /// Gets the type of this explosion. - /// </summary> - public ExplosionType ExplosionType { get; } + /// <summary> + /// Gets the type of this explosion. + /// </summary> + public ExplosionType ExplosionType { get; } - /// <summary> - /// Gets whether the explosion should destroy doors. - /// </summary> - public bool DestroyDoors { get; } - } + /// <summary> + /// Gets whether the explosion should destroy doors. + /// </summary> + public bool DestroyDoors { get; } } diff --git a/LabApi/Events/Arguments/ServerEvents/ExplosionSpawningEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/ExplosionSpawningEventArgs.cs index 29638552..cf05158c 100644 --- a/LabApi/Events/Arguments/ServerEvents/ExplosionSpawningEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/ExplosionSpawningEventArgs.cs @@ -4,58 +4,57 @@ using System; using UnityEngine; -namespace LabApi.Events.Arguments.ServerEvents +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.ExplosionSpawning"/> event. +/// </summary> +public class ExplosionSpawningEventArgs : EventArgs, IPlayerEvent, ICancellableEvent { /// <summary> - /// Represents the arguments for the <see cref="Handlers.ServerEvents.ExplosionSpawning"/> event. + /// Initializes a new instance of the <see cref="ExplosionSpawningEventArgs"/> class. /// </summary> - public class ExplosionSpawningEventArgs : EventArgs, IPlayerEvent, ICancellableEvent + /// <param name="player">The player which caused this explosion.</param> + /// <param name="position">The position of explosion.</param> + /// <param name="settingsReference">The projectile which will cause the explosion.</param> + /// <param name="explosionType">The type of this explosion.</param> + /// <param name="destroyDoors">Whether the explosion should destroy doors.</param> + public ExplosionSpawningEventArgs(ReferenceHub? player, Vector3 position, ExplosionGrenade settingsReference, ExplosionType explosionType, bool destroyDoors) { - /// <summary> - /// Initializes a new instance of the <see cref="ExplosionSpawningEventArgs"/> class. - /// </summary> - /// <param name="player">The player which caused this explosion.</param> - /// <param name="position">The position of explosion.</param> - /// <param name="settingsReference">The projectile which will cause the explosion.</param> - /// <param name="explosionType">The type of this explosion.</param> - /// <param name="destroyDoors">Whether the explosion should destroy doors.</param> - public ExplosionSpawningEventArgs(ReferenceHub? player, Vector3 position, ExplosionGrenade settingsReference, ExplosionType explosionType, bool destroyDoors) - { - Player = Player.Get(player); - Position = position; - Settings = settingsReference; - ExplosionType = explosionType; - DestroyDoors = destroyDoors; - - IsAllowed = true; - } - - /// <summary> - /// Gets or sets the player which caused this explosion. - /// </summary> - public Player? Player { get; set; } - - /// <summary> - /// Gets or sets the position of explosion. - /// </summary> - public Vector3 Position { get; set; } - - /// <summary> - /// Gets or sets the projectile which will cause explosion. - /// </summary> - public ExplosionGrenade Settings { get; set; } - - /// <summary> - /// Gets or sets the type of this explosion. - /// </summary> - public ExplosionType ExplosionType { get; set; } - - /// <summary> - /// Gets or sets whether the explosion should destroy doors. - /// </summary> - public bool DestroyDoors { get; set; } - - /// <inheritdoc/> - public bool IsAllowed { get; set; } + Player = Player.Get(player); + Position = position; + Settings = settingsReference; + ExplosionType = explosionType; + DestroyDoors = destroyDoors; + + IsAllowed = true; } + + /// <summary> + /// Gets or sets the player which caused this explosion. + /// </summary> + public Player? Player { get; set; } + + /// <summary> + /// Gets or sets the position of explosion. + /// </summary> + public Vector3 Position { get; set; } + + /// <summary> + /// Gets or sets the projectile which will cause explosion. + /// </summary> + public ExplosionGrenade Settings { get; set; } + + /// <summary> + /// Gets or sets the type of this explosion. + /// </summary> + public ExplosionType ExplosionType { get; set; } + + /// <summary> + /// Gets or sets whether the explosion should destroy doors. + /// </summary> + public bool DestroyDoors { get; set; } + + /// <inheritdoc/> + public bool IsAllowed { get; set; } } diff --git a/LabApi/Events/Arguments/ServerEvents/ItemSpawningEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/ItemSpawningEventArgs.cs index a1bd6009..92b8368e 100644 --- a/LabApi/Events/Arguments/ServerEvents/ItemSpawningEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/ItemSpawningEventArgs.cs @@ -11,7 +11,7 @@ public class ItemSpawningEventArgs : EventArgs, ICancellableEvent /// <summary> /// Initializes a new instance of the <see cref="ItemSpawningEventArgs"/> class. /// </summary> - /// <param name="type">The type of item which will spawn on map</param> + /// <param name="type">The type of item which will spawn on map.</param> public ItemSpawningEventArgs(ItemType type) { IsAllowed = true; diff --git a/LabApi/Events/Arguments/ServerEvents/RoundEndingConditionsCheckEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/RoundEndingConditionsCheckEventArgs.cs index 4ddd004b..afc3f753 100644 --- a/LabApi/Events/Arguments/ServerEvents/RoundEndingConditionsCheckEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/RoundEndingConditionsCheckEventArgs.cs @@ -10,7 +10,7 @@ public class RoundEndingConditionsCheckEventArgs : EventArgs /// <summary> /// Initializes a new instance of the <see cref="RoundEndingConditionsCheckEventArgs"/> class. /// </summary> - /// <param name="canEnd">Whether the round end conditions are met</param> + /// <param name="canEnd">Whether the round end conditions are met.</param> public RoundEndingConditionsCheckEventArgs(bool canEnd) { CanEnd = canEnd; diff --git a/LabApi/Events/Arguments/ServerEvents/SentAdminChatEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/SentAdminChatEventArgs.cs index b9cd0e43..d6a79331 100644 --- a/LabApi/Events/Arguments/ServerEvents/SentAdminChatEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/SentAdminChatEventArgs.cs @@ -1,5 +1,5 @@ -using System; using LabApi.Events.Arguments.Interfaces; +using System; namespace LabApi.Events.Arguments.ServerEvents; diff --git a/LabApi/Events/Arguments/ServerEvents/WaveRespawnedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/WaveRespawnedEventArgs.cs index 8b930c55..c24cce1a 100644 --- a/LabApi/Events/Arguments/ServerEvents/WaveRespawnedEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/WaveRespawnedEventArgs.cs @@ -18,7 +18,7 @@ public class WaveRespawnedEventArgs : EventArgs public WaveRespawnedEventArgs(SpawnableWaveBase wave, List<Player> players) { Players = players; - Wave = RespawnWaves.Get(wave); + Wave = RespawnWaves.Get(wave)!; } /// <summary> diff --git a/LabApi/Events/Arguments/ServerEvents/WaveRespawningEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/WaveRespawningEventArgs.cs index 5a0f8683..d648a0b3 100644 --- a/LabApi/Events/Arguments/ServerEvents/WaveRespawningEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/WaveRespawningEventArgs.cs @@ -21,11 +21,13 @@ public class WaveRespawningEventArgs : EventArgs, ICancellableEvent public WaveRespawningEventArgs(SpawnableWaveBase wave, Dictionary<ReferenceHub, RoleTypeId> roles) { IsAllowed = true; - Wave = RespawnWaves.Get(wave); + Wave = RespawnWaves.Get(wave)!; Roles = DictionaryPool<Player, RoleTypeId>.Get(); foreach (KeyValuePair<ReferenceHub, RoleTypeId> kvp in roles) + { Roles.Add(Player.Get(kvp.Key), kvp.Value); + } } /// <inheritdoc /> diff --git a/LabApi/Events/Arguments/ServerEvents/WaveTeamSelectedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/WaveTeamSelectedEventArgs.cs index 3a833c6e..e040abc8 100644 --- a/LabApi/Events/Arguments/ServerEvents/WaveTeamSelectedEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/WaveTeamSelectedEventArgs.cs @@ -15,11 +15,11 @@ public class WaveTeamSelectedEventArgs : EventArgs /// <param name="wave">The wave that was selected.</param> public WaveTeamSelectedEventArgs(SpawnableWaveBase wave) { - Wave = RespawnWaves.Get(wave); + Wave = RespawnWaves.Get(wave)!; } /// <summary> - /// Gets the spawnable wave. See <see cref="SpawnableWaveBase"/> and its subclasses for more info. + /// Gets the spawnable wave. See <see cref="SpawnableWaveBase"/> and its subclasses for more info. /// </summary> public RespawnWave Wave { get; } } \ No newline at end of file diff --git a/LabApi/Events/Arguments/ServerEvents/WaveTeamSelectingEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/WaveTeamSelectingEventArgs.cs index d3ba16e1..e3cc02ae 100644 --- a/LabApi/Events/Arguments/ServerEvents/WaveTeamSelectingEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/WaveTeamSelectingEventArgs.cs @@ -21,7 +21,7 @@ public WaveTeamSelectingEventArgs(SpawnableWaveBase wave) } /// <summary> - /// Gets or sets the spawnable wave. See <see cref="SpawnableWaveBase"/> and its subclasses.<br/> + /// Gets or sets the spawnable wave. See <see cref="SpawnableWaveBase"/> and its subclasses.<br/> /// Use the <see cref="WaveManager.Waves"/> to set it to a different value. /// </summary> public SpawnableWaveBase Wave { get; set; } From 3a8f851c89d83a7471c9d4912d2c5b50303e67ff Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:39:36 +0930 Subject: [PATCH 068/215] updated handlers --- .../CustomHandlers/CustomEventHandlers.cs | 2 +- .../CustomHandlers/CustomHandlersManager.cs | 8 ++++++++ LabApi/Events/EventManager.cs | 18 +++++++++++++++--- .../Handlers/PlayerEvents.EventHandlers.cs | 5 ++--- .../Handlers/Scp0492Events.EventHandlers.cs | 6 +++--- .../Handlers/ServerEvents.EventHandlers.cs | 2 +- ...tArgs.cs => LabEventHandler{TEventArgs}.cs} | 1 + 7 files changed, 31 insertions(+), 11 deletions(-) rename LabApi/Events/{LabEventHandlerTEventArgs.cs => LabEventHandler{TEventArgs}.cs} (88%) diff --git a/LabApi/Events/CustomHandlers/CustomEventHandlers.cs b/LabApi/Events/CustomHandlers/CustomEventHandlers.cs index 796c2682..c993a346 100644 --- a/LabApi/Events/CustomHandlers/CustomEventHandlers.cs +++ b/LabApi/Events/CustomHandlers/CustomEventHandlers.cs @@ -12,5 +12,5 @@ public abstract partial class CustomEventsHandler /// <summary> /// Internal dictionary to store the registered events and their delegates. /// </summary> - internal readonly Dictionary<EventInfo, Delegate> InternalEvents = new (); + internal Dictionary<EventInfo, Delegate> InternalEvents { get; } = []; } \ No newline at end of file diff --git a/LabApi/Events/CustomHandlers/CustomHandlersManager.cs b/LabApi/Events/CustomHandlers/CustomHandlersManager.cs index ea493357..4b28c80e 100644 --- a/LabApi/Events/CustomHandlers/CustomHandlersManager.cs +++ b/LabApi/Events/CustomHandlers/CustomHandlersManager.cs @@ -46,6 +46,12 @@ public static void UnregisterEventsHandler<T>(T handler) /// <summary> /// Checks if the event is overriden and subscribes the handler to the event if it is. /// </summary> + /// <param name="handler">The custom event handler instance.</param> + /// <param name="handlerType">The <see cref="Type"/> of the handler instance.</param> + /// <param name="methodDelegate">The <see langword="nameof"/> of the <see cref="CustomEventsHandler"/> event method.</param> + /// <param name="eventType">The <see cref="Type"/> class of the handler.</param> + /// <param name="eventName">The <see langword="nameof"/> the event in the handler.</param> + /// <typeparam name="T">The custom event handler type.</typeparam> public static void CheckEvent<T>(T handler, Type handlerType, string methodDelegate, Type eventType, string eventName) where T : CustomEventsHandler { @@ -54,7 +60,9 @@ public static void CheckEvent<T>(T handler, Type handlerType, string methodDeleg // If the method is null or not an override, we return. if (method == null || !IsOverride(method)) + { return; + } // We get the event from the event type. EventInfo eventInfo = eventType.GetEvent(eventName); diff --git a/LabApi/Events/EventManager.cs b/LabApi/Events/EventManager.cs index 85876068..17e15c50 100644 --- a/LabApi/Events/EventManager.cs +++ b/LabApi/Events/EventManager.cs @@ -21,7 +21,9 @@ public static void InvokeEvent(this LabEventHandler? eventHandler) { // We check if the event handler is null if (eventHandler is null) + { return; + } #if DEBUG // In DEBUG mode we add some useful logs about the event. @@ -35,7 +37,9 @@ public static void InvokeEvent(this LabEventHandler? eventHandler) { // We invoke the subscriber as a lab event handler. if (sub is LabEventHandler labEventHandler) + { labEventHandler.Invoke(); + } } catch (Exception e) { @@ -55,7 +59,9 @@ public static void InvokeEvent<TEventArgs>(this LabEventHandler<TEventArgs>? eve { // We check if the event handler is null if (eventHandler is null) + { return; + } #if DEBUG // In DEBUG mode we add some useful logs about the event. @@ -69,7 +75,9 @@ public static void InvokeEvent<TEventArgs>(this LabEventHandler<TEventArgs>? eve { // We invoke the subscriber as a lab event handler. if (sub is LabEventHandler<TEventArgs> labEventHandler) + { labEventHandler.Invoke(args); + } } catch (Exception e) { @@ -105,7 +113,9 @@ public static string FormatToString<TEventArgs>(this LabEventHandler<TEventArgs> // We iterate through all the properties of the EventArgs and append them to the StringBuilder. PropertyInfo[] properties = typeof(TEventArgs).GetProperties(); if (properties.Length > 0) + { stringBuilder.Append("\n"); + } foreach (PropertyInfo property in properties) { @@ -133,12 +143,14 @@ public static string FormatToString<TEventArgs>(this LabEventHandler<TEventArgs> /// </summary> /// <param name="eventHandler">The <see cref="LabEventHandler"/> that caused the error.</param> /// <param name="exception">The <see cref="Exception"/> that occurred.</param> - /// <returns></returns> + /// <returns>The formated error message.</returns> public static string FormatErrorMessage(Delegate eventHandler, Exception exception) { if (eventHandler.Target == null) // Static methods - return $"'{exception.GetType().Name}' occured while invoking '{eventHandler.Method.Name}' on '{eventHandler.Method.DeclaringType}': '{exception.Message}', stack trace:\n{exception.StackTrace}"; + { + return $"'{exception.GetType().Name}' occurred while invoking '{eventHandler.Method.Name}' on '{eventHandler.Method.DeclaringType}': '{exception.Message}', stack trace:\n{exception.StackTrace}"; + } - return $"'{exception.GetType().Name}' occured while invoking '{eventHandler.Method.Name}' on '{eventHandler.Target.GetType().FullName}': '{exception.Message}', stack trace:\n{exception.StackTrace}"; + return $"'{exception.GetType().Name}' occurred while invoking '{eventHandler.Method.Name}' on '{eventHandler.Target.GetType().FullName}': '{exception.Message}', stack trace:\n{exception.StackTrace}"; } } \ No newline at end of file diff --git a/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs b/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs index e5ee2733..3c68f6b2 100644 --- a/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs +++ b/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs @@ -1,5 +1,4 @@ using LabApi.Events.Arguments.PlayerEvents; -using MapGeneration; namespace LabApi.Events.Handlers; @@ -50,7 +49,7 @@ public static partial class PlayerEvents /// </summary> public static event LabEventHandler<PlayerUsedIntercomEventArgs>? UsedIntercom; - #endregion + #endregion #region Moderation @@ -458,7 +457,7 @@ public static partial class PlayerEvents ///// <summary> ///// Gets called when the player is aiming the weapon. ///// </summary> - //public static event LabEventHandler<PlayerAimingWeaponEventArgs>? AimingWeapon; + // public static event LabEventHandler<PlayerAimingWeaponEventArgs>? AimingWeapon; /// <summary> /// Gets called when the player aimed the weapon. diff --git a/LabApi/Events/Handlers/Scp0492Events.EventHandlers.cs b/LabApi/Events/Handlers/Scp0492Events.EventHandlers.cs index 9ada9a92..cfd1e490 100644 --- a/LabApi/Events/Handlers/Scp0492Events.EventHandlers.cs +++ b/LabApi/Events/Handlers/Scp0492Events.EventHandlers.cs @@ -11,17 +11,17 @@ public static partial class Scp0492Events /// Gets called when SCP-049-2 is starting to consume a corpse. /// </summary> public static event LabEventHandler<Scp0492StartingConsumingCorpseEventArgs>? StartingConsumingCorpse; - + /// <summary> /// Gets called when SCP-049-2 started to consume a corpse. /// </summary> public static event LabEventHandler<Scp0492StartedConsumingCorpseEventArgs>? StartedConsumingCorpse; - + /// <summary> /// Gets called when SCP-049-2 is consuming a corpse. /// </summary> public static event LabEventHandler<Scp0492ConsumingCorpseEventArgs>? ConsumingCorpse; - + /// <summary> /// Gets called when SCP-049-2 consumed a corpse. /// </summary> diff --git a/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs b/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs index f9b24570..4ffb37d9 100644 --- a/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs +++ b/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs @@ -118,7 +118,7 @@ public static partial class ServerEvents public static event LabEventHandler<LczDecontaminationAnnouncedEventArgs>? LczDecontaminationAnnounced; /// <summary> - /// Gets called when the server starts LCZ decontamiantion. + /// Gets called when the server starts LCZ decontamination. /// </summary> public static event LabEventHandler<LczDecontaminationStartingEventArgs>? LczDecontaminationStarting; diff --git a/LabApi/Events/LabEventHandlerTEventArgs.cs b/LabApi/Events/LabEventHandler{TEventArgs}.cs similarity index 88% rename from LabApi/Events/LabEventHandlerTEventArgs.cs rename to LabApi/Events/LabEventHandler{TEventArgs}.cs index 8690f875..9452b0fa 100644 --- a/LabApi/Events/LabEventHandlerTEventArgs.cs +++ b/LabApi/Events/LabEventHandler{TEventArgs}.cs @@ -6,6 +6,7 @@ namespace LabApi.Events; /// LabAPI's event handler with a <see cref="EventArgs"/> parameter. /// Called when an event is with the specified <see cref="EventArgs"/> triggered . /// </summary> +/// <param name="ev">The event arg instance.</param> /// <typeparam name="TEventArgs">The type of the <see cref="EventArgs"/> of the event.</typeparam> public delegate void LabEventHandler<in TEventArgs>(TEventArgs ev) where TEventArgs : EventArgs; \ No newline at end of file From bcc8d9e9f622fd803eba0af88eba360515aa0612 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:39:53 +0930 Subject: [PATCH 069/215] updated project --- LabApi.sln | 7 ++++++- LabApi/LabApi.csproj | 11 +++++++++++ LabApi/stylecop.json | 14 ++++++++++++++ StyleCopAnalyzers.ruleset | 13 +++++++++++++ 4 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 LabApi/stylecop.json create mode 100644 StyleCopAnalyzers.ruleset diff --git a/LabApi.sln b/LabApi.sln index 264f4e50..208d8a88 100644 --- a/LabApi.sln +++ b/LabApi.sln @@ -25,7 +25,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Commands", "Commands", "{3B EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommandsPlugin", "LabApi.Examples\Commands\CommandsPlugin\CommandsPlugin.csproj", "{DFDB27D3-70C9-44A6-B2D3-6D8D0716D6FC}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommandsPlugin2", "LabApi.Examples\Commands\CommandsPlugin2\CommandsPlugin2.csproj", "{295205EA-B4A2-42CF-8B91-7F9BF6909694}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommandsPlugin2", "LabApi.Examples\Commands\CommandsPlugin2\CommandsPlugin2.csproj", "{295205EA-B4A2-42CF-8B91-7F9BF6909694}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{9FDD2A60-56E4-4E77-9E87-B62F3BF06CC8}" + ProjectSection(SolutionItems) = preProject + StyleCopAnalyzers.ruleset = StyleCopAnalyzers.ruleset + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/LabApi/LabApi.csproj b/LabApi/LabApi.csproj index 36b605e0..f08b75ec 100644 --- a/LabApi/LabApi.csproj +++ b/LabApi/LabApi.csproj @@ -29,9 +29,20 @@ <PackageLicenseFile>LICENSE</PackageLicenseFile> <DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences> + + <CodeAnalysisRuleSet>$(SolutionDir)StyleCopAnalyzers.ruleset</CodeAnalysisRuleSet> </PropertyGroup> + + <ItemGroup> + <None Remove="stylecop.json" /> + <AdditionalFiles Include="stylecop.json" /> + </ItemGroup> <ItemGroup> + <PackageReference Include="StyleCop.Analyzers.Unstable" Version="1.2.0.556"> + <PrivateAssets>all</PrivateAssets> + <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> + </PackageReference> <PackageReference Include="YamlDotNet" Version="11.0.1" /> </ItemGroup> diff --git a/LabApi/stylecop.json b/LabApi/stylecop.json new file mode 100644 index 00000000..c076f363 --- /dev/null +++ b/LabApi/stylecop.json @@ -0,0 +1,14 @@ +{ + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "orderingRules": { + "elementOrder": [ "constant", "static", "kind", "accessibility" ], + "systemUsingDirectivesFirst": false, + "usingDirectivesPlacement": "outsideNamespace", + "blankLinesBetweenUsingGroups": "omit" + }, + "maintainabilityRules": { + "topLevelTypes": ["class", "interface", "delegate", "enum", "struct"] + } + } +} diff --git a/StyleCopAnalyzers.ruleset b/StyleCopAnalyzers.ruleset new file mode 100644 index 00000000..c1e8677f --- /dev/null +++ b/StyleCopAnalyzers.ruleset @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<RuleSet Name="New Rule Set" Description=" " ToolsVersion="17.0"> + <Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers"> + <Rule Id="SA1101" Action="None" /> + <Rule Id="SA1124" Action="None" /> + <Rule Id="SA1309" Action="None" /> + <Rule Id="SA1623" Action="None" /> + <Rule Id="SA1633" Action="None" /> + <Rule Id="SA1642" Action="None" /> + <Rule Id="SX1101" Action="Warning" /> + <Rule Id="SX1309" Action="Warning" /> + </Rules> +</RuleSet> \ No newline at end of file From 39711f181c3c0df8b28ee7b7cad052c272f21386 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:40:17 +0930 Subject: [PATCH 070/215] audio --- LabApi/Features/Audio/AudioTransmitter.cs | 128 ++++++++++++---------- 1 file changed, 70 insertions(+), 58 deletions(-) diff --git a/LabApi/Features/Audio/AudioTransmitter.cs b/LabApi/Features/Audio/AudioTransmitter.cs index 4dbad2ea..dfb516ca 100644 --- a/LabApi/Features/Audio/AudioTransmitter.cs +++ b/LabApi/Features/Audio/AudioTransmitter.cs @@ -17,19 +17,11 @@ namespace LabApi.Features.Audio; /// Encodes and sends audio to certain players which plays on speakers with the specified controller id. /// </summary> /// <remarks> -/// Its possible to create multiple transmitters with the same controller id, but you must filter the receiving players such that no one player receives audio from multiple transmitters. +/// Its possible to create multiple transmitters with the same controller id, but you must filter the receiving players such that no one player receives audio from multiple transmitters. /// This is done to allow you to send different audio to certain players using the same speakers. /// </remarks> public class AudioTransmitter { - private const float GainCorrectionFactor = 1.41421356237f; - - private static readonly float[] EmptyData = new float[FrameSize]; - - private static readonly float[] TempSampleData = new float[FrameSize]; - - private static readonly byte[] TempEncodedData = new byte[MaxEncodedSize]; - /// <summary> /// The sample rate in samples per second. /// </summary> @@ -50,16 +42,39 @@ public class AudioTransmitter /// </summary> public const int MaxEncodedSize = VoiceChatSettings.MaxEncodedSize; + private const float GainCorrectionFactor = 1.41421356237f; + + private static readonly float[] EmptyData = new float[FrameSize]; + private static readonly float[] TempSampleData = new float[FrameSize]; + private static readonly byte[] TempEncodedData = new byte[MaxEncodedSize]; + + private readonly OpusEncoder _opusEncoder; + private CoroutineHandle _update; + private double _targetTime = 0.0; + private bool _breakCurrent = false; + private float[] _currentSamples = EmptyData; + + /// <summary> + /// Creates a new audio transmitter for the specified controller. + /// </summary> + /// <param name="controllerId">The controller specified by its Id.</param> + /// <param name="type">What kind of audio the encoder should optimise's for.</param> + public AudioTransmitter(byte controllerId, OpusApplicationType type = OpusApplicationType.Audio) + { + ControllerId = controllerId; + _opusEncoder = new OpusEncoder(type); + } + /// <summary> /// The <see cref="SpeakerToy.ControllerId"/> of the speakers to play the audio on. /// </summary> - public readonly byte ControllerId; + public byte ControllerId { get; } /// <summary> /// The queued audio clips. /// Includes the current playing clip. /// </summary> - public readonly Queue<float[]> AudioClipSamples = []; + public Queue<float[]> AudioClipSamples { get; } = []; /// <summary> /// The predicate for determining which players receive audio. @@ -67,56 +82,35 @@ public class AudioTransmitter /// <remarks> /// If <see langword="null"/>, all authenticated players will receive audio packets. /// </remarks> - public Func<Player, bool>? ValidPlayers = null; + public Func<Player, bool>? ValidPlayers { get; set; } = null; /// <summary> /// Whether the last queued clip will loop. /// </summary> - public bool Looping = false; + public bool Looping { get; set; } = false; /// <summary> - /// The position in samples of the current clip. + /// The position in samples of the current clip. /// </summary> - public int CurrentPosition = 0; + public int CurrentPosition { get; set; } = 0; /// <summary> /// Number of samples in the current clip. /// </summary> - public int CurrentSampleCount => currentSamples == EmptyData ? 0 : currentSamples.Length; + public int CurrentSampleCount => _currentSamples == EmptyData ? 0 : _currentSamples.Length; /// <summary> /// Whether playback is active and can be stopped or paused. /// </summary> - public bool IsPlaying => update.IsRunning && !IsPaused; + public bool IsPlaying => _update.IsRunning && !IsPaused; /// <summary> /// Whether playback is paused and can be resumed. /// </summary> - public bool IsPaused => update.IsAliveAndPaused; - - private readonly OpusEncoder opusEncoder; - - private CoroutineHandle update; - - private double targetTime = 0.0; - - private bool breakCurrent = false; - - private float[] currentSamples = EmptyData; + public bool IsPaused => _update.IsAliveAndPaused; private bool CanLoop => AudioClipSamples.Count == 0 && Looping; - /// <summary> - /// Creates a new audio transmitter for the specified controller. - /// </summary> - /// <param name="controllerId">The controller specified by its Id.</param> - /// <param name="type">What kind of audio the encoder should optimise's for.</param> - public AudioTransmitter(byte controllerId, OpusApplicationType type = OpusApplicationType.Audio) - { - ControllerId = controllerId; - opusEncoder = new OpusEncoder(type); - } - /// <summary> /// Plays the PCM samples on the current controller. /// </summary> @@ -126,17 +120,19 @@ public AudioTransmitter(byte controllerId, OpusApplicationType type = OpusApplic /// <param name="samples">The PCM samples.</param> /// <param name="queue">Whether to queue the audio if audio is already playing, otherwise overrides the current audio.</param> /// <param name="loop"> - /// Whether to loop this clip. + /// Whether to loop this clip. /// Loop ends if another clip is played either immediately if not queued or at the end of the loop if next clip was queued. /// </param> public void Play(float[] samples, bool queue, bool loop) { if (samples.IsEmpty()) + { throw new InvalidOperationException($"Audio clip samples must not be empty"); + } if (!queue) { - breakCurrent = true; + _breakCurrent = true; AudioClipSamples.Clear(); CurrentPosition = 0; } @@ -144,8 +140,10 @@ public void Play(float[] samples, bool queue, bool loop) AudioClipSamples.Enqueue(samples); Looping = loop; - if (!update.IsRunning) - update = Timing.RunCoroutine(Transmit(), Segment.Update); + if (!_update.IsRunning) + { + _update = Timing.RunCoroutine(Transmit(), Segment.Update); + } } /// <summary> @@ -153,7 +151,7 @@ public void Play(float[] samples, bool queue, bool loop) /// </summary> public void Pause() { - update.IsAliveAndPaused = true; + _update.IsAliveAndPaused = true; } /// <summary> @@ -161,8 +159,8 @@ public void Pause() /// </summary> public void Resume() { - update.IsAliveAndPaused = false; - targetTime = NetworkTime.time; + _update.IsAliveAndPaused = false; + _targetTime = NetworkTime.time; } /// <summary> @@ -173,12 +171,16 @@ public void Resume() public void Skip(int count) { if (count == 0) + { return; + } - breakCurrent = true; + _breakCurrent = true; CurrentPosition = 0; for (int i = 1; i < count; i++) + { AudioClipSamples.Dequeue(); + } } /// <summary> @@ -186,39 +188,43 @@ public void Skip(int count) /// </summary> public void Stop() { - Timing.KillCoroutines(update); + Timing.KillCoroutines(_update); AudioClipSamples.Clear(); CurrentPosition = 0; } private IEnumerator<float> Transmit() { - targetTime = NetworkTime.time; + _targetTime = NetworkTime.time; while (!AudioClipSamples.IsEmpty()) { - currentSamples = AudioClipSamples.Dequeue(); + _currentSamples = AudioClipSamples.Dequeue(); - breakCurrent = false; - while (!breakCurrent && (CanLoop || CurrentPosition < currentSamples.Length)) + _breakCurrent = false; + while (!_breakCurrent && (CanLoop || CurrentPosition < _currentSamples.Length)) { try { - while (targetTime < NetworkTime.time) + while (_targetTime < NetworkTime.time) { int read = 0; while (read != FrameSize) { int remaining = FrameSize - read; - int count = Mathf.Max(Mathf.Min(CurrentPosition + remaining, currentSamples.Length) - CurrentPosition, 0); - Array.Copy(currentSamples, CurrentPosition, TempSampleData, read, count); + int count = Mathf.Max(Mathf.Min(CurrentPosition + remaining, _currentSamples.Length) - CurrentPosition, 0); + Array.Copy(_currentSamples, CurrentPosition, TempSampleData, read, count); if (remaining == count) + { CurrentPosition += count; + } else { CurrentPosition = 0; if (!CanLoop) - currentSamples = AudioClipSamples.IsEmpty() ? EmptyData : AudioClipSamples.Dequeue(); + { + _currentSamples = AudioClipSamples.IsEmpty() ? EmptyData : AudioClipSamples.Dequeue(); + } } read += count; @@ -227,9 +233,11 @@ private IEnumerator<float> Transmit() // Client sided bug causes output to be 3db quieter than expected // so we correct for that here for (int i = 0; i < TempSampleData.Length; i++) + { TempSampleData[i] *= GainCorrectionFactor; + } - int length = opusEncoder.Encode(TempSampleData, TempEncodedData, FrameSize); + int length = _opusEncoder.Encode(TempSampleData, TempEncodedData, FrameSize); if (length > 2) { AudioMessage msg = new() @@ -240,12 +248,16 @@ private IEnumerator<float> Transmit() }; if (ValidPlayers != null) + { msg.SendToHubsConditionally(x => x.Mode != ClientInstanceMode.Unverified && ValidPlayers.Invoke(Player.Get(x))); + } else + { msg.SendToAuthenticated(); + } } - targetTime += FramePeriod; + _targetTime += FramePeriod; } } catch (Exception ex) From 0a53fd6c38f49fb28718b2ad406beb1b6791b79d Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:40:24 +0930 Subject: [PATCH 071/215] console --- LabApi/Features/Console/Logger.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/LabApi/Features/Console/Logger.cs b/LabApi/Features/Console/Logger.cs index 2b5445e6..e0c59c16 100644 --- a/LabApi/Features/Console/Logger.cs +++ b/LabApi/Features/Console/Logger.cs @@ -30,7 +30,9 @@ public static class Logger public static void Debug(object message, bool canBePrinted = true) { if (!canBePrinted) + { return; + } Raw(FormatLog(message, DebugPrefix, Assembly.GetCallingAssembly()), ConsoleColor.Gray); } From 888a9307e63a683ea0d0be5b937dbc18f7616606 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:40:30 +0930 Subject: [PATCH 072/215] enums --- LabApi/Features/Enums/DoorName.cs | 93 ++++++++++++++++--------------- 1 file changed, 48 insertions(+), 45 deletions(-) diff --git a/LabApi/Features/Enums/DoorName.cs b/LabApi/Features/Enums/DoorName.cs index 21dd9d55..466d70d2 100644 --- a/LabApi/Features/Enums/DoorName.cs +++ b/LabApi/Features/Enums/DoorName.cs @@ -1,47 +1,50 @@ -namespace LabApi.Features.Enums +namespace LabApi.Features.Enums; + +/// <summary> +/// Enum type that represents all the door name tags defined in the game. +/// </summary> +public enum DoorName { - /// <summary> - /// Enum type that represents all the door name tags defined in the game. - /// </summary> - public enum DoorName - { - None = 0, - LczPc,// LCZ_CAFE - LczWc,// LCZ_WC - LczCheckpointA,// CHECKPOINT_LCZ_A - LczCheckpointB,// CHECKPOINT_LCZ_B - LczArmory,// LCZ_ARMORY - Lcz173Bottom,// 173_BOTTOM - Lcz173Gate,// 173_GATE - Lcz173Connector,// 173_CONNECTOR - Lcz173Armory,// 173_ARMORY - LczGr18Inner,// GR18_INNER - LczGr18Gate,// GR18 - Lcz914Gate,// 914 - Lcz330,// 330 - Lcz330Chamber,// 330_CHAMBER - Hcz079FirstGate,// 079_FIRST - Hcz079SecondGate,// 079_SECOND - Hcz079Armory,// 079_ARMORY - Hcz096,// 096 - Hcz939Cryo,// 939_CRYO - HczArmory,// HCZ_ARMORY - Hcz049Armory,// 049_ARMORY - HczHidChamber,// HID_CHAMBER - HczHidUpper,// HID_UPPER - HczHidLower,// HID_LOWER - HczNukeArmory,// NUKE_ARMORY - Hcz106Primiary,// 106_PRIMARY - Hcz106Secondary,// 106_SECONDARY - HczCheckpoint,// CHECKPOINT_EZ_HCZ_A - Hcz127Lab, // HCZ_127_LAB - EzIntercom,// INTERCOM - EzGateA,// GATE_A - EzGateB,// GATE_B - SurfaceGate,// SURFACE_GATE - SurfaceNuke,// SURFACE_NUKE - SurfaceEscapePrimary,// ESCAPE_PRIMARY - SurfaceEscapeSecondary,// ESCAPE_SECONDARY - SurfaceEscapeFinal,// ESCAPE_FINAL - } +#pragma warning disable SA1602 // Enumeration items should be documented +#pragma warning disable CS1591 // Missing XML Comment for publicly visible type or member + None = 0, + LczPc, // LCZ_CAFE + LczWc, // LCZ_WC + LczCheckpointA, // CHECKPOINT_LCZ_A + LczCheckpointB, // CHECKPOINT_LCZ_B + LczArmory, // LCZ_ARMORY + Lcz173Bottom, // 173_BOTTOM + Lcz173Gate, // 173_GATE + Lcz173Connector, // 173_CONNECTOR + Lcz173Armory, // 173_ARMORY + LczGr18Inner, // GR18_INNER + LczGr18Gate, // GR18 + Lcz914Gate, // 914 + Lcz330, // 330 + Lcz330Chamber, // 330_CHAMBER + Hcz079FirstGate, // 079_FIRST + Hcz079SecondGate, // 079_SECOND + Hcz079Armory, // 079_ARMORY + Hcz096, // 096 + Hcz939Cryo, // 939_CRYO + HczArmory, // HCZ_ARMORY + Hcz049Armory, // 049_ARMORY + HczHidChamber, // HID_CHAMBER + HczHidUpper, // HID_UPPER + HczHidLower, // HID_LOWER + HczNukeArmory, // NUKE_ARMORY + Hcz106Primiary, // 106_PRIMARY + Hcz106Secondary, // 106_SECONDARY + HczCheckpoint, // CHECKPOINT_EZ_HCZ_A + Hcz127Lab, // HCZ_127_LAB + EzIntercom, // INTERCOM + EzGateA, // GATE_A + EzGateB, // GATE_B + SurfaceGate, // SURFACE_GATE + SurfaceNuke, // SURFACE_NUKE + SurfaceEscapePrimary, // ESCAPE_PRIMARY + SurfaceEscapeSecondary, // ESCAPE_SECONDARY + SurfaceEscapeFinal, // ESCAPE_FINAL +#pragma warning restore SA1602 // Enumeration items should be documented +#pragma warning restore CS1591 // Missing XML Comment for publicly visible type or member } From f07e997ddc6b74b7bd5921b547bcd0057577a65d Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:40:39 +0930 Subject: [PATCH 073/215] exntensions --- LabApi/Features/Extensions/LinqExtensions.cs | 28 +++++++++++++------ LabApi/Features/Extensions/PriorityQueue.cs | 28 +++++++++++++------ .../Features/Extensions/PriorityQueuePool.cs | 6 ++-- LabApi/Features/Extensions/RoleExtensions.cs | 4 +-- 4 files changed, 45 insertions(+), 21 deletions(-) diff --git a/LabApi/Features/Extensions/LinqExtensions.cs b/LabApi/Features/Extensions/LinqExtensions.cs index 37a31fd2..d8ccc0b3 100644 --- a/LabApi/Features/Extensions/LinqExtensions.cs +++ b/LabApi/Features/Extensions/LinqExtensions.cs @@ -10,48 +10,60 @@ namespace LabApi.Features.Extensions; public static class LinqExtensions { /// <summary> - /// Finds smallest value by a specified key. - /// If 2 or more occurances have the same minimum value then the first one in the collection is returned. + /// Finds smallest value by a specified key. + /// If 2 or more occurrences have the same minimum value then the first one in the collection is returned. /// </summary> /// <typeparam name="T">The type to compare and select.</typeparam> - /// <typeparam name="K">The value to compare the keys.</typeparam> + /// <typeparam name="TKey">The value to compare the keys.</typeparam> /// <param name="enumerable">The enumerable collection.</param> /// <param name="selectFunc">The selection function.</param> /// <returns>Minimum value or <see langword="null"/> if the collection is empty.</returns> - public static T? MinBy<T, K>(this IEnumerable<T> enumerable, Func<T, K> selectFunc) where T : class where K : IComparable + public static T? MinBy<T, TKey>(this IEnumerable<T> enumerable, Func<T, TKey> selectFunc) + where T : class + where TKey : IComparable { if (!enumerable.Any()) + { return null; + } T? currentMin = enumerable.First(); foreach (T member in enumerable) { if (selectFunc(member).CompareTo(selectFunc(currentMin)) < 0) + { currentMin = member; + } } return currentMin; } /// <summary> - /// Finds largest value by a specified key. - /// If 2 or more occurances have the same minimum value then the first one in the collection is returned. + /// Finds largest value by a specified key. + /// If 2 or more occurrences have the same minimum value then the first one in the collection is returned. /// </summary> /// <typeparam name="T">The type to compare and select.</typeparam> - /// <typeparam name="K">The value to compare the keys.</typeparam> + /// <typeparam name="TKey">The value to compare the keys.</typeparam> /// <param name="enumerable">The enumerable collection.</param> /// <param name="selectFunc">The selection function.</param> /// <returns>Maximum value or <see langword="null"/> if the collection is empty.</returns> - public static T? MaxBy<T, K>(this IEnumerable<T> enumerable, Func<T, K> selectFunc) where T : class where K : IComparable + public static T? MaxBy<T, TKey>(this IEnumerable<T> enumerable, Func<T, TKey> selectFunc) + where T : class + where TKey : IComparable { if (!enumerable.Any()) + { return null; + } T? currentMin = enumerable.First(); foreach (T member in enumerable) { if (selectFunc(member).CompareTo(selectFunc(currentMin)) > 0) + { currentMin = member; + } } return currentMin; diff --git a/LabApi/Features/Extensions/PriorityQueue.cs b/LabApi/Features/Extensions/PriorityQueue.cs index 5b81f3a8..be989c92 100644 --- a/LabApi/Features/Extensions/PriorityQueue.cs +++ b/LabApi/Features/Extensions/PriorityQueue.cs @@ -9,21 +9,21 @@ namespace LabApi.Features.Extensions; /// <typeparam name="T">Data type to store in the queue.</typeparam> public class PriorityQueue<T> { - /// <summary> - /// Gets the number of items currently in the queue. - /// </summary> - public int Count => _elements.Count; - - private readonly List<ValueTuple<int, T>> _elements; + private readonly List<(int, T)> _elements; /// <summary> /// Initializes a new instance of the <see cref="PriorityQueue{T}"/> class. /// </summary> public PriorityQueue() { - _elements = new List<ValueTuple<int, T>>(); + _elements = []; } + /// <summary> + /// Gets the number of items currently in the queue. + /// </summary> + public int Count => _elements.Count; + /// <summary> /// Adds an item to the priority queue with the specified priority. /// Smaller numbers indicate higher priority. @@ -32,10 +32,11 @@ public PriorityQueue() /// <param name="priority">The priority of the item.</param> public void Enqueue(T item, int priority) { - ValueTuple<int, T> newItem = new ValueTuple<int, T>(priority, item); + ValueTuple<int, T> newItem = new(priority, item); _elements.Add(newItem); HeapifyUp(_elements.Count - 1); } + /// <summary> /// Removes and returns the item with the highest priority (smallest priority value) from the queue. /// </summary> @@ -44,7 +45,9 @@ public void Enqueue(T item, int priority) public T Dequeue() { if (Count == 0) + { throw new InvalidOperationException("The queue is empty."); + } T bestItem = _elements[0].Item2; int lastIndex = _elements.Count - 1; @@ -53,10 +56,13 @@ public T Dequeue() _elements.RemoveAt(lastIndex); if (Count > 0) + { HeapifyDown(0); + } return bestItem; } + /// <summary> /// Clears all items from the queue. /// </summary> @@ -88,13 +94,19 @@ private void HeapifyDown(int index) smallestChildIndex = index; if (leftChildIndex < Count && _elements[leftChildIndex].Item1 < _elements[smallestChildIndex].Item1) + { smallestChildIndex = leftChildIndex; + } if (rightChildIndex < Count && _elements[rightChildIndex].Item1 < _elements[smallestChildIndex].Item1) + { smallestChildIndex = rightChildIndex; + } if (smallestChildIndex == index) + { break; + } Swap(index, smallestChildIndex); index = smallestChildIndex; diff --git a/LabApi/Features/Extensions/PriorityQueuePool.cs b/LabApi/Features/Extensions/PriorityQueuePool.cs index 00ecd3f8..c171c073 100644 --- a/LabApi/Features/Extensions/PriorityQueuePool.cs +++ b/LabApi/Features/Extensions/PriorityQueuePool.cs @@ -1,10 +1,10 @@ -using System.Collections.Concurrent; using NorthwoodLib.Pools; +using System.Collections.Concurrent; namespace LabApi.Features.Extensions; /// <summary> -/// Pool for <see cref="PriorityQueue{T}"/> +/// Pool for <see cref="PriorityQueue{T}"/>. /// </summary> /// <typeparam name="T">Type of the queue.</typeparam> public sealed class PriorityQueuePool<T> : IPool<PriorityQueue<T>> @@ -15,7 +15,7 @@ public sealed class PriorityQueuePool<T> : IPool<PriorityQueue<T>> public static readonly PriorityQueuePool<T> Shared = new(); private readonly ConcurrentQueue<PriorityQueue<T>> _pool = new(); - + /// <summary> /// Gives a pooled <see cref="PriorityQueue{T}"/> or creates a new one if the pool is empty. /// </summary> diff --git a/LabApi/Features/Extensions/RoleExtensions.cs b/LabApi/Features/Extensions/RoleExtensions.cs index e148d3c9..94dc7129 100644 --- a/LabApi/Features/Extensions/RoleExtensions.cs +++ b/LabApi/Features/Extensions/RoleExtensions.cs @@ -13,14 +13,14 @@ public static class RoleExtensions /// <param name="roleType">The <see cref="RoleTypeId"/>.</param> /// <returns>The <see cref="PlayerRoleBase"/>.</returns> public static PlayerRoleBase GetRoleBase(this RoleTypeId roleType) => PlayerRoleLoader.TryGetRoleTemplate(roleType, out PlayerRoleBase role) ? role : null!; - + /// <summary> /// Gets the human-readable version of a <see cref="RoleTypeId"/>'s name. /// </summary> /// <param name="roleType">The <see cref="RoleTypeId"/>.</param> /// <returns>The name of the role.</returns> public static string GetFullName(this RoleTypeId roleType) => roleType.GetRoleBase().RoleName; - + /// <summary> /// Checks if the role is an SCP role. /// </summary> From fc9b72afb4a2fabc1b67dd35221111f6bbda38b2 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:40:48 +0930 Subject: [PATCH 074/215] permissions --- .../Permissions/PermissionsExtensions.cs | 8 ++-- .../Permissions/PermissionsManager.cs | 19 +++++++--- .../Providers/DefaultPermissionsProvider.cs | 38 +++++++++++++------ .../Permissions/Providers/PermissionGroup.cs | 36 ++++++++++-------- 4 files changed, 64 insertions(+), 37 deletions(-) diff --git a/LabApi/Features/Permissions/PermissionsExtensions.cs b/LabApi/Features/Permissions/PermissionsExtensions.cs index cc65ca67..dec1782b 100644 --- a/LabApi/Features/Permissions/PermissionsExtensions.cs +++ b/LabApi/Features/Permissions/PermissionsExtensions.cs @@ -1,8 +1,8 @@ -using System; -using System.Collections.Generic; using CommandSystem; using LabApi.Features.Wrappers; using RemoteAdmin; +using System; +using System.Collections.Generic; namespace LabApi.Features.Permissions; @@ -13,11 +13,11 @@ public static class PermissionsExtensions { /// <inheritdoc cref="PermissionsManager.GetPermissionsByProvider"/> public static Dictionary<Type, string[]> GetPermissionsByProvider(this ICommandSender sender) => - Player.Get(sender)?.GetPermissionsByProvider() ?? new Dictionary<Type, string[]>(); + Player.Get(sender)?.GetPermissionsByProvider() ?? []; /// <inheritdoc cref="IPermissionsProvider.GetPermissions"/> public static string[] GetPermissions(this ICommandSender sender) => - Player.Get(sender)?.GetPermissions() ?? Array.Empty<string>(); + Player.Get(sender)?.GetPermissions() ?? []; /// <inheritdoc cref="IPermissionsProvider.HasPermissions"/> public static bool HasPermissions(this ICommandSender sender, params string[] permissions) => diff --git a/LabApi/Features/Permissions/PermissionsManager.cs b/LabApi/Features/Permissions/PermissionsManager.cs index b21cb91b..58cefce7 100644 --- a/LabApi/Features/Permissions/PermissionsManager.cs +++ b/LabApi/Features/Permissions/PermissionsManager.cs @@ -1,8 +1,8 @@ +using LabApi.Features.Console; +using LabApi.Features.Wrappers; using System; using System.Collections.Generic; using System.Linq; -using LabApi.Features.Console; -using LabApi.Features.Wrappers; namespace LabApi.Features.Permissions; @@ -16,13 +16,14 @@ public static class PermissionsManager /// <summary> /// Internal dictionary to store the registered permission providers. /// </summary> - private static readonly Dictionary<Type, IPermissionsProvider> PermissionProviders = new(); + private static readonly Dictionary<Type, IPermissionsProvider> PermissionProviders = []; /// <summary> /// Registers the given <see cref="IPermissionsProvider"/>. /// </summary> /// <typeparam name="T">The type of the permission provider to register.</typeparam> - public static void RegisterProvider<T>() where T : IPermissionsProvider, new() + public static void RegisterProvider<T>() + where T : IPermissionsProvider, new() { if (PermissionProviders.ContainsKey(typeof(T))) { @@ -43,10 +44,13 @@ public static class PermissionsManager /// Unregisters the given <see cref="IPermissionsProvider"/>. /// </summary> /// <typeparam name="T">The type of the permission provider to unregister.</typeparam> - public static void UnregisterProvider<T>() where T : IPermissionsProvider, new() + public static void UnregisterProvider<T>() + where T : IPermissionsProvider, new() { if (PermissionProviders.Remove(typeof(T))) + { return; + } Logger.Warn($"{LoggerPrefix} Failed to unregister the permission provider of type {typeof(T).FullName}. It is not registered."); } @@ -56,10 +60,13 @@ public static class PermissionsManager /// </summary> /// <typeparam name="T">The type of the permission provider to retrieve.</typeparam> /// <returns>The registered <see cref="IPermissionsProvider"/> of the given type <typeparamref name="T"/>; otherwise, null.</returns> - public static IPermissionsProvider? GetProvider<T>() where T : IPermissionsProvider, new() + public static IPermissionsProvider? GetProvider<T>() + where T : IPermissionsProvider, new() { if (PermissionProviders.TryGetValue(typeof(T), out IPermissionsProvider provider)) + { return provider; + } Logger.Warn($"{LoggerPrefix} The permission provider of type {typeof(T).FullName} is not registered."); return null; diff --git a/LabApi/Features/Permissions/Providers/DefaultPermissionsProvider.cs b/LabApi/Features/Permissions/Providers/DefaultPermissionsProvider.cs index 4a51a584..0b49ac83 100644 --- a/LabApi/Features/Permissions/Providers/DefaultPermissionsProvider.cs +++ b/LabApi/Features/Permissions/Providers/DefaultPermissionsProvider.cs @@ -1,12 +1,12 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; using LabApi.Features.Console; using LabApi.Features.Wrappers; using LabApi.Loader.Features.Paths; using NorthwoodLib.Pools; using Serialization; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; namespace LabApi.Features.Permissions.Providers; @@ -20,7 +20,7 @@ public class DefaultPermissionsProvider : IPermissionsProvider private const string PermissionsFileName = "permissions.yml"; private readonly FileInfo _permissions; - private Dictionary<string, PermissionGroup> _permissionsDictionary = new(); + private Dictionary<string, PermissionGroup> _permissionsDictionary = []; /// <summary> /// Creates a new instance of the <see cref="DefaultPermissionsProvider"/> class. @@ -86,7 +86,7 @@ public bool HasAnyPermission(Player player, params string[] permissions) public void AddPermissions(Player player, params string[] permissions) { PermissionGroup group = GetPlayerGroup(player); - group.Permissions = group.Permissions.Concat(permissions).ToArray(); + group.Permissions = [.. group.Permissions, .. permissions]; ReloadPermissions(); SavePermissions(); } @@ -100,6 +100,9 @@ public void RemovePermissions(Player player, params string[] permissions) SavePermissions(); } + /// <inheritdoc /> + void IPermissionsProvider.ReloadPermissions() => ReloadPermissions(); + private PermissionGroup GetPlayerGroup(Player player) => _permissionsDictionary.GetValueOrDefault(player.PermissionsGroupName ?? "default") ?? PermissionGroup.Default; private string[] GetPermissions(PermissionGroup group) @@ -112,22 +115,28 @@ private string[] GetPermissions(PermissionGroup group) foreach (string inheritedGroup in group.InheritedGroups) { if (!_permissionsDictionary.TryGetValue(inheritedGroup, out PermissionGroup inherited)) + { continue; + } permissions.AddRange(GetPermissions(inherited)); } - return permissions.ToArray(); + return [.. permissions]; } private bool HasPermission(PermissionGroup group, string permission) { if (group.IsRoot) + { return true; - + } + // We do first check if the group has the permission. if (group.Permissions.Contains(permission)) + { return true; + } if (permission.Contains(".")) { @@ -135,17 +144,23 @@ private bool HasPermission(PermissionGroup group, string permission) string perm = permission[..index]; if (group.SpecialPermissionsSuperset.Contains(perm + ".*")) + { return true; + } } // Then we check if the group has the permission from the inherited groups. foreach (string inheritedGroup in group.InheritedGroups) { if (!_permissionsDictionary.TryGetValue(inheritedGroup, out PermissionGroup inherited)) + { continue; + } if (HasPermission(inherited, permission)) + { return true; + } } return false; @@ -157,8 +172,6 @@ private void LoadDefaultPermissions() ReloadPermissions(); } - void IPermissionsProvider.ReloadPermissions() => ReloadPermissions(); - private void ReloadPermissions() { // We clear the special permissions and fill them again. @@ -170,12 +183,15 @@ private void ReloadPermissions() if (permission == ".*") { permissionsGroup.IsRoot = true; + // We don't have to continue. break; } - + if (!permission.Contains(".*")) + { continue; + } int index = permission.LastIndexOf(".", StringComparison.Ordinal); string perm = permission[..index]; diff --git a/LabApi/Features/Permissions/Providers/PermissionGroup.cs b/LabApi/Features/Permissions/Providers/PermissionGroup.cs index dcb80acb..875e0806 100644 --- a/LabApi/Features/Permissions/Providers/PermissionGroup.cs +++ b/LabApi/Features/Permissions/Providers/PermissionGroup.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using YamlDotNet.Serialization; @@ -9,20 +8,6 @@ namespace LabApi.Features.Permissions.Providers; /// </summary> public class PermissionGroup { - /// <summary> - /// Constructor for deserialization. - /// </summary> - public PermissionGroup() : this([], []) {} - - /// <summary> - /// Represents a group of permissions. They are linked to RA user groups. - /// </summary> - public PermissionGroup(string[] inheritedGroups, string[] permissions) - { - InheritedGroups = inheritedGroups; - Permissions = permissions; - } - /// <summary> /// Gets the default permission group. /// </summary> @@ -37,13 +22,32 @@ public static Dictionary<string, PermissionGroup> DefaultPermissionGroups { Dictionary<string, PermissionGroup> groups = new() { - ["default"] = Default + ["default"] = Default, }; return groups; } } + /// <summary> + /// Constructor for deserialization. + /// </summary> + public PermissionGroup() + : this([], []) + { + } + + /// <summary> + /// Represents a group of permissions. They are linked to RA user groups. + /// </summary> + /// <param name="inheritedGroups">Array of groups that should be inherited.</param> + /// <param name="permissions">Array of permissions this group should have.</param> + public PermissionGroup(string[] inheritedGroups, string[] permissions) + { + InheritedGroups = inheritedGroups; + Permissions = permissions; + } + /// <summary> /// The inherited groups of the group. /// </summary> From 430844d605da09635fd905e835b18460e6a024d9 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:40:54 +0930 Subject: [PATCH 075/215] stores --- LabApi/Features/Stores/CustomDataStore.cs | 84 ++++++++----------- .../Features/Stores/CustomDataStoreManager.cs | 53 +++++++++--- .../Stores/CustomDataStore{TStore}.cs | 27 ++++++ 3 files changed, 107 insertions(+), 57 deletions(-) create mode 100644 LabApi/Features/Stores/CustomDataStore{TStore}.cs diff --git a/LabApi/Features/Stores/CustomDataStore.cs b/LabApi/Features/Stores/CustomDataStore.cs index e27ad23d..90b4d3d4 100644 --- a/LabApi/Features/Stores/CustomDataStore.cs +++ b/LabApi/Features/Stores/CustomDataStore.cs @@ -1,8 +1,8 @@ +using LabApi.Features.Wrappers; +using NorthwoodLib.Pools; using System; using System.Collections.Generic; using System.Linq; -using LabApi.Features.Wrappers; -using NorthwoodLib.Pools; namespace LabApi.Features.Stores; @@ -11,22 +11,7 @@ namespace LabApi.Features.Stores; /// </summary> public abstract class CustomDataStore { - private static readonly Dictionary<Type, Dictionary<Player, CustomDataStore>> StoreInstances = new(); - - /// <summary> - /// Gets the <see cref="Player"/> that this instance is associated with. - /// </summary> - public Player Owner { get; internal set; } - - /// <summary> - /// Initializes a new instance of the <see cref="CustomDataStore"/> class. - /// </summary> - /// <param name="owner">The <see cref="Player"/> that this instance is associated with.</param> - protected CustomDataStore(Player owner) - { - Owner = owner; - InternalOnInstanceCreated(); - } + private static readonly Dictionary<Type, Dictionary<Player, CustomDataStore>> StoreInstances = []; /// <summary> /// Gets the <see cref="CustomDataStore"/> for the specified <see cref="Player"/>, or creates a new one if it doesn't exist. @@ -40,16 +25,20 @@ public static TStore GetOrAdd<TStore>(Player player) Type type = typeof(TStore); if (!CustomDataStoreManager.IsRegistered<TStore>()) + { CustomDataStoreManager.RegisterStore<TStore>(); + } if (!StoreInstances.TryGetValue(type, out Dictionary<Player, CustomDataStore>? playerStores)) { - playerStores = new Dictionary<Player, CustomDataStore>(); + playerStores = []; StoreInstances[type] = playerStores; } if (playerStores.TryGetValue(player, out CustomDataStore? store)) + { return (TStore)store; + } store = (TStore)Activator.CreateInstance(type, player); playerStores[player] = store; @@ -57,16 +46,6 @@ public static TStore GetOrAdd<TStore>(Player player) return (TStore)store; } - /// <summary> - /// Called when a new instance of the <see cref="CustomDataStore"/> is created. - /// </summary> - protected virtual void OnInstanceCreated() { } - - /// <summary> - /// Called when an instance of the <see cref="CustomDataStore"/> is going to be destroyed. - /// </summary> - protected virtual void OnInstanceDestroyed() { } - /// <summary> /// Destroys the <see cref="CustomDataStore"/> for the specified <see cref="Player"/>. /// </summary> @@ -76,10 +55,14 @@ internal static void Destroy<TStore>(Player player) where TStore : CustomDataStore { if (!StoreInstances.TryGetValue(typeof(TStore), out Dictionary<Player, CustomDataStore>? playerStores)) + { return; + } if (!playerStores.TryGetValue(player, out CustomDataStore? store)) + { return; + } store.Destroy(); } @@ -94,11 +77,28 @@ internal static void DestroyAll<TStore>() entry.Value.Where(static playerStore => playerStore.Value.GetType() == typeof(TStore)).Select(playerStore => playerStore.Value))); foreach (CustomDataStore? store in storesToRemove) + { store.Destroy(); + } ListPool<CustomDataStore>.Shared.Return(storesToRemove); } + /// <summary> + /// Initializes a new instance of the <see cref="CustomDataStore"/> class. + /// </summary> + /// <param name="owner">The <see cref="Player"/> that this instance is associated with.</param> + protected CustomDataStore(Player owner) + { + Owner = owner; + InternalOnInstanceCreated(); + } + + /// <summary> + /// Gets the <see cref="Player"/> that this instance is associated with. + /// </summary> + public Player Owner { get; internal set; } + /// <summary> /// Destroys this instance of the <see cref="CustomDataStore"/>. /// </summary> @@ -108,29 +108,19 @@ internal void Destroy() StoreInstances[GetType()].Remove(Owner); } - private void InternalOnInstanceCreated() => OnInstanceCreated(); -} - -/// <summary> -/// Represents a Custom Data Store that plugins can use to store data with a player. -/// </summary> -/// <typeparam name="TStore">The type of the <see cref="CustomDataStore"/>.</typeparam> -public abstract class CustomDataStore<TStore> : CustomDataStore - where TStore : CustomDataStore<TStore> -{ /// <summary> - /// Initializes a new instance of the <see cref="CustomDataStore"/> class. + /// Called when a new instance of the <see cref="CustomDataStore"/> is created. /// </summary> - /// <param name="owner">The <see cref="Player"/> that this instance is associated with.</param> - protected CustomDataStore(Player owner) - : base(owner) + protected virtual void OnInstanceCreated() { } /// <summary> - /// Gets the <see cref="CustomDataStore"/> for the specified <see cref="Player"/>. + /// Called when an instance of the <see cref="CustomDataStore"/> is going to be destroyed. /// </summary> - /// <param name="player">The <see cref="Player"/> to get the <see cref="CustomDataStore"/> for.</param> - /// <returns>The <see cref="CustomDataStore"/> for the specified <see cref="Player"/>.</returns> - public static TStore Get(Player player) => GetOrAdd<TStore>(player); + protected virtual void OnInstanceDestroyed() + { + } + + private void InternalOnInstanceCreated() => OnInstanceCreated(); } \ No newline at end of file diff --git a/LabApi/Features/Stores/CustomDataStoreManager.cs b/LabApi/Features/Stores/CustomDataStoreManager.cs index 57add4ba..d882830a 100644 --- a/LabApi/Features/Stores/CustomDataStoreManager.cs +++ b/LabApi/Features/Stores/CustomDataStoreManager.cs @@ -1,7 +1,7 @@ +using LabApi.Features.Wrappers; using System; using System.Collections.Generic; using System.Reflection; -using LabApi.Features.Wrappers; namespace LabApi.Features.Stores; @@ -10,10 +10,10 @@ namespace LabApi.Features.Stores; /// </summary> public static class CustomDataStoreManager { - private static readonly List<Type> RegisteredStores = new (); - private static readonly Dictionary<Type, MethodInfo> GetOrAddMethods = new (); - private static readonly Dictionary<Type, MethodInfo> DestroyMethods = new (); - private static readonly Dictionary<Type, MethodInfo> DestroyAllMethods = new (); + private static readonly List<Type> RegisteredStores = []; + private static readonly Dictionary<Type, MethodInfo> GetOrAddMethods = []; + private static readonly Dictionary<Type, MethodInfo> DestroyMethods = []; + private static readonly Dictionary<Type, MethodInfo> DestroyAllMethods = []; /// <summary> /// Registers a custom data store. @@ -24,25 +24,34 @@ public static bool RegisterStore<T>() where T : CustomDataStore { Type type = typeof(T); - if (RegisteredStores.Contains(type)) return false; + if (RegisteredStores.Contains(type)) + { + return false; + } MethodInfo? getOrAddMethod = typeof(CustomDataStore).GetMethod(nameof(CustomDataStore.GetOrAdd), BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); if (getOrAddMethod == null) + { return false; + } getOrAddMethod = getOrAddMethod.MakeGenericMethod(type); GetOrAddMethods.Add(type, getOrAddMethod); MethodInfo? destroyMethod = typeof(CustomDataStore).GetMethod(nameof(CustomDataStore.Destroy), BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); if (destroyMethod == null) + { return false; + } destroyMethod = destroyMethod.MakeGenericMethod(type); DestroyMethods.Add(type, destroyMethod); MethodInfo? destroyAllMethod = typeof(CustomDataStore).GetMethod(nameof(CustomDataStore.DestroyAll), BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); if (destroyAllMethod == null) + { return false; + } destroyAllMethod = destroyAllMethod.MakeGenericMethod(type); DestroyAllMethods.Add(type, destroyAllMethod); @@ -60,9 +69,11 @@ public static void UnregisterStore<T>() where T : CustomDataStore { Type type = typeof(T); - + if (DestroyAllMethods.TryGetValue(type, out MethodInfo? method)) + { method.Invoke(null, null); + } DestroyAllMethods.Remove(type); RegisteredStores.Remove(type); @@ -70,19 +81,41 @@ public static void UnregisterStore<T>() DestroyMethods.Remove(type); } + /// <summary> + /// Method used to initialize stores when a new player joins the server. + /// </summary> + /// <param name="player">The player added to the game.</param> internal static void AddPlayer(Player player) { foreach (Type? storeType in RegisteredStores) - GetOrAddMethods[storeType].Invoke(null, new object[] { player }); + { + GetOrAddMethods[storeType].Invoke(null, [player]); + } } - internal static void RemovePlayer(Player player) + /// <summary> + /// Method used to destroy stores when an existing player leaves the server. + /// </summary> + /// <param name="player">The player removed from the game.</param> + internal static void RemovePlayer(Player player) { foreach (Type? storeType in RegisteredStores) - DestroyMethods[storeType].Invoke(null, new object[] { player }); + { + DestroyMethods[storeType].Invoke(null, [player]); + } } + /// <summary> + /// Whether the store type had been registered. + /// </summary> + /// <param name="type">The <see cref="Type"/> of the store.</param> + /// <returns><see langword="true"/> if registered; otherwise <see langword="false"/>.</returns> internal static bool IsRegistered(Type type) => RegisteredStores.Contains(type); + /// <summary> + /// Whether the store type had been registered. + /// </summary> + /// <typeparam name="T">The stores type.</typeparam> + /// <returns><see langword="true"/> if registered; otherwise <see langword="false"/>.</returns> internal static bool IsRegistered<T>() => IsRegistered(typeof(T)); } \ No newline at end of file diff --git a/LabApi/Features/Stores/CustomDataStore{TStore}.cs b/LabApi/Features/Stores/CustomDataStore{TStore}.cs new file mode 100644 index 00000000..4daa39a4 --- /dev/null +++ b/LabApi/Features/Stores/CustomDataStore{TStore}.cs @@ -0,0 +1,27 @@ +using LabApi.Features.Wrappers; + +namespace LabApi.Features.Stores; + +/// <summary> +/// Represents a Custom Data Store that plugins can use to store data with a player. +/// </summary> +/// <typeparam name="TStore">The type of the <see cref="CustomDataStore"/>.</typeparam> +public abstract class CustomDataStore<TStore> : CustomDataStore + where TStore : CustomDataStore<TStore> +{ + /// <summary> + /// Gets the <see cref="CustomDataStore"/> for the specified <see cref="Player"/>. + /// </summary> + /// <param name="player">The <see cref="Player"/> to get the <see cref="CustomDataStore"/> for.</param> + /// <returns>The <see cref="CustomDataStore"/> for the specified <see cref="Player"/>.</returns> + public static TStore Get(Player player) => GetOrAdd<TStore>(player); + + /// <summary> + /// Initializes a new instance of the <see cref="CustomDataStore"/> class. + /// </summary> + /// <param name="owner">The <see cref="Player"/> that this instance is associated with.</param> + protected CustomDataStore(Player owner) + : base(owner) + { + } +} From 93ed63bff420b88f6dc66d4f41d6856a44fdd053 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:41:01 +0930 Subject: [PATCH 076/215] admintoys --- .../Features/Wrappers/AdminToys/AdminToy.cs | 308 +++++++++--------- 1 file changed, 161 insertions(+), 147 deletions(-) diff --git a/LabApi/Features/Wrappers/AdminToys/AdminToy.cs b/LabApi/Features/Wrappers/AdminToys/AdminToy.cs index e891c506..ce7eefd3 100644 --- a/LabApi/Features/Wrappers/AdminToys/AdminToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/AdminToy.cs @@ -1,6 +1,5 @@ using AdminToys; using Generators; -using MapGeneration; using Mirror; using System; using System.Collections.Generic; @@ -14,6 +13,49 @@ namespace LabApi.Features.Wrappers; /// </summary> public class AdminToy { + /// <summary> + /// Contains all the handlers for constructing wrappers for the associated base game types. + /// </summary> + private static readonly Dictionary<Type, Func<AdminToyBase, AdminToy?>> _typeWrappers = []; + + /// <summary> + /// Contains all the cached admin toys, accessible through their <see cref="Base"/>. + /// </summary> + public static Dictionary<AdminToyBase, AdminToy> Dictionary { get; } = []; + + /// <summary> + /// A reference to all instances of <see cref="AdminToy"/>. + /// </summary> + public static IReadOnlyCollection<AdminToy> List => Dictionary.Values; + + /// <summary> + /// Gets the admin toy wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="AdminToyBase"/> was not <see langword="null"/>. + /// </summary> + /// <param name="adminToyBase">The <see cref="Base"/> of the admin toy.</param> + /// <returns>The requested admin toy or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(adminToyBase))] + public static AdminToy? Get(AdminToyBase? adminToyBase) + { + if (adminToyBase == null) + { + return null; + } + + return Dictionary.TryGetValue(adminToyBase, out AdminToy item) ? item : CreateAdminToyWrapper(adminToyBase); + } + + /// <summary> + /// Tries to get the admin toy wrapper from the <see cref="Dictionary"/>. + /// </summary> + /// <param name="adminToyBase">The <see cref="Base"/> of the admin toy.</param> + /// <param name="adminToy">The requested admin toy.</param> + /// <returns>True if the admin toy exists, otherwise <see langword="false"/>.</returns> + public static bool TryGet(AdminToyBase? adminToyBase, [NotNullWhen(true)] out AdminToy? adminToy) + { + adminToy = Get(adminToyBase); + return adminToy != null; + } + /// <summary> /// Initializes the <see cref="AdminToy"/> class. /// </summary> @@ -35,43 +77,129 @@ internal static void Initialize() } /// <summary> - /// Contains all the handlers for constructing wrappers for the associated base game types. + /// Instantiates a new base game admin toy object. /// </summary> - private static readonly Dictionary<Type, Func<AdminToyBase, AdminToy?>> typeWrappers = []; + /// <typeparam name="T">The base game admin toy type.</typeparam> + /// <param name="position">The initial local position.</param> + /// <param name="rotation">The initial local rotation.</param> + /// <param name="scale">The initial local scale.</param> + /// <param name="parent">The parent transform.</param> + /// <returns>The instantiated admin toy.</returns> + protected static T Create<T>(Vector3 position, Quaternion rotation, Vector3 scale, Transform? parent) + where T : AdminToyBase + { + if (PrefabCache<T>.Prefab == null) + { + T? found = null; + foreach (GameObject prefab in NetworkClient.prefabs.Values) + { + if (prefab.TryGetComponent(out found)) + { + break; + } + } + + if (found == null) + { + throw new InvalidOperationException($"No prefab in NetworkClient.prefabs has component type {typeof(T)}"); + } + + PrefabCache<T>.Prefab = found; + } + + T instance = UnityEngine.Object.Instantiate(PrefabCache<T>.Prefab, parent); + instance.transform.localPosition = position; + instance.transform.localRotation = rotation; + instance.transform.localScale = scale; + return instance; + } /// <summary> - /// Contains all the cached admin toys, accessible through their <see cref="Base"/>. + /// Creates a new wrapper from the base admin toy object. /// </summary> - public static Dictionary<AdminToyBase, AdminToy> Dictionary { get; } = []; + /// <param name="adminToyBase">The base object.</param> + /// <returns>The newly created wrapper.</returns> + protected static AdminToy CreateAdminToyWrapper(AdminToyBase adminToyBase) + { + if (!_typeWrappers.TryGetValue(adminToyBase.GetType(), out Func<AdminToyBase, AdminToy?> handler)) + { + Console.Logger.InternalWarn($"Backing up to the default AdminToy constructor. Missing constructor handler for type {adminToyBase.GetType()}"); + return new AdminToy(adminToyBase); + } + + AdminToy? wrapper = handler.Invoke(adminToyBase); + if (wrapper == null) + { + Console.Logger.InternalWarn($"Backing up to the default AdminToy constructor. A handler returned null for type {adminToyBase.GetType()}"); + return new AdminToy(adminToyBase); + } + + return wrapper ?? new AdminToy(adminToyBase); + } /// <summary> - /// A reference to all instances of <see cref="AdminToy"/>. + /// A private method to handle the creation of new admin toys in the server. /// </summary> - public static IReadOnlyCollection<AdminToy> List => Dictionary.Values; + /// <param name="adminToyBase">The created <see cref="AdminToyBase"/> instance.</param> + private static void AddAdminToy(AdminToyBase adminToyBase) + { + try + { + if (!Dictionary.ContainsKey(adminToyBase)) + { + _ = CreateAdminToyWrapper(adminToyBase); + } + } + catch (Exception e) + { + Console.Logger.InternalError($"Failed to handle admin toy creation with error: {e}"); + } + } /// <summary> - /// A protected constructor to prevent external instantiation. + /// A private method to handle the removal of admin toys from the server. /// </summary> - /// <param name="adminToyBase">The base object.</param> - protected AdminToy(AdminToyBase adminToyBase) + /// <param name="adminToyBase">The to be destroyed <see cref="AdminToyBase"/> instance.</param> + private static void RemoveAdminToy(AdminToyBase adminToyBase) { - Base = adminToyBase; - - if (CanCache) - Dictionary.Add(adminToyBase, this); + try + { + if (Dictionary.TryGetValue(adminToyBase, out AdminToy adminToy)) + { + Dictionary.Remove(adminToyBase); + adminToy.OnRemove(); + } + } + catch (Exception e) + { + Console.Logger.InternalError($"Failed to handle admin toy destruction with error: {e}"); + } } /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. + /// A private method to handle the addition of wrapper handlers. /// </summary> - internal virtual void OnRemove() + /// <typeparam name="T">The derived base game type to handle.</typeparam> + /// <param name="constructor">A handler to construct the wrapper with the base game instance.</param> + private static void Register<T>(Func<T, AdminToy?> constructor) + where T : AdminToyBase { + _typeWrappers.Add(typeof(T), x => constructor((T)x)); } /// <summary> - /// Whether to cache this wrapper. + /// A protected constructor to prevent external instantiation. /// </summary> - protected bool CanCache => !IsDestroyed && Base.isActiveAndEnabled; + /// <param name="adminToyBase">The base object.</param> + protected AdminToy(AdminToyBase adminToyBase) + { + Base = adminToyBase; + + if (CanCache) + { + Dictionary.Add(adminToyBase, this); + } + } /// <summary> /// The <see cref="AdminToyBase">base</see> object. @@ -143,7 +271,7 @@ public Vector3 Scale /// <para> /// Can be used even if <see cref="IsStatic"/> is <see langword="true"/>. /// When changing parent the toys relative <see cref="Position"/>, <see cref="Rotation"/> and <see cref="Scale"/> are retained. - /// Note that if the parent has <see cref="NetworkServer.Destroy"/> called on it this object automatically has <see cref="NetworkServer.Destroy"/> called on itself. + /// Note that if the parent has <see cref="NetworkServer.Destroy"/> called on it this object automatically has <see cref="NetworkServer.Destroy"/> called on itself. /// To prevent destruction make sure you unparent it before that happens. /// </para> /// </remarks> @@ -171,7 +299,7 @@ public byte MovementSmoothing /// <summary> /// Gets or sets whether the admin toy is static. /// This should be enabled on as many toys possible to increase performance. - /// Static is only applies to the local transformations so parenting to something that moves will still causes it to move while retaining the performance boost. + /// Static is only applies to the local transformations so parenting to something that moves will still causes it to move while retaining the performance boost. /// </summary> /// <remarks> /// A static admin toy will not process <see cref="Position"/>, <see cref="Rotation"/> or <see cref="Scale"/> on both server and client drastically increasing performance. @@ -194,6 +322,11 @@ public float SyncInterval set => Base.syncInterval = value; } + /// <summary> + /// Whether to cache this wrapper. + /// </summary> + protected bool CanCache => !IsDestroyed && Base.isActiveAndEnabled; + /// <summary> /// Spawns the toy on the client. /// </summary> @@ -211,143 +344,24 @@ public float SyncInterval public void Destroy() => NetworkServer.Destroy(GameObject); /// <summary> - /// Instantiates a new base game admin toy object. - /// </summary> - /// <typeparam name="T">The base game admin toy type.</typeparam> - /// <param name="position">The initial local position.</param> - /// <param name="rotation">The initial local rotation.</param> - /// <param name="scale">The initial local scale.</param> - /// <param name="parent">The parent transform.</param> - /// <returns>The instantiated admin toy.</returns> - protected static T Create<T>(Vector3 position, Quaternion rotation, Vector3 scale, Transform? parent) where T : AdminToyBase - { - if (PrefabCache<T>.prefab == null) - { - T? found = null; - foreach (GameObject prefab in NetworkClient.prefabs.Values) - { - if (prefab.TryGetComponent(out found)) - break; - } - - if (found == null) - throw new InvalidOperationException($"No prefab in NetworkClient.prefabs has component type {typeof(T)}"); - - PrefabCache<T>.prefab = found; - } - - T instance = UnityEngine.Object.Instantiate(PrefabCache<T>.prefab, parent); - instance.transform.localPosition = position; - instance.transform.localRotation = rotation; - instance.transform.localScale = scale; - return instance; - } - - /// <summary> - /// Gets the admin toy wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="AdminToyBase"/> was not <see langword="null"/>. - /// </summary> - /// <param name="adminToyBase">The <see cref="Base"/> of the admin toy.</param> - /// <returns>The requested admin toy or <see langword="null"/>.</returns> - [return: NotNullIfNotNull(nameof(adminToyBase))] - public static AdminToy? Get(AdminToyBase? adminToyBase) - { - if (adminToyBase == null) - return null; - - return Dictionary.TryGetValue(adminToyBase, out AdminToy item) ? item : CreateAdminToyWrapper(adminToyBase); - } - - /// <summary> - /// Tries to get the admin toy wrapper from the <see cref="Dictionary"/>. - /// </summary> - /// <param name="adminToyBase">The <see cref="Base"/> of the admin toy.</param> - /// <param name="adminToy">The requested admin toy.</param> - /// <returns>True if the admin toy exists, otherwise <see langword="false"/>.</returns> - public static bool TryGet(AdminToyBase? adminToyBase, [NotNullWhen(true)] out AdminToy? adminToy) - { - adminToy = Get(adminToyBase); - return adminToy != null; - } - - /// <summary> - /// Creates a new wrapper from the base admin toy object. - /// </summary> - /// <param name="adminToyBase">The base object.</param> - /// <returns>The newly created wrapper.</returns> - protected static AdminToy CreateAdminToyWrapper(AdminToyBase adminToyBase) - { - if (!typeWrappers.TryGetValue(adminToyBase.GetType(), out Func<AdminToyBase, AdminToy?> handler)) - { - Console.Logger.InternalWarn($"Backing up to the default AdminToy constructor. Missing constructor handler for type {adminToyBase.GetType()}"); - return new AdminToy(adminToyBase); - } - - AdminToy? wrapper = handler.Invoke(adminToyBase); - if (wrapper == null) - { - Console.Logger.InternalWarn($"Backing up to the default AdminToy constructor. A handler returned null for type {adminToyBase.GetType()}"); - return new AdminToy(adminToyBase); - } - - return wrapper ?? new AdminToy(adminToyBase); - } - - /// <summary> - /// A private method to handle the creation of new admin toys in the server. - /// </summary> - /// <param name="adminToyBase">The created <see cref="AdminToyBase"/> instance.</param> - private static void AddAdminToy(AdminToyBase adminToyBase) - { - try - { - if (!Dictionary.ContainsKey(adminToyBase)) - _ = CreateAdminToyWrapper(adminToyBase); - } - catch (Exception e) - { - Console.Logger.InternalError($"Failed to handle admin toy creation with error: {e}"); - } - } - - /// <summary> - /// A private method to handle the removal of admin toys from the server. - /// </summary> - /// <param name="adminToyBase">The to be destroyed <see cref="AdminToyBase"/> instance.</param> - private static void RemoveAdminToy(AdminToyBase adminToyBase) - { - try - { - - if (Dictionary.TryGetValue(adminToyBase, out AdminToy adminToy)) - { - Dictionary.Remove(adminToyBase); - adminToy.OnRemove(); - } - } - catch (Exception e) - { - Console.Logger.InternalError($"Failed to handle admin toy destruction with error: {e}"); - } - } - - /// <summary> - /// A private method to handle the addition of wrapper handlers. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <typeparam name="T">The derived base game type to handle.</typeparam> - /// <param name="constructor">A handler to construct the wrapper with the base game instance.</param> - private static void Register<T>(Func<T, AdminToy?> constructor) where T : AdminToyBase + internal virtual void OnRemove() { - typeWrappers.Add(typeof(T), x => constructor((T)x)); } +#pragma warning disable SA1204 // Static elements should appear before instance elements /// <summary> /// Static prefab cache used to speed up prefab search. /// </summary> - internal static class PrefabCache<T> where T : NetworkBehaviour + /// <typeparam name="T">The base game component type of the prefab.</typeparam> + internal static class PrefabCache<T> + where T : NetworkBehaviour { /// <summary> /// Cached prefab instance for type T. /// </summary> - public static T? prefab = null; + public static T? Prefab { get; set; } = null; } +#pragma warning restore SA1204 // Static elements should appear before instance elements } From 2f2cef8860bc094f45e22c5d735f0789b013091e Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:41:07 +0930 Subject: [PATCH 077/215] camaratoy --- .../Features/Wrappers/AdminToys/CameraToy.cs | 136 +++++++++--------- 1 file changed, 71 insertions(+), 65 deletions(-) diff --git a/LabApi/Features/Wrappers/AdminToys/CameraToy.cs b/LabApi/Features/Wrappers/AdminToys/CameraToy.cs index 92af8fa4..129a29ea 100644 --- a/LabApi/Features/Wrappers/AdminToys/CameraToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/CameraToy.cs @@ -13,33 +13,87 @@ public class CameraToy : AdminToy /// <summary> /// Contains all the camera toys, accessible through their <see cref="Base"/>. /// </summary> - public new static Dictionary<Scp079CameraToy, CameraToy> Dictionary { get; } = []; + public static new Dictionary<Scp079CameraToy, CameraToy> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="CameraToy"/>. /// </summary> - public new static IReadOnlyCollection<CameraToy> List => Dictionary.Values; + public static new IReadOnlyCollection<CameraToy> List => Dictionary.Values; + + /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> + public static CameraToy Create(Transform? parent = null, bool networkSpawn = true) + => Create(Vector3.zero, parent, networkSpawn); + + /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> + public static CameraToy Create(Vector3 position, Transform? parent = null, bool networkSpawn = true) + => Create(position, Quaternion.identity, parent, networkSpawn); + + /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> + public static CameraToy Create(Vector3 position, Quaternion rotation, Transform? parent = null, bool networkSpawn = true) + => Create(position, rotation, Vector3.one, parent, networkSpawn); + + /// <summary> + /// Creates a new camera toy. + /// </summary> + /// <param name="position">The initial local position.</param> + /// <param name="rotation">The initial local rotation.</param> + /// <param name="scale">The initial local scale.</param> + /// <param name="parent">The parent transform.</param> + /// <param name="networkSpawn">Whether to spawn the toy on the client.</param> + /// <returns>The created camera toy.</returns> + public static CameraToy Create(Vector3 position, Quaternion rotation, Vector3 scale, Transform? parent = null, bool networkSpawn = true) + { + CameraToy toy = Get(Create<Scp079CameraToy>(position, rotation, scale, parent)); + + if (networkSpawn) + { + toy.Spawn(); + } + + return toy; + } + + /// <summary> + /// Gets the camera toy wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="Scp079CameraToy"/> was not <see langword="null"/>. + /// </summary> + /// <param name="baseCameraToy">The <see cref="Base"/> of the camera toy.</param> + /// <returns>The requested camera toy or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(baseCameraToy))] + public static CameraToy? Get(Scp079CameraToy? baseCameraToy) + { + if (baseCameraToy == null) + { + return null; + } + + return Dictionary.TryGetValue(baseCameraToy, out CameraToy item) ? item : (CameraToy)CreateAdminToyWrapper(baseCameraToy); + } + + /// <summary> + /// Tries to get the camera toy wrapper from the <see cref="Dictionary"/>. + /// </summary> + /// <param name="baseCameraToy">The <see cref="Base"/> of the camera toy.</param> + /// <param name="cameraToy">The requested camera toy.</param> + /// <returns>True if the camera toy exists, otherwise false.</returns> + public static bool TryGet(Scp079CameraToy? baseCameraToy, [NotNullWhen(true)] out CameraToy? cameraToy) + { + cameraToy = Get(baseCameraToy); + return cameraToy != null; + } /// <summary> /// An internal constructor to prevent external instantiation. /// </summary> /// <param name="baseCameraToy">The base <see cref="Scp079CameraToy"/> object.</param> - internal CameraToy(Scp079CameraToy baseCameraToy) + internal CameraToy(Scp079CameraToy baseCameraToy) : base(baseCameraToy) { Base = baseCameraToy; if (CanCache) + { Dictionary.Add(baseCameraToy, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -103,7 +157,7 @@ public Vector2 HorizontalConstraint /// Gets or set the min and max zoom level of the camera. /// </summary> /// <remarks> - /// Values range from 0.0 to 1.0, with zero being the minimum zoom, and 1 being the maximum zoom. + /// Values range from 0.0 to 1.0, with zero being the minimum zoom, and 1 being the maximum zoom. /// X should be less than or equal to y. /// </remarks> public Vector2 ZoomConstraints @@ -112,60 +166,12 @@ public Vector2 ZoomConstraints set => Base.NetworkZoomConstraint = value; } - /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> - public static CameraToy Create(Transform? parent = null, bool networkSpawn = true) - => Create(Vector3.zero, parent, networkSpawn); - - /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> - public static CameraToy Create(Vector3 position, Transform? parent = null, bool networkSpawn = true) - => Create(position, Quaternion.identity, parent, networkSpawn); - - /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> - public static CameraToy Create(Vector3 position, Quaternion rotation, Transform? parent = null, bool networkSpawn = true) - => Create(position, rotation, Vector3.one, parent, networkSpawn); - /// <summary> - /// Creates a new camera toy. - /// </summary> - /// <param name="position">The initial local position.</param> - /// <param name="rotation">The initial local rotation.</param> - /// <param name="scale">The initial local scale.</param> - /// <param name="parent">The parent transform.</param> - /// <param name="networkSpawn">Whether to spawn the toy on the client.</param> - /// <returns>The created camera toy.</returns> - public static CameraToy Create(Vector3 position, Quaternion rotation, Vector3 scale, Transform? parent = null, bool networkSpawn = true) - { - CameraToy toy = Get(Create<Scp079CameraToy>(position, rotation, scale, parent)); - - if (networkSpawn) - toy.Spawn(); - - return toy; - } - - /// <summary> - /// Gets the camera toy wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="Scp079CameraToy"/> was not <see langword="null"/>. - /// </summary> - /// <param name="baseCameraToy">The <see cref="Base"/> of the camera toy.</param> - /// <returns>The requested camera toy or <see langword="null"/>.</returns> - [return: NotNullIfNotNull(nameof(baseCameraToy))] - public static CameraToy? Get(Scp079CameraToy? baseCameraToy) - { - if (baseCameraToy == null) - return null; - - return Dictionary.TryGetValue(baseCameraToy, out CameraToy item) ? item : (CameraToy)CreateAdminToyWrapper(baseCameraToy); - } - - /// <summary> - /// Tries to get the camera toy wrapper from the <see cref="Dictionary"/>. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="baseCameraToy">The <see cref="Base"/> of the camera toy.</param> - /// <param name="cameraToy">The requested camera toy.</param> - /// <returns>True if the camera toy exists, otherwise false.</returns> - public static bool TryGet(Scp079CameraToy? baseCameraToy, [NotNullWhen(true)] out CameraToy? cameraToy) + internal override void OnRemove() { - cameraToy = Get(baseCameraToy); - return cameraToy != null; + base.OnRemove(); + Dictionary.Remove(Base); } } From c032b86927a3b84b81c455a670f1f9d4b0c4b2b9 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:41:18 +0930 Subject: [PATCH 078/215] capybara --- .../Wrappers/AdminToys/CapybaraToy.cs | 82 ++++++++++--------- 1 file changed, 44 insertions(+), 38 deletions(-) diff --git a/LabApi/Features/Wrappers/AdminToys/CapybaraToy.cs b/LabApi/Features/Wrappers/AdminToys/CapybaraToy.cs index ae38b80d..2f703443 100644 --- a/LabApi/Features/Wrappers/AdminToys/CapybaraToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/CapybaraToy.cs @@ -13,48 +13,12 @@ public class CapybaraToy : AdminToy /// <summary> /// Contains all the capybara toys, accessible through their <see cref="Base"/>. /// </summary> - public new static Dictionary<BaseCapybaraToy, CapybaraToy> Dictionary { get; } = []; + public static new Dictionary<BaseCapybaraToy, CapybaraToy> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="CapybaraToy"/>. /// </summary> - public new static IReadOnlyCollection<CapybaraToy> List => Dictionary.Values; - - /// <summary> - /// An internal constructor to prevent external instantiation. - /// </summary> - /// <param name="baseCapybaraToy">The base <see cref="BaseCapybaraToy"/> object.</param> - internal CapybaraToy(BaseCapybaraToy baseCapybaraToy) - : base(baseCapybaraToy) - { - Base = baseCapybaraToy; - - if (CanCache) - Dictionary.Add(baseCapybaraToy, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); - } - - /// <summary> - /// The <see cref="BaseCapybaraToy"/> object. - /// </summary> - public new BaseCapybaraToy Base { get; } - - /// <summary> - /// Gets or sets whether the capybara has enabled colliders. - /// </summary> - public bool CollidersEnabled - { - get => Base.CollisionsEnabled; - set => Base.CollisionsEnabled = value; - } + public static new IReadOnlyCollection<CapybaraToy> List => Dictionary.Values; /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> public static CapybaraToy Create(Transform? parent = null, bool networkSpawn = true) @@ -82,7 +46,9 @@ public static CapybaraToy Create(Vector3 position, Quaternion rotation, Vector3 CapybaraToy toy = Get(Create<BaseCapybaraToy>(position, rotation, scale, parent)); if (networkSpawn) + { toy.Spawn(); + } return toy; } @@ -96,8 +62,48 @@ public static CapybaraToy Create(Vector3 position, Quaternion rotation, Vector3 public static CapybaraToy? Get(BaseCapybaraToy? baseCapybaraToy) { if (baseCapybaraToy == null) + { return null; + } return Dictionary.TryGetValue(baseCapybaraToy, out CapybaraToy toy) ? toy : (CapybaraToy)CreateAdminToyWrapper(baseCapybaraToy); } + + /// <summary> + /// An internal constructor to prevent external instantiation. + /// </summary> + /// <param name="baseCapybaraToy">The base <see cref="BaseCapybaraToy"/> object.</param> + internal CapybaraToy(BaseCapybaraToy baseCapybaraToy) + : base(baseCapybaraToy) + { + Base = baseCapybaraToy; + + if (CanCache) + { + Dictionary.Add(baseCapybaraToy, this); + } + } + + /// <summary> + /// The <see cref="BaseCapybaraToy"/> object. + /// </summary> + public new BaseCapybaraToy Base { get; } + + /// <summary> + /// Gets or sets whether the capybara has enabled colliders. + /// </summary> + public bool CollidersEnabled + { + get => Base.CollisionsEnabled; + set => Base.CollisionsEnabled = value; + } + + /// <summary> + /// An internal method to remove itself from the cache when the base object is destroyed. + /// </summary> + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); + } } From e55c9fd8a429322a0def6076a39b8a30b0f6d2f6 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:41:23 +0930 Subject: [PATCH 079/215] interactable --- .../Wrappers/AdminToys/InteractableToy.cs | 184 ++++++++++-------- 1 file changed, 105 insertions(+), 79 deletions(-) diff --git a/LabApi/Features/Wrappers/AdminToys/InteractableToy.cs b/LabApi/Features/Wrappers/AdminToys/InteractableToy.cs index 0bc5381a..9727b8a4 100644 --- a/LabApi/Features/Wrappers/AdminToys/InteractableToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/InteractableToy.cs @@ -14,39 +14,88 @@ public class InteractableToy : AdminToy /// <summary> /// Contains all the interactable toys, accessible through their <see cref="Base"/>. /// </summary> - public new static Dictionary<InvisibleInteractableToy, InteractableToy> Dictionary { get; } = []; + public static new Dictionary<InvisibleInteractableToy, InteractableToy> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="InteractableToy"/>. /// </summary> - public new static IReadOnlyCollection<InteractableToy> List => Dictionary.Values; + public static new IReadOnlyCollection<InteractableToy> List => Dictionary.Values; + + /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> + public static InteractableToy Create(Transform? parent = null, bool networkSpawn = true) + => Create(Vector3.zero, parent, networkSpawn); + + /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> + public static InteractableToy Create(Vector3 position, Transform? parent = null, bool networkSpawn = true) + => Create(position, Quaternion.identity, parent, networkSpawn); + + /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> + public static InteractableToy Create(Vector3 position, Quaternion rotation, Transform? parent = null, bool networkSpawn = true) + => Create(position, rotation, Vector3.one, parent, networkSpawn); /// <summary> - /// An internal constructor to prevent external instantiation. + /// Creates a new interactable toy. /// </summary> - /// <param name="baseInteractableToy">The base <see cref="InvisibleInteractableToy"/> object.</param> - internal InteractableToy(InvisibleInteractableToy baseInteractableToy) - : base(baseInteractableToy) + /// <param name="position">The initial local position.</param> + /// <param name="rotation">The initial local rotation.</param> + /// <param name="scale">The initial local scale.</param> + /// <param name="parent">The parent transform.</param> + /// <param name="networkSpawn">Whether to spawn the toy on the client.</param> + /// <returns>The created interactable toy.</returns> + public static InteractableToy Create(Vector3 position, Quaternion rotation, Vector3 scale, Transform? parent = null, bool networkSpawn = true) { - Base = baseInteractableToy; + InteractableToy toy = Get(Create<InvisibleInteractableToy>(position, rotation, scale, parent)); - if (CanCache) - Dictionary.Add(baseInteractableToy, this); + if (networkSpawn) + { + toy.Spawn(); + } + + return toy; } /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. + /// Gets the interactable toy wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="InvisibleInteractableToy"/> was not <see langword="null"/>. /// </summary> - internal override void OnRemove() + /// <param name="baseInteractableToy">The <see cref="Base"/> of the interactable toy.</param> + /// <returns>The requested interactable toy or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(baseInteractableToy))] + public static InteractableToy? Get(InvisibleInteractableToy? baseInteractableToy) { - base.OnRemove(); - Dictionary.Remove(Base); + if (baseInteractableToy == null) + { + return null; + } + + return Dictionary.TryGetValue(baseInteractableToy, out InteractableToy item) ? item : (InteractableToy)CreateAdminToyWrapper(baseInteractableToy); } /// <summary> - /// The <see cref="InvisibleInteractableToy"/> object. + /// Tries to get the interactable toy wrapper from the <see cref="Dictionary"/>. /// </summary> - public new InvisibleInteractableToy Base { get; } + /// <param name="baseInteractableToy">The <see cref="Base"/> of the interactable toy.</param> + /// <param name="interactableToy">The requested interactable toy.</param> + /// <returns>True if the interactable toy exists, otherwise false.</returns> + public static bool TryGet(InvisibleInteractableToy? baseInteractableToy, [NotNullWhen(true)] out InteractableToy? interactableToy) + { + interactableToy = Get(baseInteractableToy); + return interactableToy != null; + } + + /// <summary> + /// An internal constructor to prevent external instantiation. + /// </summary> + /// <param name="baseInteractableToy">The base <see cref="InvisibleInteractableToy"/> object.</param> + internal InteractableToy(InvisibleInteractableToy baseInteractableToy) + : base(baseInteractableToy) + { + Base = baseInteractableToy; + + if (CanCache) + { + Dictionary.Add(baseInteractableToy, this); + } + } /// <summary> /// Event called when a <see cref="Player"/> interacts with the toy. @@ -56,16 +105,21 @@ public event Action<Player> OnInteracted add { if (InternalOnInteracted == null) + { Base.OnInteracted += InvokeOnInteracted; + } InternalOnInteracted += value; } + remove { InternalOnInteracted -= value; if (InternalOnInteracted == null) + { Base.OnInteracted -= InvokeOnInteracted; + } } } @@ -77,16 +131,21 @@ public event Action<Player> OnSearching add { if (InternalOnSearching == null) + { Base.OnSearching += InvokeOnSearching; + } InternalOnSearching += value; } + remove { InternalOnSearching -= value; if (InternalOnSearching == null) + { Base.OnSearching -= InvokeOnSearching; + } } } @@ -98,16 +157,21 @@ public event Action<Player> OnSearched add { if (InternalOnSearched == null) + { Base.OnSearched += InvokeOnSearched; + } InternalOnSearched += value; } + remove { InternalOnSearched -= value; if (InternalOnSearched == null) + { Base.OnSearched -= InvokeOnSearched; + } } } @@ -119,19 +183,37 @@ public event Action<Player> OnSearchAborted add { if (InternalOnSearchAborted == null) + { Base.OnSearched += InvokeOnSearchAborted; + } InternalOnSearchAborted += value; } + remove { InternalOnSearchAborted -= value; if (InternalOnSearchAborted == null) + { Base.OnSearched -= InvokeOnSearchAborted; + } } } + private event Action<Player>? InternalOnInteracted; + + private event Action<Player>? InternalOnSearching; + + private event Action<Player>? InternalOnSearched; + + private event Action<Player>? InternalOnSearchAborted; + + /// <summary> + /// The <see cref="InvisibleInteractableToy"/> object. + /// </summary> + public new InvisibleInteractableToy Base { get; } + /// <summary> /// Gets or sets the shape of the collider used for interactions. /// </summary> @@ -173,13 +255,14 @@ public bool IsLocked /// </summary> public bool CanSearch => Base.CanSearch; - private event Action<Player>? InternalOnInteracted; - - private event Action<Player>? InternalOnSearching; - - private event Action<Player>? InternalOnSearched; - - private event Action<Player>? InternalOnSearchAborted; + /// <summary> + /// An internal method to remove itself from the cache when the base object is destroyed. + /// </summary> + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); + } private void InvokeOnInteracted(ReferenceHub hub) => InternalOnInteracted?.Invoke(Player.Get(hub)); @@ -188,61 +271,4 @@ public bool IsLocked private void InvokeOnSearched(ReferenceHub hub) => InternalOnSearched?.Invoke(Player.Get(hub)); private void InvokeOnSearchAborted(ReferenceHub hub) => InternalOnSearchAborted?.Invoke(Player.Get(hub)); - - /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> - public static InteractableToy Create(Transform? parent = null, bool networkSpawn = true) - => Create(Vector3.zero, parent, networkSpawn); - - /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> - public static InteractableToy Create(Vector3 position, Transform? parent = null, bool networkSpawn = true) - => Create(position, Quaternion.identity, parent, networkSpawn); - - /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> - public static InteractableToy Create(Vector3 position, Quaternion rotation, Transform? parent = null, bool networkSpawn = true) - => Create(position, rotation, Vector3.one, parent, networkSpawn); - - /// <summary> - /// Creates a new interactable toy. - /// </summary> - /// <param name="position">The initial local position.</param> - /// <param name="rotation">The initial local rotation.</param> - /// <param name="scale">The initial local scale.</param> - /// <param name="parent">The parent transform.</param> - /// <param name="networkSpawn">Whether to spawn the toy on the client.</param> - /// <returns>The created interactable toy.</returns> - public static InteractableToy Create(Vector3 position, Quaternion rotation, Vector3 scale, Transform? parent = null, bool networkSpawn = true) - { - InteractableToy toy = Get(Create<InvisibleInteractableToy>(position, rotation, scale, parent)); - - if (networkSpawn) - toy.Spawn(); - - return toy; - } - - /// <summary> - /// Gets the interactable toy wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="InvisibleInteractableToy"/> was not <see langword="null"/>. - /// </summary> - /// <param name="baseInteractableToy">The <see cref="Base"/> of the interactable toy.</param> - /// <returns>The requested interactable toy or <see langword="null"/>.</returns> - [return: NotNullIfNotNull(nameof(baseInteractableToy))] - public static InteractableToy? Get(InvisibleInteractableToy? baseInteractableToy) - { - if (baseInteractableToy == null) - return null; - - return Dictionary.TryGetValue(baseInteractableToy, out InteractableToy item) ? item : (InteractableToy)CreateAdminToyWrapper(baseInteractableToy); - } - - /// <summary> - /// Tries to get the interactable toy wrapper from the <see cref="Dictionary"/>. - /// </summary> - /// <param name="baseInteractableToy">The <see cref="Base"/> of the interactable toy.</param> - /// <param name="interactableToy">The requested interactable toy.</param> - /// <returns>True if the interactable toy exists, otherwise false.</returns> - public static bool TryGet(InvisibleInteractableToy? baseInteractableToy, [NotNullWhen(true)] out InteractableToy? interactableToy) - { - interactableToy = Get(baseInteractableToy); - return interactableToy != null; - } } From 7e93341e42c815610c89b11a48153f841c8a1819 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:41:31 +0930 Subject: [PATCH 080/215] lightsource --- .../Wrappers/AdminToys/LightSourceToy.cs | 136 +++++++++--------- 1 file changed, 72 insertions(+), 64 deletions(-) diff --git a/LabApi/Features/Wrappers/AdminToys/LightSourceToy.cs b/LabApi/Features/Wrappers/AdminToys/LightSourceToy.cs index 8a0f4c78..c442f09a 100644 --- a/LabApi/Features/Wrappers/AdminToys/LightSourceToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/LightSourceToy.cs @@ -13,33 +13,87 @@ public class LightSourceToy : AdminToy /// <summary> /// Contains all the light source toys, accessible through their <see cref="Base"/>. /// </summary> - public new static Dictionary<BaseLightSourceToy, LightSourceToy> Dictionary { get; } = []; + public static new Dictionary<BaseLightSourceToy, LightSourceToy> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="LightSourceToy"/>. /// </summary> - public new static IReadOnlyCollection<LightSourceToy> List => Dictionary.Values; + public static new IReadOnlyCollection<LightSourceToy> List => Dictionary.Values; + + /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> + public static LightSourceToy Create(Transform? parent = null, bool networkSpawn = true) + => Create(Vector3.zero, parent, networkSpawn); + + /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> + public static LightSourceToy Create(Vector3 position, Transform? parent = null, bool networkSpawn = true) + => Create(position, Quaternion.identity, parent, networkSpawn); + + /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> + public static LightSourceToy Create(Vector3 position, Quaternion rotation, Transform? parent = null, bool networkSpawn = true) + => Create(position, rotation, Vector3.one, parent, networkSpawn); + + /// <summary> + /// Creates a new light source toy. + /// </summary> + /// <param name="position">The initial local position.</param> + /// <param name="rotation">The initial local rotation.</param> + /// <param name="scale">The initial local scale.</param> + /// <param name="parent">The parent transform.</param> + /// <param name="networkSpawn">Whether to spawn the toy on the client.</param> + /// <returns>The created light source toy.</returns> + public static LightSourceToy Create(Vector3 position, Quaternion rotation, Vector3 scale, Transform? parent = null, bool networkSpawn = true) + { + LightSourceToy toy = Get(Create<BaseLightSourceToy>(position, rotation, scale, parent)); + + if (networkSpawn) + { + toy.Spawn(); + } + + return toy; + } + + /// <summary> + /// Gets the light source toy wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseLightSourceToy"/> was not <see langword="null"/>. + /// </summary> + /// <param name="baseLightSourceToy">The <see cref="Base"/> of the light source toy.</param> + /// <returns>The requested light source toy or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(baseLightSourceToy))] + public static LightSourceToy? Get(BaseLightSourceToy? baseLightSourceToy) + { + if (baseLightSourceToy == null) + { + return null; + } + + return Dictionary.TryGetValue(baseLightSourceToy, out LightSourceToy item) ? item : (LightSourceToy)CreateAdminToyWrapper(baseLightSourceToy); + } + + /// <summary> + /// Tries to get the light source toy wrapper from the <see cref="Dictionary"/>. + /// </summary> + /// <param name="baseLightSourceToy">The <see cref="Base"/> of the light source toy.</param> + /// <param name="lightSourceToy">The requested light source toy.</param> + /// <returns><see langword="True"/> if the light toy exists, otherwise <see langword="false"/>.</returns> + public static bool TryGet(BaseLightSourceToy? baseLightSourceToy, [NotNullWhen(true)] out LightSourceToy? lightSourceToy) + { + lightSourceToy = Get(baseLightSourceToy); + return lightSourceToy != null; + } /// <summary> /// An internal constructor to prevent external instantiation. /// </summary> /// <param name="baseLightSourceToy">The base <see cref="BaseLightSourceToy"/> object.</param> - internal LightSourceToy(BaseLightSourceToy baseLightSourceToy) + internal LightSourceToy(BaseLightSourceToy baseLightSourceToy) : base(baseLightSourceToy) { Base = baseLightSourceToy; if (CanCache) + { Dictionary.Add(baseLightSourceToy, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -104,7 +158,9 @@ public LightType Type /// <summary> /// Gets or sets the lights <see cref="Light.shape"/>. /// </summary> +#pragma warning disable CS0618 // Type or member is obsolete public LightShape Shape +#pragma warning restore CS0618 // Type or member is obsolete { get => Base.LightShape; set => Base.NetworkLightShape = value; @@ -134,60 +190,12 @@ public override string ToString() return $"[LightSourceToy: Type={Type}, Shape={Shape}, Intensity={Intensity}, Range={Range}, Color={Color}, ShadowType={ShadowType}, ShadowStrength={ShadowStrength}]"; } - /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> - public static LightSourceToy Create(Transform? parent = null, bool networkSpawn = true) - => Create(Vector3.zero, parent, networkSpawn); - - /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> - public static LightSourceToy Create(Vector3 position, Transform? parent = null, bool networkSpawn = true) - => Create(position, Quaternion.identity, parent, networkSpawn); - - /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> - public static LightSourceToy Create(Vector3 position, Quaternion rotation, Transform? parent = null, bool networkSpawn = true) - => Create(position, rotation, Vector3.one, parent, networkSpawn); - /// <summary> - /// Creates a new light source toy. - /// </summary> - /// <param name="position">The initial local position.</param> - /// <param name="rotation">The initial local rotation.</param> - /// <param name="scale">The initial local scale.</param> - /// <param name="parent">The parent transform.</param> - /// <param name="networkSpawn">Whether to spawn the toy on the client.</param> - /// <returns>The created light source toy.</returns> - public static LightSourceToy Create(Vector3 position, Quaternion rotation, Vector3 scale, Transform? parent = null, bool networkSpawn = true) - { - LightSourceToy toy = Get(Create<BaseLightSourceToy>(position, rotation, scale, parent)); - - if (networkSpawn) - toy.Spawn(); - - return toy; - } - - /// <summary> - /// Gets the light source toy wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseLightSourceToy"/> was not <see langword="null"/>. - /// </summary> - /// <param name="baseLightSourceToy">The <see cref="Base"/> of the light source toy.</param> - /// <returns>The requested light source toy or <see langword="null"/>.</returns> - [return: NotNullIfNotNull(nameof(baseLightSourceToy))] - public static LightSourceToy? Get(BaseLightSourceToy? baseLightSourceToy) - { - if (baseLightSourceToy == null) - return null; - - return Dictionary.TryGetValue(baseLightSourceToy, out LightSourceToy item) ? item : (LightSourceToy)CreateAdminToyWrapper(baseLightSourceToy); - } - - /// <summary> - /// Tries to get the light source toy wrapper from the <see cref="Dictionary"/>. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="baseLightSourceToy">The <see cref="Base"/> of the light source toy.</param> - /// <param name="lightSourceToy">The requested light source toy.</param> - /// <returns><see langword="True"/> if the light toy exists, otherwise <see langword="false"/>.</returns> - public static bool TryGet(BaseLightSourceToy? baseLightSourceToy, [NotNullWhen(true)] out LightSourceToy? lightSourceToy) + internal override void OnRemove() { - lightSourceToy = Get(baseLightSourceToy); - return lightSourceToy != null; + base.OnRemove(); + Dictionary.Remove(Base); } } From 28239ae5ed99c3072618897867c6715e47df1718 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:41:38 +0930 Subject: [PATCH 081/215] primitiveobject --- .../Wrappers/AdminToys/PrimitiveObjectToy.cs | 134 +++++++++--------- 1 file changed, 70 insertions(+), 64 deletions(-) diff --git a/LabApi/Features/Wrappers/AdminToys/PrimitiveObjectToy.cs b/LabApi/Features/Wrappers/AdminToys/PrimitiveObjectToy.cs index cfc78642..ba5c4fad 100644 --- a/LabApi/Features/Wrappers/AdminToys/PrimitiveObjectToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/PrimitiveObjectToy.cs @@ -14,33 +14,87 @@ public class PrimitiveObjectToy : AdminToy /// <summary> /// Contains all the primitive object toys, accessible through their <see cref="Base"/>. /// </summary> - public new static Dictionary<BasePrimitiveObjectToy, PrimitiveObjectToy> Dictionary { get; } = []; + public static new Dictionary<BasePrimitiveObjectToy, PrimitiveObjectToy> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="PrimitiveObjectToy"/>. /// </summary> - public new static IReadOnlyCollection<PrimitiveObjectToy> List => Dictionary.Values; + public static new IReadOnlyCollection<PrimitiveObjectToy> List => Dictionary.Values; + + /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> + public static PrimitiveObjectToy Create(Transform? parent = null, bool networkSpawn = true) + => Create(Vector3.zero, parent, networkSpawn); + + /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> + public static PrimitiveObjectToy Create(Vector3 position, Transform? parent = null, bool networkSpawn = true) + => Create(position, Quaternion.identity, parent, networkSpawn); + + /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> + public static PrimitiveObjectToy Create(Vector3 position, Quaternion rotation, Transform? parent = null, bool networkSpawn = true) + => Create(position, rotation, Vector3.one, parent, networkSpawn); + + /// <summary> + /// Creates a new primitive object toy. + /// </summary> + /// <param name="position">The initial local position.</param> + /// <param name="rotation">The initial local rotation.</param> + /// <param name="scale">The initial local scale.</param> + /// <param name="parent">The parent transform.</param> + /// <param name="networkSpawn">Whether to spawn the toy on the client.</param> + /// <returns>The created primitive object toy.</returns> + public static PrimitiveObjectToy Create(Vector3 position, Quaternion rotation, Vector3 scale, Transform? parent = null, bool networkSpawn = true) + { + PrimitiveObjectToy toy = Get(Create<BasePrimitiveObjectToy>(position, rotation, scale, parent)); + + if (networkSpawn) + { + toy.Spawn(); + } + + return toy; + } + + /// <summary> + /// Gets the primitive object toy wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BasePrimitiveObjectToy"/> was not <see langword="null"/>. + /// </summary> + /// <param name="primitiveObjectToy">The <see cref="Base"/> of the primitive object toy.</param> + /// <returns>The requested primitive object toy or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(primitiveObjectToy))] + public static PrimitiveObjectToy? Get(BasePrimitiveObjectToy? primitiveObjectToy) + { + if (primitiveObjectToy == null) + { + return null; + } + + return Dictionary.TryGetValue(primitiveObjectToy, out PrimitiveObjectToy item) ? item : (PrimitiveObjectToy)CreateAdminToyWrapper(primitiveObjectToy); + } + + /// <summary> + /// Tries to get the primitive object toy wrapper from the <see cref="Dictionary"/>. + /// </summary> + /// <param name="basePrimitiveObjectToy">The <see cref="Base"/> of the primitive object toy.</param> + /// <param name="primitiveObjectToy">The requested primitive object toy.</param> + /// <returns><see langword="True"/> if the primitive object exists, otherwise <see langword="false"/>.</returns> + public static bool TryGet(BasePrimitiveObjectToy? basePrimitiveObjectToy, [NotNullWhen(true)] out PrimitiveObjectToy? primitiveObjectToy) + { + primitiveObjectToy = Get(basePrimitiveObjectToy); + return primitiveObjectToy != null; + } /// <summary> /// An internal constructor to prevent external instantiation. /// </summary> /// <param name="basePrimitiveObjectToy">The base <see cref="BasePrimitiveObjectToy"/> object.</param> - internal PrimitiveObjectToy(BasePrimitiveObjectToy basePrimitiveObjectToy) + internal PrimitiveObjectToy(BasePrimitiveObjectToy basePrimitiveObjectToy) : base(basePrimitiveObjectToy) { Base = basePrimitiveObjectToy; if (CanCache) + { Dictionary.Add(basePrimitiveObjectToy, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -84,60 +138,12 @@ public override string ToString() return $"[PrimitiveObjectToy: Type={Type}, Color={Color}, Flags={Flags}]"; } - /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> - public static PrimitiveObjectToy Create(Transform? parent = null, bool networkSpawn = true) - => Create(Vector3.zero, parent, networkSpawn); - - /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> - public static PrimitiveObjectToy Create(Vector3 position, Transform? parent = null, bool networkSpawn = true) - => Create(position, Quaternion.identity, parent, networkSpawn); - - /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> - public static PrimitiveObjectToy Create(Vector3 position, Quaternion rotation, Transform? parent = null, bool networkSpawn = true) - => Create(position, rotation, Vector3.one, parent, networkSpawn); - /// <summary> - /// Creates a new primitive object toy. - /// </summary> - /// <param name="position">The initial local position.</param> - /// <param name="rotation">The initial local rotation.</param> - /// <param name="scale">The initial local scale.</param> - /// <param name="parent">The parent transform.</param> - /// <param name="networkSpawn">Whether to spawn the toy on the client.</param> - /// <returns>The created primitive object toy.</returns> - public static PrimitiveObjectToy Create(Vector3 position, Quaternion rotation, Vector3 scale, Transform? parent = null, bool networkSpawn = true) - { - PrimitiveObjectToy toy = Get(Create<BasePrimitiveObjectToy>(position, rotation, scale, parent)); - - if (networkSpawn) - toy.Spawn(); - - return toy; - } - - /// <summary> - /// Gets the primitive object toy wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BasePrimitiveObjectToy"/> was not <see langword="null"/>. - /// </summary> - /// <param name="primitiveObjectToy">The <see cref="Base"/> of the primitive object toy.</param> - /// <returns>The requested primitive object toy or <see langword="null"/>.</returns> - [return: NotNullIfNotNull(nameof(primitiveObjectToy))] - public static PrimitiveObjectToy? Get(BasePrimitiveObjectToy? primitiveObjectToy) - { - if (primitiveObjectToy == null) - return null; - - return Dictionary.TryGetValue(primitiveObjectToy, out PrimitiveObjectToy item) ? item : (PrimitiveObjectToy)CreateAdminToyWrapper(primitiveObjectToy); - } - - /// <summary> - /// Tries to get the primitive object toy wrapper from the <see cref="Dictionary"/>. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="basePrimitiveObjectToy">The <see cref="Base"/> of the primitive object toy.</param> - /// <param name="primitiveObjectToy">The requested primitive object toy.</param> - /// <returns><see langword="True"/> if the primitive object exists, otherwise <see langword="false"/>.</returns> - public static bool TryGet(BasePrimitiveObjectToy? basePrimitiveObjectToy, [NotNullWhen(true)] out PrimitiveObjectToy? primitiveObjectToy) + internal override void OnRemove() { - primitiveObjectToy = Get(basePrimitiveObjectToy); - return primitiveObjectToy != null; + base.OnRemove(); + Dictionary.Remove(Base); } } From fcc963dd3bb3b5e6c2d0dcfa42875913096419e0 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:41:45 +0930 Subject: [PATCH 082/215] shootingtarget --- .../Wrappers/AdminToys/ShootingTargetToy.cs | 102 +++++++++--------- 1 file changed, 54 insertions(+), 48 deletions(-) diff --git a/LabApi/Features/Wrappers/AdminToys/ShootingTargetToy.cs b/LabApi/Features/Wrappers/AdminToys/ShootingTargetToy.cs index 2fd18ac7..6f5281cc 100644 --- a/LabApi/Features/Wrappers/AdminToys/ShootingTargetToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/ShootingTargetToy.cs @@ -13,67 +13,25 @@ public class ShootingTargetToy : AdminToy /// <summary> /// Contains all the shooting target toys, accessible through their <see cref="Base"/>. /// </summary> - public new static Dictionary<ShootingTarget, ShootingTargetToy> Dictionary { get; } = []; + public static new Dictionary<ShootingTarget, ShootingTargetToy> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="ShootingTargetToy"/>. /// </summary> - public new static IReadOnlyCollection<ShootingTargetToy> List => Dictionary.Values; - - /// <summary> - /// An internal constructor to prevent external instantiation. - /// </summary> - /// <param name="shootingTarget">The base <see cref="ShootingTarget"/> object.</param> - internal ShootingTargetToy(ShootingTarget shootingTarget) - : base(shootingTarget) - { - Base = shootingTarget; - - if (CanCache) - Dictionary.Add(shootingTarget, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); - } - - /// <summary> - /// The <see cref="ShootingTarget"/> object. - /// </summary> - public new ShootingTarget Base { get; } - - /// <summary> - /// Gets or sets whether other players can see your interactions. - /// </summary> - public bool IsGlobal - { - get => Base.Network_syncMode; - set => Base.Network_syncMode = value; - } - - /// <inheritdoc /> - public override string ToString() - { - return $"[ShootingTargetToy: IsGlobal={IsGlobal}]"; - } + public static new IReadOnlyCollection<ShootingTargetToy> List => Dictionary.Values; /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> - // BUG: you can only spawn one of the shooting target types and you dont get to choose which. + // BUG: you can only spawn one of the shooting target types and you don't get to choose which. public static ShootingTargetToy Create(Transform? parent = null, bool networkSpawn = true) => Create(Vector3.zero, parent, networkSpawn); /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> - // BUG: you can only spawn one of the shooting target types and you dont get to choose which. + // BUG: you can only spawn one of the shooting target types and you don't get to choose which. public static ShootingTargetToy Create(Vector3 position, Transform? parent = null, bool networkSpawn = true) => Create(position, Quaternion.identity, parent, networkSpawn); /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> - // BUG: you can only spawn one of the shooting target types and you dont get to choose which. + // BUG: you can only spawn one of the shooting target types and you don't get to choose which. public static ShootingTargetToy Create(Vector3 position, Quaternion rotation, Transform? parent = null, bool networkSpawn = true) => Create(position, rotation, Vector3.one, parent, networkSpawn); @@ -86,13 +44,15 @@ public static ShootingTargetToy Create(Vector3 position, Quaternion rotation, Tr /// <param name="parent">The parent transform.</param> /// <param name="networkSpawn">Whether to spawn the toy on the client.</param> /// <returns>The created shooting target toy.</returns> - // BUG: you can only spawn one of the shooting target types and you dont get to choose which. + // BUG: you can only spawn one of the shooting target types and you don't get to choose which. public static ShootingTargetToy Create(Vector3 position, Quaternion rotation, Vector3 scale, Transform? parent = null, bool networkSpawn = true) { ShootingTargetToy toy = Get(Create<ShootingTarget>(position, rotation, scale, parent)); if (networkSpawn) + { toy.Spawn(); + } return toy; } @@ -106,7 +66,9 @@ public static ShootingTargetToy Create(Vector3 position, Quaternion rotation, Ve public static ShootingTargetToy? Get(ShootingTarget? shootingTarget) { if (shootingTarget == null) + { return null; + } return Dictionary.TryGetValue(shootingTarget, out ShootingTargetToy toy) ? toy : (ShootingTargetToy)CreateAdminToyWrapper(shootingTarget); } @@ -122,4 +84,48 @@ public static bool TryGet(ShootingTarget? shootingTarget, [NotNullWhen(true)] ou shootingTargetToy = Get(shootingTarget); return shootingTargetToy != null; } + + /// <summary> + /// An internal constructor to prevent external instantiation. + /// </summary> + /// <param name="shootingTarget">The base <see cref="ShootingTarget"/> object.</param> + internal ShootingTargetToy(ShootingTarget shootingTarget) + : base(shootingTarget) + { + Base = shootingTarget; + + if (CanCache) + { + Dictionary.Add(shootingTarget, this); + } + } + + /// <summary> + /// The <see cref="ShootingTarget"/> object. + /// </summary> + public new ShootingTarget Base { get; } + + /// <summary> + /// Gets or sets whether other players can see your interactions. + /// </summary> + public bool IsGlobal + { + get => Base.Network_syncMode; + set => Base.Network_syncMode = value; + } + + /// <inheritdoc /> + public override string ToString() + { + return $"[ShootingTargetToy: IsGlobal={IsGlobal}]"; + } + + /// <summary> + /// An internal method to remove itself from the cache when the base object is destroyed. + /// </summary> + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); + } } From 6ad30df968a5b2241c38f56e30681790749834ac Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:41:55 +0930 Subject: [PATCH 083/215] spawnablecullingparent --- .../AdminToys/SpawnableCullingParent.cs | 164 ++++++++++-------- 1 file changed, 87 insertions(+), 77 deletions(-) diff --git a/LabApi/Features/Wrappers/AdminToys/SpawnableCullingParent.cs b/LabApi/Features/Wrappers/AdminToys/SpawnableCullingParent.cs index 078fd6d2..e96c08d4 100644 --- a/LabApi/Features/Wrappers/AdminToys/SpawnableCullingParent.cs +++ b/LabApi/Features/Wrappers/AdminToys/SpawnableCullingParent.cs @@ -1,11 +1,11 @@ -using static LabApi.Features.Wrappers.AdminToy; -using AdminToys; +using AdminToys; +using Generators; using Mirror; using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using UnityEngine; -using Generators; +using static LabApi.Features.Wrappers.AdminToy; using BaseCullingParent = AdminToys.SpawnableCullingParent; using Logger = LabApi.Features.Console.Logger; @@ -21,16 +21,6 @@ namespace LabApi.Features.Wrappers; /// </remarks> public class SpawnableCullingParent { - /// <summary> - /// Initializes the <see cref="SpawnableCullingParent"/> class. - /// </summary> - [InitializeWrapper] - internal static void Initialize() - { - BaseCullingParent.OnAdded += AddCullableParent; - BaseCullingParent.OnRemoved += RemoveCullableParent; - } - /// <summary> /// Contains all the cached spawnable culling parents, accessible through their <see cref="Base"/>. /// </summary> @@ -41,67 +31,6 @@ internal static void Initialize() /// </summary> public static IReadOnlyCollection<SpawnableCullingParent> List => Dictionary.Values; - /// <summary> - /// A protected constructor to prevent external instantiation. - /// </summary> - /// <param name="cullingBase">The base object.</param> - protected SpawnableCullingParent(BaseCullingParent cullingBase) - { - Dictionary.Add(cullingBase, this); - Base = cullingBase; - } - - /// <summary> - /// The <see cref="BaseCullingParent">base</see> object. - /// </summary> - public BaseCullingParent Base { get; } - - /// <summary> - /// The <see cref="UnityEngine.GameObject"/>. - /// </summary> - public GameObject GameObject => Base.gameObject; - - /// <summary> - /// The culling parent's <see cref="UnityEngine.Transform"/>. - /// </summary> - public Transform Transform => Base.transform; - - /// <summary> - /// Whether the <see cref="Base"/> was destroyed. - /// </summary> - /// <remarks> - /// A destroyed object may not be used. - /// </remarks> - public bool IsDestroyed => Base == null; - - /// <summary> - /// Gets or sets the position of the culling parent. - /// </summary> - public Vector3 Position - { - get => Base.BoundsPosition; - set => Base.BoundsPosition = value; - } - - /// <summary> - /// Gets or sets the culling bound size of the culling parent. - /// </summary> - public Vector3 Size - { - get => Base.BoundsSize; - set => Base.BoundsSize = value; - } - - /// <summary> - /// Spawns the culling parent on client. - /// </summary> - public void Spawn() => NetworkServer.Spawn(GameObject); - - /// <summary> - /// Destroys the culling parent on server and client. - /// </summary> - public void Destroy() => NetworkServer.Destroy(GameObject); - /// <summary> /// Instantiates a new culling parent object. /// </summary> @@ -111,27 +40,33 @@ public Vector3 Size /// <returns>The instantiated culling parent.</returns> public static SpawnableCullingParent Create(Vector3 position, Vector3 size, bool networkSpawn = true) { - if (PrefabCache<BaseCullingParent>.prefab == null) + if (PrefabCache<BaseCullingParent>.Prefab == null) { BaseCullingParent? found = null; foreach (GameObject prefab in NetworkClient.prefabs.Values) { if (prefab.TryGetComponent(out found)) + { break; + } } if (found == null) + { throw new InvalidOperationException($"No prefab in NetworkClient.prefabs has component type {typeof(BaseCullingParent)}"); + } - PrefabCache<BaseCullingParent>.prefab = found; + PrefabCache<BaseCullingParent>.Prefab = found; } - BaseCullingParent instance = UnityEngine.Object.Instantiate(PrefabCache<BaseCullingParent>.prefab); + BaseCullingParent instance = UnityEngine.Object.Instantiate(PrefabCache<BaseCullingParent>.Prefab); instance.BoundsPosition = position; instance.BoundsSize = size; if (networkSpawn) + { NetworkServer.Spawn(instance.gameObject); + } return Get(instance); } @@ -145,7 +80,9 @@ public static SpawnableCullingParent Create(Vector3 position, Vector3 size, bool public static SpawnableCullingParent? Get(BaseCullingParent? cullingBase) { if (cullingBase == null) + { return null; + } return Dictionary.TryGetValue(cullingBase, out SpawnableCullingParent item) ? item : new SpawnableCullingParent(cullingBase); } @@ -162,6 +99,16 @@ public static bool TryGet(BaseCullingParent? adminToyBase, [NotNullWhen(true)] o return adminToy != null; } + /// <summary> + /// Initializes the <see cref="SpawnableCullingParent"/> class. + /// </summary> + [InitializeWrapper] + internal static void Initialize() + { + BaseCullingParent.OnAdded += AddCullableParent; + BaseCullingParent.OnRemoved += RemoveCullableParent; + } + /// <summary> /// A private method to handle the creation of new cullable parents on the server. /// </summary> @@ -171,7 +118,9 @@ private static void AddCullableParent(BaseCullingParent cullableParent) try { if (!Dictionary.ContainsKey(cullableParent)) + { _ = new SpawnableCullingParent(cullableParent); + } } catch (Exception e) { @@ -194,4 +143,65 @@ private static void RemoveCullableParent(BaseCullingParent cullableParent) Logger.InternalError($"Failed to handle cullable parent destruction with error: {e}"); } } + + /// <summary> + /// A protected constructor to prevent external instantiation. + /// </summary> + /// <param name="cullingBase">The base object.</param> + protected SpawnableCullingParent(BaseCullingParent cullingBase) + { + Dictionary.Add(cullingBase, this); + Base = cullingBase; + } + + /// <summary> + /// The <see cref="BaseCullingParent">base</see> object. + /// </summary> + public BaseCullingParent Base { get; } + + /// <summary> + /// The <see cref="UnityEngine.GameObject"/>. + /// </summary> + public GameObject GameObject => Base.gameObject; + + /// <summary> + /// The culling parent's <see cref="UnityEngine.Transform"/>. + /// </summary> + public Transform Transform => Base.transform; + + /// <summary> + /// Whether the <see cref="Base"/> was destroyed. + /// </summary> + /// <remarks> + /// A destroyed object may not be used. + /// </remarks> + public bool IsDestroyed => Base == null; + + /// <summary> + /// Gets or sets the position of the culling parent. + /// </summary> + public Vector3 Position + { + get => Base.BoundsPosition; + set => Base.BoundsPosition = value; + } + + /// <summary> + /// Gets or sets the culling bound size of the culling parent. + /// </summary> + public Vector3 Size + { + get => Base.BoundsSize; + set => Base.BoundsSize = value; + } + + /// <summary> + /// Spawns the culling parent on client. + /// </summary> + public void Spawn() => NetworkServer.Spawn(GameObject); + + /// <summary> + /// Destroys the culling parent on server and client. + /// </summary> + public void Destroy() => NetworkServer.Destroy(GameObject); } \ No newline at end of file From 382b4e399be102240759e1c49a28133491198b20 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:42:02 +0930 Subject: [PATCH 084/215] speaker --- .../Features/Wrappers/AdminToys/SpeakerToy.cs | 246 +++++++++--------- 1 file changed, 126 insertions(+), 120 deletions(-) diff --git a/LabApi/Features/Wrappers/AdminToys/SpeakerToy.cs b/LabApi/Features/Wrappers/AdminToys/SpeakerToy.cs index ccd557a1..9abdb733 100644 --- a/LabApi/Features/Wrappers/AdminToys/SpeakerToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/SpeakerToy.cs @@ -10,42 +10,149 @@ namespace LabApi.Features.Wrappers; /// <summary> -/// Wrapper for the <see cref="BaseSpeakerToy"/> class +/// Wrapper for the <see cref="BaseSpeakerToy"/> class. /// </summary> public class SpeakerToy : AdminToy { + private static readonly Dictionary<byte, AudioTransmitter> TransmitterByControllerId = []; + /// <summary> /// Contains all the speaker toys, accessible through their <see cref="Base"/>. /// </summary> - public new static Dictionary<BaseSpeakerToy, SpeakerToy> Dictionary { get; } = []; + public static new Dictionary<BaseSpeakerToy, SpeakerToy> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="SpeakerToy"/>. /// </summary> - public new static IReadOnlyCollection<SpeakerToy> List => Dictionary.Values; + public static new IReadOnlyCollection<SpeakerToy> List => Dictionary.Values; - private static readonly Dictionary<byte, AudioTransmitter> TransmitterByControllerId = []; + /// <summary> + /// Plays the PCM samples on the current controller. + /// </summary> + /// <remarks> + /// Samples are played at a sample rate of <see cref="AudioTransmitter.SampleRate"/>, mono channel (non interleaved data) with ranges from -1.0f to 1.0f. + /// </remarks> + /// <param name="controllerId">The Id of the controller to play audio on.</param> + /// <param name="samples">The PCM samples.</param> + /// <param name="queue">Whether to queue the audio if audio is already playing, otherwise overrides the current audio.</param> + /// <param name="loop"> + /// Whether to loop this clip. + /// Loop ends if another clip is played either immediately if not queued or at the end of the loop if next clip was queued. + /// </param> + public static void Play(byte controllerId, float[] samples, bool queue = true, bool loop = false) + => GetTransmitter(controllerId).Play(samples, queue, loop); + + /// <inheritdoc cref="AudioTransmitter.Pause"/> + /// <param name="controllerId">The Id of the controller to play audio on.</param> + public static void Pause(byte controllerId) => GetTransmitter(controllerId).Pause(); + + /// <inheritdoc cref="AudioTransmitter.Resume"/> + /// <param name="controllerId">The Id of the controller to play audio on.</param> + public static void Resume(byte controllerId) => GetTransmitter(controllerId).Resume(); + + /// <summary> + /// Skips the current or queued clips. + /// Includes the current clip. + /// </summary> + /// <param name="controllerId">The Id of the controller to play audio on.</param> + /// <param name="count">The number of queued audios clips to skip.</param> + public static void Skip(byte controllerId, int count) => GetTransmitter(controllerId).Skip(count); + + /// <inheritdoc cref="AudioTransmitter.Stop"/> + /// <param name="controllerId">The Id of the controller to play audio on.</param> + public static void Stop(byte controllerId) => GetTransmitter(controllerId).Stop(); + + /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> + public static SpeakerToy Create(Transform? parent = null, bool networkSpawn = true) + => Create(Vector3.zero, parent, networkSpawn); + + /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> + public static SpeakerToy Create(Vector3 position, Transform? parent = null, bool networkSpawn = true) + => Create(position, Quaternion.identity, parent, networkSpawn); + + /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> + public static SpeakerToy Create(Vector3 position, Quaternion rotation, Transform? parent = null, bool networkSpawn = true) + => Create(position, rotation, Vector3.one, parent, networkSpawn); + + /// <summary> + /// Creates a new speaker toy. + /// </summary> + /// <param name="position">The initial local position.</param> + /// <param name="rotation">The initial local rotation.</param> + /// <param name="scale">The initial local scale.</param> + /// <param name="parent">The parent transform.</param> + /// <param name="networkSpawn">Whether to spawn the toy on the client.</param> + /// <returns>The created speaker toy.</returns> + public static SpeakerToy Create(Vector3 position, Quaternion rotation, Vector3 scale, Transform? parent = null, bool networkSpawn = true) + { + SpeakerToy toy = Get(Create<BaseSpeakerToy>(position, rotation, scale, parent)); + + if (networkSpawn) + { + toy.Spawn(); + } + + return toy; + } + + /// <summary> + /// Gets the speaker toy wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseSpeakerToy"/> was not <see langword="null"/>. + /// </summary> + /// <param name="baseSpeakerToy">The <see cref="Base"/> of the speaker toy.</param> + /// <returns>The requested speaker toy or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(baseSpeakerToy))] + public static SpeakerToy? Get(BaseSpeakerToy? baseSpeakerToy) + { + if (baseSpeakerToy == null) + { + return null; + } + + return Dictionary.TryGetValue(baseSpeakerToy, out SpeakerToy toy) ? toy : (SpeakerToy)CreateAdminToyWrapper(baseSpeakerToy); + } + + /// <summary> + /// Tries to get the speaker toy wrapper from the <see cref="Dictionary"/>. + /// </summary> + /// <param name="baseSpeakerToy">The <see cref="Base"/> of the speaker toy.</param> + /// <param name="speakerToy">The requested speaker toy.</param> + /// <returns><see langword="True"/> if the speaker exists, otherwise <see langword="false"/>.</returns> + public static bool TryGet(BaseSpeakerToy? baseSpeakerToy, [NotNullWhen(true)] out SpeakerToy? speakerToy) + { + speakerToy = Get(baseSpeakerToy); + return speakerToy != null; + } + + /// <summary> + /// Gets the <see cref="AudioTransmitter"/> for the <see cref="ControllerId"/>. + /// If one does not exists, a new one is created for the id. + /// </summary> + /// <param name="controllerId">The <see cref="ControllerId"/> for the transmitter.</param> + /// <returns>Cached transmitter.</returns> + public static AudioTransmitter GetTransmitter(byte controllerId) + { + if (!TransmitterByControllerId.TryGetValue(controllerId, out AudioTransmitter transmitter)) + { + transmitter = new(controllerId); + TransmitterByControllerId.Add(controllerId, transmitter); + } + + return transmitter; + } /// <summary> /// An internal constructor to prevent external instantiation. /// </summary> /// <param name="baseSpeakerToy">The base <see cref="BaseSpeakerToy"/> object.</param> - internal SpeakerToy(BaseSpeakerToy baseSpeakerToy) + internal SpeakerToy(BaseSpeakerToy baseSpeakerToy) : base(baseSpeakerToy) { Base = baseSpeakerToy; if (CanCache) + { Dictionary.Add(baseSpeakerToy, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -180,7 +287,7 @@ public Func<Player, bool>? ValidPlayers } /// <summary> - /// Gets the audio transmitter for this speakers <see cref="ControllerId"/>. + /// Gets the audio transmitter for this speakers <see cref="ControllerId"/>. /// </summary> /// <remarks> /// Speakers can share <see cref="AudioTransmitter"/> instances if they have the same <see cref="ControllerId"/>. @@ -210,112 +317,11 @@ public override string ToString() } /// <summary> - /// Plays the PCM samples on the current controller. - /// </summary> - /// <remarks> - /// Samples are played at a sample rate of <see cref="AudioTransmitter.SampleRate"/>, mono channel (non interleaved data) with ranges from -1.0f to 1.0f. - /// </remarks> - /// <param name="controllerId">The Id of the controller to play audio on.</param> - /// <param name="samples">The PCM samples.</param> - /// <param name="queue">Whether to queue the audio if audio is already playing, otherwise overrides the current audio.</param> - /// <param name="loop"> - /// Whether to loop this clip. - /// Loop ends if another clip is played either immediately if not queued or at the end of the loop if next clip was queued. - /// </param> - public static void Play(byte controllerId, float[] samples, bool queue = true, bool loop = false) - => GetTransmitter(controllerId).Play(samples, queue, loop); - - /// <inheritdoc cref="AudioTransmitter.Pause"/> - /// <param name="controllerId">The Id of the controller to play audio on.</param> - public static void Pause(byte controllerId) => GetTransmitter(controllerId).Pause(); - - /// <inheritdoc cref="AudioTransmitter.Resume"/> - /// <param name="controllerId">The Id of the controller to play audio on.</param> - public static void Resume(byte controllerId) => GetTransmitter(controllerId).Resume(); - - /// <summary> - /// Skips the current or queued clips. - /// Includes the current clip. - /// </summary> - /// <param name="controllerId">The Id of the controller to play audio on.</param> - /// <param name="count">The number of queued audios clips to skip.</param> - public static void Skip(byte controllerId, int count) => GetTransmitter(controllerId).Skip(count); - - /// <inheritdoc cref="AudioTransmitter.Stop"/> - /// <param name="controllerId">The Id of the controller to play audio on.</param> - public static void Stop(byte controllerId) => GetTransmitter(controllerId).Stop(); - - /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> - public static SpeakerToy Create(Transform? parent = null, bool networkSpawn = true) - => Create(Vector3.zero, parent, networkSpawn); - - /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> - public static SpeakerToy Create(Vector3 position, Transform? parent = null, bool networkSpawn = true) - => Create(position, Quaternion.identity, parent, networkSpawn); - - /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> - public static SpeakerToy Create(Vector3 position, Quaternion rotation, Transform? parent = null, bool networkSpawn = true) - => Create(position, rotation, Vector3.one, parent, networkSpawn); - - /// <summary> - /// Creates a new speaker toy. - /// </summary> - /// <param name="position">The initial local position.</param> - /// <param name="rotation">The initial local rotation.</param> - /// <param name="scale">The initial local scale.</param> - /// <param name="parent">The parent transform.</param> - /// <param name="networkSpawn">Whether to spawn the toy on the client.</param> - /// <returns>The created speaker toy.</returns> - public static SpeakerToy Create(Vector3 position, Quaternion rotation, Vector3 scale, Transform? parent = null, bool networkSpawn = true) - { - SpeakerToy toy = Get(Create<BaseSpeakerToy>(position, rotation, scale, parent)); - - if (networkSpawn) - toy.Spawn(); - - return toy; - } - - /// <summary> - /// Gets the speaker toy wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseSpeakerToy"/> was not <see langword="null"/>. - /// </summary> - /// <param name="baseSpeakerToy">The <see cref="Base"/> of the speaker toy.</param> - /// <returns>The requested speaker toy or <see langword="null"/>.</returns> - [return: NotNullIfNotNull(nameof(baseSpeakerToy))] - public static SpeakerToy? Get(BaseSpeakerToy? baseSpeakerToy) - { - if (baseSpeakerToy == null) - return null; - - return Dictionary.TryGetValue(baseSpeakerToy, out SpeakerToy toy) ? toy : (SpeakerToy)CreateAdminToyWrapper(baseSpeakerToy); - } - - /// <summary> - /// Tries to get the speaker toy wrapper from the <see cref="Dictionary"/>. - /// </summary> - /// <param name="baseSpeakerToy">The <see cref="Base"/> of the speaker toy.</param> - /// <param name="speakerToy">The requested speaker toy.</param> - /// <returns><see langword="True"/> if the speaker exists, otherwise <see langword="false"/>.</returns> - public static bool TryGet(BaseSpeakerToy? baseSpeakerToy, [NotNullWhen(true)] out SpeakerToy? speakerToy) - { - speakerToy = Get(baseSpeakerToy); - return speakerToy != null; - } - - /// <summary> - /// Gets the <see cref="AudioTransmitter"/> for the <see cref="ControllerId"/>. - /// If one does not exists, a new one is created for the id. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="controllerId">The <see cref="ControllerId"/> for the transmitter.</param> - /// <returns>Cached transmitter.</returns> - public static AudioTransmitter GetTransmitter(byte controllerId) + internal override void OnRemove() { - if (!TransmitterByControllerId.TryGetValue(controllerId, out AudioTransmitter transmitter)) - { - transmitter = new(controllerId); - TransmitterByControllerId.Add(controllerId, transmitter); - } - - return transmitter; + base.OnRemove(); + Dictionary.Remove(Base); } } From 6c60d2726f4a2449defe385328d5bf28e438d33a Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:42:07 +0930 Subject: [PATCH 085/215] text --- LabApi/Features/Wrappers/AdminToys/TextToy.cs | 116 +++++++++--------- 1 file changed, 61 insertions(+), 55 deletions(-) diff --git a/LabApi/Features/Wrappers/AdminToys/TextToy.cs b/LabApi/Features/Wrappers/AdminToys/TextToy.cs index 0ae7714e..0e628b4d 100644 --- a/LabApi/Features/Wrappers/AdminToys/TextToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/TextToy.cs @@ -8,71 +8,19 @@ namespace LabApi.Features.Wrappers; /// <summary> /// The wrapper for the <see cref="BaseTextToy"/> class. <br/> -/// Toy with changable text and formatting arguments. +/// Toy with changeable text and formatting arguments. /// </summary> public class TextToy : AdminToy { /// <summary> /// Contains all the text toys, accessible through their <see cref="Base"/>. /// </summary> - public new static Dictionary<BaseTextToy, TextToy> Dictionary { get; } = []; + public static new Dictionary<BaseTextToy, TextToy> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="TextToy"/>. /// </summary> - public new static IReadOnlyCollection<TextToy> List => Dictionary.Values; - - /// <summary> - /// An internal constructor to prevent external instantiation. - /// </summary> - /// <param name="baseToy">The base <see cref="BaseTextToy"/> object.</param> - internal TextToy(BaseTextToy baseToy) - : base(baseToy) - { - Base = baseToy; - - if (CanCache) - Dictionary.Add(baseToy, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); - } - - /// <summary> - /// The <see cref="BaseTextToy"/> object. - /// </summary> - public new BaseTextToy Base { get; } - - /// <summary> - /// Gets or sets the base text format used when formatting the final text string.<br/> - /// Text can be formatted and arguments are replaced with <see cref="Arguments"/>. - /// </summary> - public string TextFormat - { - get => Base.TextFormat; - set => Base.TextFormat = value; - } - - /// <summary> - /// Gets or sets the size of text display used by TMP. - /// </summary> - public Vector2 DisplaySize - { - get => Base.DisplaySize; - set => Base.DisplaySize = value; - } - - /// <summary> - /// Gets the arguments used while formatting the <see cref="TextFormat"/>.<br/> - /// Missing arguments for <see cref="TextFormat"/> are not replaced and any extra arguments are ignored. - /// </summary> - public SyncList<string> Arguments => Base.Arguments; + public static new IReadOnlyCollection<TextToy> List => Dictionary.Values; /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> public static TextToy Create(Transform? parent = null, bool networkSpawn = true) @@ -100,7 +48,9 @@ public static TextToy Create(Vector3 position, Quaternion rotation, Vector3 scal TextToy toy = Get(Create<BaseTextToy>(position, rotation, scale, parent)); if (networkSpawn) + { toy.Spawn(); + } return toy; } @@ -114,7 +64,9 @@ public static TextToy Create(Vector3 position, Quaternion rotation, Vector3 scal public static TextToy? Get(BaseTextToy? baseTextToy) { if (baseTextToy == null) + { return null; + } return Dictionary.TryGetValue(baseTextToy, out TextToy item) ? item : (TextToy)CreateAdminToyWrapper(baseTextToy); } @@ -130,4 +82,58 @@ public static bool TryGet(BaseTextToy? baseTextToy, [NotNullWhen(true)] out Text textToy = Get(baseTextToy); return textToy != null; } + + /// <summary> + /// An internal constructor to prevent external instantiation. + /// </summary> + /// <param name="baseToy">The base <see cref="BaseTextToy"/> object.</param> + internal TextToy(BaseTextToy baseToy) + : base(baseToy) + { + Base = baseToy; + + if (CanCache) + { + Dictionary.Add(baseToy, this); + } + } + + /// <summary> + /// The <see cref="BaseTextToy"/> object. + /// </summary> + public new BaseTextToy Base { get; } + + /// <summary> + /// Gets or sets the base text format used when formatting the final text string.<br/> + /// Text can be formatted and arguments are replaced with <see cref="Arguments"/>. + /// </summary> + public string TextFormat + { + get => Base.TextFormat; + set => Base.TextFormat = value; + } + + /// <summary> + /// Gets or sets the size of text display used by TMP. + /// </summary> + public Vector2 DisplaySize + { + get => Base.DisplaySize; + set => Base.DisplaySize = value; + } + + /// <summary> + /// Gets the arguments used while formatting the <see cref="TextFormat"/>.<br/> + /// Missing arguments for <see cref="TextFormat"/> are not replaced and any extra arguments are ignored. + /// </summary> + public SyncList<string> Arguments => Base.Arguments; + + /// <summary> + /// An internal method to remove itself from the cache when the base object is destroyed. + /// </summary> + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); + } } From 6674574a897c2e652e1466078eba5d269d68369c Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:42:14 +0930 Subject: [PATCH 086/215] waypoint --- .../Wrappers/AdminToys/WaypointToy.cs | 117 +++++++++--------- 1 file changed, 60 insertions(+), 57 deletions(-) diff --git a/LabApi/Features/Wrappers/AdminToys/WaypointToy.cs b/LabApi/Features/Wrappers/AdminToys/WaypointToy.cs index 9c5e0fa7..93dfbe7b 100644 --- a/LabApi/Features/Wrappers/AdminToys/WaypointToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/WaypointToy.cs @@ -1,5 +1,4 @@ -using LabApi.Features.Wrappers; -using System.Collections.Generic; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using UnityEngine; using BaseWaypointToy = AdminToys.WaypointToy; @@ -14,65 +13,12 @@ public class WaypointToy : AdminToy /// <summary> /// Contains all the waypoint toys, accessible through their <see cref="Base"/>. /// </summary> - public new static Dictionary<BaseWaypointToy, WaypointToy> Dictionary { get; } = []; + public static new Dictionary<BaseWaypointToy, WaypointToy> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="WaypointToy"/>. /// </summary> - public new static IReadOnlyCollection<WaypointToy> List => Dictionary.Values; - - /// <summary> - /// The <see cref="BaseWaypointToy"/> object. - /// </summary> - public new BaseWaypointToy Base { get; } - - /// <summary> - /// Gets or sets whether to visualize the waypoint's maximum bounds. - /// </summary> - public bool VisualizeBounds - { - get => Base.VisualizeBounds; - set => Base.NetworkVisualizeBounds = value; - } - - /// <summary> - /// Gets or sets how many meters to bias towards this waypoint. - /// </summary> - /// <remarks> - /// The closest waypoint is determined by its square distance. - /// When set this takes away <c>(Priority * Priority)</c> from the sqr distance. - /// </remarks> - public float PriorityBias - { - get => Base.Priority; - set => Base.NetworkPriority = value; - } - - /// <summary> - /// An internal constructor to prevent external instantiation. - /// </summary> - /// <param name="baseWaypointToy">The base <see cref="BaseWaypointToy"/> object.</param> - internal WaypointToy(BaseWaypointToy baseWaypointToy) - : base(baseWaypointToy) - { - Dictionary.Add(baseWaypointToy, this); - Base = baseWaypointToy; - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); - } - - /// <inheritdoc /> - public override string ToString() - { - return $"[WaypointToy: Position{Position}, VisualizeBounds:{VisualizeBounds}, PriorityBias:{PriorityBias}]"; - } + public static new IReadOnlyCollection<WaypointToy> List => Dictionary.Values; /// <inheritdoc cref="Create(Vector3, Quaternion, Vector3, Transform?, bool)"/> public static WaypointToy Create(Transform? parent = null, bool networkSpawn = true) @@ -100,7 +46,9 @@ public static WaypointToy Create(Vector3 position, Quaternion rotation, Vector3 WaypointToy toy = Get(Create<BaseWaypointToy>(position, rotation, scale, parent)); if (networkSpawn) + { toy.Spawn(); + } return toy; } @@ -114,7 +62,9 @@ public static WaypointToy Create(Vector3 position, Quaternion rotation, Vector3 public static WaypointToy? Get(BaseWaypointToy? baseWaypointToy) { if (baseWaypointToy == null) + { return null; + } return Dictionary.TryGetValue(baseWaypointToy, out WaypointToy item) ? item : (WaypointToy)CreateAdminToyWrapper(baseWaypointToy); } @@ -130,4 +80,57 @@ public static bool TryGet(BaseWaypointToy? baseWaypointToy, [NotNullWhen(true)] waypointToy = Get(baseWaypointToy); return waypointToy != null; } + + /// <summary> + /// An internal constructor to prevent external instantiation. + /// </summary> + /// <param name="baseWaypointToy">The base <see cref="BaseWaypointToy"/> object.</param> + internal WaypointToy(BaseWaypointToy baseWaypointToy) + : base(baseWaypointToy) + { + Dictionary.Add(baseWaypointToy, this); + Base = baseWaypointToy; + } + + /// <summary> + /// The <see cref="BaseWaypointToy"/> object. + /// </summary> + public new BaseWaypointToy Base { get; } + + /// <summary> + /// Gets or sets whether to visualize the waypoint's maximum bounds. + /// </summary> + public bool VisualizeBounds + { + get => Base.VisualizeBounds; + set => Base.NetworkVisualizeBounds = value; + } + + /// <summary> + /// Gets or sets how many meters to bias towards this waypoint. + /// </summary> + /// <remarks> + /// The closest waypoint is determined by its square distance. + /// When set this takes away <c>(Priority * Priority)</c> from the sqr distance. + /// </remarks> + public float PriorityBias + { + get => Base.Priority; + set => Base.NetworkPriority = value; + } + + /// <inheritdoc /> + public override string ToString() + { + return $"[WaypointToy: Position{Position}, VisualizeBounds:{VisualizeBounds}, PriorityBias:{PriorityBias}]"; + } + + /// <summary> + /// An internal method to remove itself from the cache when the base object is destroyed. + /// </summary> + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); + } } From 5388e785da2da938f6b0be5e080541443e61f7cb Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:42:21 +0930 Subject: [PATCH 087/215] breakable --- .../Wrappers/Facility/Doors/BreakableDoor.cs | 52 +++++++++++-------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Doors/BreakableDoor.cs b/LabApi/Features/Wrappers/Facility/Doors/BreakableDoor.cs index 08bbba34..47066280 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/BreakableDoor.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/BreakableDoor.cs @@ -13,12 +13,33 @@ public class BreakableDoor : Door /// <summary> /// Contains all the cached <see cref="BreakableDoor"/> instances, accessible through their <see cref="BaseBreakableDoor"/>. /// </summary> - public new static Dictionary<BaseBreakableDoor, BreakableDoor> Dictionary { get; } = []; + public static new Dictionary<BaseBreakableDoor, BreakableDoor> Dictionary { get; } = []; /// <summary> /// A reference to all <see cref="BreakableDoor"/> instances currently in the game. /// </summary> - public new static IReadOnlyCollection<BreakableDoor> List => Dictionary.Values; + public static new IReadOnlyCollection<BreakableDoor> List => Dictionary.Values; + + /// <summary> + /// Gets the <see cref="BreakableDoor"/> wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist. + /// </summary> + /// <param name="baseBreakableDoor">The <see cref="BaseBreakableDoor"/> of the door.</param> + /// <returns>The requested door wrapper or null if the input was null.</returns> + [return: NotNullIfNotNull(nameof(baseBreakableDoor))] + public static BreakableDoor? Get(BaseBreakableDoor? baseBreakableDoor) + { + if (baseBreakableDoor == null) + { + return null; + } + + if (Dictionary.TryGetValue(baseBreakableDoor, out BreakableDoor door)) + { + return door; + } + + return (BreakableDoor)CreateDoorWrapper(baseBreakableDoor); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -30,16 +51,9 @@ internal BreakableDoor(BaseBreakableDoor baseBreakableDoor) Base = baseBreakableDoor; if (CanCache) + { Dictionary.Add(baseBreakableDoor, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -120,19 +134,11 @@ public bool TryBreak(DoorDamageType type = DoorDamageType.ServerCommand) public bool TryRepair() => Base.ServerRepair(); /// <summary> - /// Gets the <see cref="BreakableDoor"/> wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="baseBreakableDoor">The <see cref="BaseBreakableDoor"/> of the door.</param> - /// <returns>The requested door wrapper or null if the input was null.</returns> - [return: NotNullIfNotNull(nameof(baseBreakableDoor))] - public static BreakableDoor? Get(BaseBreakableDoor? baseBreakableDoor) + internal override void OnRemove() { - if (baseBreakableDoor == null) - return null; - - if (Dictionary.TryGetValue(baseBreakableDoor, out BreakableDoor door)) - return door; - - return (BreakableDoor)CreateDoorWrapper(baseBreakableDoor); + base.OnRemove(); + Dictionary.Remove(Base); } } From 10ccf6baaeff5251e4c37e9605672b011e024ef4 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:42:27 +0930 Subject: [PATCH 088/215] bulkhead --- .../Wrappers/Facility/Doors/BulkheadDoor.cs | 54 +++++++++++-------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Doors/BulkheadDoor.cs b/LabApi/Features/Wrappers/Facility/Doors/BulkheadDoor.cs index e85765de..e4d5edb3 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/BulkheadDoor.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/BulkheadDoor.cs @@ -13,12 +13,33 @@ public class BulkheadDoor : Gate /// <summary> /// Contains all the cached <see cref="BulkheadDoor"/> instances, accessible through their <see cref="PryableDoor"/>. /// </summary> - public new static Dictionary<PryableDoor, BulkheadDoor> Dictionary { get; } = []; + public static new Dictionary<PryableDoor, BulkheadDoor> Dictionary { get; } = []; /// <summary> /// A reference to all <see cref="BulkheadDoor"/> instances currently in the game. /// </summary> - public new static IReadOnlyCollection<BulkheadDoor> List => Dictionary.Values; + public static new IReadOnlyCollection<BulkheadDoor> List => Dictionary.Values; + + /// <summary> + /// Gets the <see cref="BulkheadDoor"/> wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist. + /// </summary> + /// <param name="pryableDoor">The <see cref="PryableDoor"/> of the door.</param> + /// <returns>The requested door wrapper or null if the input was null.</returns> + [return: NotNullIfNotNull(nameof(pryableDoor))] + public static new BulkheadDoor? Get(PryableDoor? pryableDoor) + { + if (pryableDoor == null) + { + return null; + } + + if (Dictionary.TryGetValue(pryableDoor, out BulkheadDoor door)) + { + return door; + } + + return (BulkheadDoor)CreateDoorWrapper(pryableDoor); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -30,19 +51,14 @@ internal BulkheadDoor(PryableDoor pryableDoor) Base = pryableDoor; DoorCrusherExtension extension = pryableDoor.gameObject.GetComponent<DoorCrusherExtension>(); if (extension != null) + { Crusher = new DoorCrusher(extension); + } if (CanCache) + { Dictionary.Add(pryableDoor, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -59,19 +75,11 @@ internal override void OnRemove() public DoorCrusher? Crusher { get; } /// <summary> - /// Gets the <see cref="BulkheadDoor"/> wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="pryableDoor">The <see cref="PryableDoor"/> of the door.</param> - /// <returns>The requested door wrapper or null if the input was null.</returns> - [return: NotNullIfNotNull(nameof(pryableDoor))] - public new static BulkheadDoor? Get(PryableDoor? pryableDoor) + internal override void OnRemove() { - if (pryableDoor == null) - return null; - - if (Dictionary.TryGetValue(pryableDoor, out BulkheadDoor door)) - return door; - - return (BulkheadDoor)CreateDoorWrapper(pryableDoor); + base.OnRemove(); + Dictionary.Remove(Base); } } From d535934da9d02b693d6bc3659dc4770efef80a7c Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:42:34 +0930 Subject: [PATCH 089/215] checkpoint --- .../Wrappers/Facility/Doors/CheckpointDoor.cs | 54 +++++++++++-------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Doors/CheckpointDoor.cs b/LabApi/Features/Wrappers/Facility/Doors/CheckpointDoor.cs index ad970c42..d2f58955 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/CheckpointDoor.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/CheckpointDoor.cs @@ -15,12 +15,33 @@ public class CheckpointDoor : Door /// <summary> /// Contains all the cached <see cref="CheckpointDoor"/> instances, accessible through their <see cref="BaseCheckpointDoor"/>. /// </summary> - public new static Dictionary<BaseCheckpointDoor, CheckpointDoor> Dictionary { get; } = []; + public static new Dictionary<BaseCheckpointDoor, CheckpointDoor> Dictionary { get; } = []; /// <summary> /// A reference to all <see cref="CheckpointDoor"/> instances currently in the game. /// </summary> - public new static IReadOnlyCollection<CheckpointDoor> List => Dictionary.Values; + public static new IReadOnlyCollection<CheckpointDoor> List => Dictionary.Values; + + /// <summary> + /// Gets the <see cref="CheckpointDoor"/> wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist. + /// </summary> + /// <param name="baseCheckpointDoor">The <see cref="BaseCheckpointDoor"/> of the door.</param> + /// <returns>The requested door wrapper or null if the input was null.</returns> + [return: NotNullIfNotNull(nameof(baseCheckpointDoor))] + public static CheckpointDoor? Get(BaseCheckpointDoor? baseCheckpointDoor) + { + if (baseCheckpointDoor == null) + { + return null; + } + + if (Dictionary.TryGetValue(baseCheckpointDoor, out CheckpointDoor door)) + { + return door; + } + + return (CheckpointDoor)CreateDoorWrapper(baseCheckpointDoor); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -33,19 +54,14 @@ internal CheckpointDoor(BaseCheckpointDoor baseCheckpointDoor) SubDoors = new Door[baseCheckpointDoor.SubDoors.Length]; for (int i = 0; i < baseCheckpointDoor.SubDoors.Length; i++) + { SubDoors[i] = Get(baseCheckpointDoor.SubDoors[i]); + } if (CanCache) + { Dictionary.Add(baseCheckpointDoor, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -157,19 +173,11 @@ public bool TryBreak(DoorDamageType type = DoorDamageType.ServerCommand) => TryDamage(float.MaxValue, type); /// <summary> - /// Gets the <see cref="CheckpointDoor"/> wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="baseCheckpointDoor">The <see cref="BaseCheckpointDoor"/> of the door.</param> - /// <returns>The requested door wrapper or null if the input was null.</returns> - [return: NotNullIfNotNull(nameof(baseCheckpointDoor))] - public static CheckpointDoor? Get(BaseCheckpointDoor? baseCheckpointDoor) + internal override void OnRemove() { - if (baseCheckpointDoor == null) - return null; - - if (Dictionary.TryGetValue(baseCheckpointDoor, out CheckpointDoor door)) - return door; - - return (CheckpointDoor)CreateDoorWrapper(baseCheckpointDoor); + base.OnRemove(); + Dictionary.Remove(Base); } } From 723c3a664f36c4b32fb5ecc6b1f9ce3b4b1a307f Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:42:39 +0930 Subject: [PATCH 090/215] door --- .../Features/Wrappers/Facility/Doors/Door.cs | 311 ++++++++++-------- 1 file changed, 167 insertions(+), 144 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Doors/Door.cs b/LabApi/Features/Wrappers/Facility/Doors/Door.cs index 98dca4a0..2ffe3b0c 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/Door.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/Door.cs @@ -17,31 +17,15 @@ namespace LabApi.Features.Wrappers; /// </summary> public class Door { - [InitializeWrapper] - internal static void Initialize() - { - DoorVariant.OnInstanceCreated += OnAdded; - DoorVariant.OnInstanceRemoved += OnRemoved; - - Register<Interactables.Interobjects.BreakableDoor>(x => new BreakableDoor(x)); - Register<Interactables.Interobjects.ElevatorDoor>(x => new ElevatorDoor(x)); - Register<Timed173PryableDoor>(x => new Timed173Gate(x)); - Register<PryableDoor>(x => x.name.StartsWith("HCZ BulkDoor") ? new BulkheadDoor(x) : new Gate(x)); - Register<BasicNonInteractableDoor>(x => new NonInteractableDoor(x)); - Register<Interactables.Interobjects.CheckpointDoor>(x => new CheckpointDoor(x)); - Register<Interactables.Interobjects.DummyDoor>(x => new DummyDoor(x)); - Register<DoorVariant>(x => new Door(x)); - } - /// <summary> /// Contains all the handlers for constructing wrappers for the associated base game types. /// </summary> - private static readonly Dictionary<Type, Func<DoorVariant, Door>> typeWrappers = []; + private static readonly Dictionary<Type, Func<DoorVariant, Door>> TypeWrappers = []; /// <summary> /// Contains all the <see cref="Enums.DoorName"/> values for the associated <see cref="NameTag"/>. /// </summary> - private static readonly Dictionary<string, DoorName> doorNameDictionary = new() + private static readonly Dictionary<string, DoorName> DoorNameDictionary = new() { { "LCZ_CAFE", DoorName.LczPc }, { "LCZ_WC", DoorName.LczWc }, @@ -79,18 +63,155 @@ internal static void Initialize() { "SURFACE_NUKE", DoorName.SurfaceNuke }, { "ESCAPE_PRIMARY", DoorName.SurfaceEscapePrimary }, { "ESCAPE_SECONDARY", DoorName.SurfaceEscapeSecondary }, - { "ESCAPE_FINAL", DoorName.SurfaceEscapeFinal } + { "ESCAPE_FINAL", DoorName.SurfaceEscapeFinal }, }; + /// <summary> + /// A reference to all <see cref="Door"/> instances currently in the game. + /// </summary> + public static IReadOnlyCollection<Door> List => Dictionary.Values; + /// <summary> /// Contains all the cached <see cref="Door">doors</see> in the game, accessible through their <see cref="DoorVariant"/>. /// </summary> protected static Dictionary<DoorVariant, Door> Dictionary { get; } = []; /// <summary> - /// A reference to all <see cref="Door"/> instances currently in the game. + /// Gets the door wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist. /// </summary> - public static IReadOnlyCollection<Door> List => Dictionary.Values; + /// <param name="doorVariant">The <see cref="DoorVariant"/> of the door.</param> + /// <returns>The requested door or null if the input was null.</returns> + [return: NotNullIfNotNull(nameof(doorVariant))] + public static Door? Get(DoorVariant? doorVariant) + { + if (doorVariant == null) + { + return null; + } + + if (Dictionary.TryGetValue(doorVariant, out Door door)) + { + return door; + } + + return CreateDoorWrapper(doorVariant); + } + + /// <summary> + /// Gets the door by it's nametag. + /// </summary> + /// <param name="nametag">The door's nametag.</param> + /// <returns>The requested door. May be null if door with provided nametag does not exist.</returns> + public static Door? Get(string nametag) + { + if (!DoorNametagExtension.NamedDoors.TryGetValue(nametag, out DoorNametagExtension doorNametagExtension)) + { + return null; + } + + return Get(doorNametagExtension.TargetDoor); + } + + /// <summary> + /// Gets the door in specified zone. + /// </summary> + /// <param name="facilityZone">Target zone.</param> + /// <returns>An enumerable set of doors.</returns> + public static IEnumerable<Door> Get(FacilityZone facilityZone) => + List.Where(x => x.Rooms.First().Zone.Equals(facilityZone)); + + /// <summary> + /// Gets the door in specified room. + /// </summary> + /// <param name="roomId">Target room wrapper.</param> + /// <returns>An enumerable set of doors.</returns> + public static IEnumerable<Door> Get(Room roomId) => Get(roomId.Base); + + /// <summary> + /// Gets the door in specified room. + /// </summary> + /// <param name="roomId">Target room identifier.</param> + /// <returns>An enumerable set of doors.</returns> + public static IEnumerable<Door> Get(RoomIdentifier roomId) => + List.Where(x => x.Rooms.First().Equals(roomId)); + + /// <summary> + /// Initializes the door wrapper class. + /// </summary> + [InitializeWrapper] + internal static void Initialize() + { + DoorVariant.OnInstanceCreated += OnAdded; + DoorVariant.OnInstanceRemoved += OnRemoved; + + Register<Interactables.Interobjects.BreakableDoor>(x => new BreakableDoor(x)); + Register<Interactables.Interobjects.ElevatorDoor>(x => new ElevatorDoor(x)); + Register<Timed173PryableDoor>(x => new Timed173Gate(x)); + Register<PryableDoor>(x => x.name.StartsWith("HCZ BulkDoor") ? new BulkheadDoor(x) : new Gate(x)); + Register<BasicNonInteractableDoor>(x => new NonInteractableDoor(x)); + Register<Interactables.Interobjects.CheckpointDoor>(x => new CheckpointDoor(x)); + Register<Interactables.Interobjects.DummyDoor>(x => new DummyDoor(x)); + Register<DoorVariant>(x => new Door(x)); + } + + /// <summary> + /// A protected method to create new door wrappers from the base game object. + /// </summary> + /// <param name="doorVariant">The base object to create the wrapper from.</param> + /// <returns>The newly created wrapper.</returns> + protected static Door CreateDoorWrapper(DoorVariant doorVariant) + { + Type targetType = doorVariant.GetType(); + if (!TypeWrappers.TryGetValue(targetType, out Func<DoorVariant, Door> ctorFunc)) + { + Logger.Warn($"Unable to find {nameof(Door)} wrapper for {targetType.Name}, backup up to base constructor!"); + return new Door(doorVariant); + } + + return ctorFunc.Invoke(doorVariant); + } + + /// <summary> + /// Private method to handle the creation of new doors in the server. + /// </summary> + /// <param name="doorVariant">The <see cref="DoorVariant"/> that was created.</param> + private static void OnAdded(DoorVariant doorVariant) + { + try + { + if (!Dictionary.ContainsKey(doorVariant)) + { + CreateDoorWrapper(doorVariant); + } + } + catch (Exception ex) + { + Console.Logger.Error($"An exception occurred while handling the creation of a new door in LabApi.Features.Wrappers.Door.OnAdded(DoorVariant). Error: {ex}"); + } + } + + /// <summary> + /// Private method to handle the removal of doors from the server. + /// </summary> + /// <param name="doorVariant">The door being destroyed.</param> + private static void OnRemoved(DoorVariant doorVariant) + { + if (Dictionary.TryGetValue(doorVariant, out Door door)) + { + door.OnRemove(); + } + } + + /// <summary> + /// A private method to handle the addition of wrapper handlers. + /// </summary> + /// <typeparam name="T">The derived base game type to handle.</typeparam> + /// <param name="constructor">A handler to construct the wrapper with the base game instance.</param> + private static void Register<T>(Func<T, Door> constructor) + where T : DoorVariant + { + TypeWrappers.Add(typeof(T), x => constructor((T)x)); + } /// <summary> /// A private constructor to prevent external instantiation. @@ -101,42 +222,35 @@ protected Door(DoorVariant doorVariant) Base = doorVariant; if (CanCache) + { Dictionary.Add(doorVariant, this); + } if (doorVariant.TryGetComponent(out DoorNametagExtension nametag) && !string.IsNullOrEmpty(nametag.GetName)) { - if (doorNameDictionary.TryGetValue(nametag.GetName, out DoorName doorName)) + if (DoorNameDictionary.TryGetValue(nametag.GetName, out DoorName doorName)) + { DoorName = doorName; + } else + { Logger.InternalWarn($"Missing DoorName enum value for door name tag {nametag.GetName}"); + } } } - /// <summary> - /// An internal virtual method to signal that the base object has been destroyed. - /// </summary> - internal virtual void OnRemove() - { - Dictionary.Remove(Base); - } - /// <summary> /// Whether the door has been destroyed, see <see cref="UnityEngine.Object.DestroyObject(UnityEngine.Object)"/>. /// </summary> public bool IsDestroyed => Base == null; - /// <summary> - /// Whether the wrapper can be cached. - /// </summary> - protected bool CanCache => !IsDestroyed && Base.isActiveAndEnabled; - /// <summary> /// The base object. /// </summary> public DoorVariant Base { get; } /// <summary> - /// Gets the <see cref="Enums.DoorName"/> of the door.s + /// Gets the <see cref="Enums.DoorName"/> of the door. /// </summary> /// <remarks> /// Is the enum version of <see cref="NameTag"/>. @@ -154,7 +268,7 @@ internal virtual void OnRemove() /// <summary> /// Gets the rooms which have this door. /// </summary> - public Room[] Rooms => Base.Rooms.Select(Room.Get).ToArray(); + public Room[] Rooms => Base.Rooms.Select(Room.Get).ToArray()!; /// <summary> /// Gets the zone in which this door is. @@ -194,17 +308,10 @@ public bool IsLocked } /// <summary> - /// Gets the door's <see cref="DoorLockReason"/> + /// Gets the door's <see cref="DoorLockReason"/>. /// </summary> public DoorLockReason LockReason => (DoorLockReason)Base.ActiveLocks; - /// <summary> - /// Locks the door. - /// </summary> - /// <param name="reason">The reason.</param> - /// <param name="enabled">Whether the door lock reason is new.</param> - public void Lock(DoorLockReason reason, bool enabled) => Base.ServerChangeLock(reason, enabled); - /// <summary> /// Gets or sets the required <see cref="DoorPermissionFlags"/>. /// </summary> @@ -243,6 +350,18 @@ public bool Bypass2176 /// </summary> public Quaternion Rotation => Transform.rotation; + /// <summary> + /// Whether the wrapper can be cached. + /// </summary> + protected bool CanCache => !IsDestroyed && Base.isActiveAndEnabled; + + /// <summary> + /// Locks the door. + /// </summary> + /// <param name="reason">The reason.</param> + /// <param name="enabled">Whether the door lock reason is new.</param> + public void Lock(DoorLockReason reason, bool enabled) => Base.ServerChangeLock(reason, enabled); + /// <summary> /// Plays a sound that indicates that lock bypass was denied. /// </summary> @@ -260,106 +379,10 @@ public override string ToString() } /// <summary> - /// Gets the door wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist. - /// </summary> - /// <param name="doorVariant">The <see cref="DoorVariant"/> of the door.</param> - /// <returns>The requested door or null if the input was null.</returns> - [return: NotNullIfNotNull(nameof(doorVariant))] - public static Door? Get(DoorVariant? doorVariant) - { - if (doorVariant == null) - return null; - - if (Dictionary.TryGetValue(doorVariant, out Door door)) - return door; - - return CreateDoorWrapper(doorVariant); - } - - /// <summary> - /// Gets the door by it's nametag. - /// </summary> - /// <param name="nametag">The door's nametag</param> - /// <returns>The requested door. May be null if door with provided nametag does not exist.</returns> - public static Door? Get(string nametag) - { - if (!DoorNametagExtension.NamedDoors.TryGetValue(nametag, out DoorNametagExtension doorNametagExtension)) - return null; - - return Get(doorNametagExtension.TargetDoor); - } - - /// <summary> - /// Gets the door in specified zone. - /// </summary> - /// <param name="facilityZone">Target zone.</param> - public static IEnumerable<Door> Get(FacilityZone facilityZone) => - List.Where(x => x.Rooms.First().Zone.Equals(facilityZone)); - - /// <summary> - /// Gets the door in specified room. - /// </summary> - /// <param name="roomId">Target room wrapper.</param> - public static IEnumerable<Door> Get(Room roomId) => Get(roomId.Base); - - /// <summary> - /// Gets the door in specified room. - /// </summary> - /// <param name="roomId">Target room identifier.</param> - public static IEnumerable<Door> Get(RoomIdentifier roomId) => - List.Where(x => x.Rooms.First().Equals(roomId)); - - /// <summary> - /// A protected method to create new door wrappers from the base game object. - /// </summary> - /// <param name="doorVariant">The base object to create the wrapper from.</param> - /// <returns>The newly created wrapper.</returns> - protected static Door CreateDoorWrapper(DoorVariant doorVariant) - { - Type targetType = doorVariant.GetType(); - if (!typeWrappers.TryGetValue(targetType, out Func<DoorVariant, Door> ctorFunc)) - { - Logger.Warn($"Unable to find {nameof(Door)} wrapper for {targetType.Name}, backup up to base constructor!"); - return new Door(doorVariant); - } - - return ctorFunc.Invoke(doorVariant); - } - - /// <summary> - /// Private method to handle the creation of new doors in the server. - /// </summary> - /// <param name="doorVariant">The <see cref="DoorVariant"/> that was created.</param> - private static void OnAdded(DoorVariant doorVariant) - { - try - { - if (!Dictionary.ContainsKey(doorVariant)) - CreateDoorWrapper(doorVariant); - } - catch (Exception ex) - { - Console.Logger.Error($"An exception occurred while handling the creation of a new door in LabApi.Features.Wrappers.Door.OnAdded(DoorVariant). Error: {ex}"); - } - } - - /// <summary> - /// Private method to handle the removal of doors from the server. - /// </summary> - /// <param name="doorVariant">The door being destroyed.</param> - private static void OnRemoved(DoorVariant doorVariant) - { - if (Dictionary.TryGetValue(doorVariant, out Door door)) - door.OnRemove(); - } - - /// <summary> - /// A private method to handle the addition of wrapper handlers. + /// An internal virtual method to signal that the base object has been destroyed. /// </summary> - /// <typeparam name="T">The derived base game type to handle.</typeparam> - /// <param name="constructor">A handler to construct the wrapper with the base game instance.</param> - private static void Register<T>(Func<T, Door> constructor) where T : DoorVariant + internal virtual void OnRemove() { - typeWrappers.Add(typeof(T), x => constructor((T)x)); + Dictionary.Remove(Base); } } \ No newline at end of file From 184ff243bf8ac976f7530e307dd85c00e9f144bf Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:42:47 +0930 Subject: [PATCH 091/215] dummy --- .../Wrappers/Facility/Doors/DummyDoor.cs | 50 ++++++++++--------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Doors/DummyDoor.cs b/LabApi/Features/Wrappers/Facility/Doors/DummyDoor.cs index e9947feb..a31cebe9 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/DummyDoor.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/DummyDoor.cs @@ -12,12 +12,33 @@ public class DummyDoor : Door /// <summary> /// Contains all the cached <see cref="DummyDoor"/> instances, accessible through their <see cref="BaseDummyDoor"/>. /// </summary> - public new static Dictionary<BaseDummyDoor, DummyDoor> Dictionary { get; } = []; + public static new Dictionary<BaseDummyDoor, DummyDoor> Dictionary { get; } = []; /// <summary> /// A reference to all <see cref="DummyDoor"/> instances currently in the game. /// </summary> - public new static IReadOnlyCollection<DummyDoor> List => Dictionary.Values; + public static new IReadOnlyCollection<DummyDoor> List => Dictionary.Values; + + /// <summary> + /// Gets the <see cref="DummyDoor"/> wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist. + /// </summary> + /// <param name="baseDummyDoor">The <see cref="BaseDummyDoor"/> of the door.</param> + /// <returns>The requested door wrapper or null if the input was null.</returns> + [return: NotNullIfNotNull(nameof(baseDummyDoor))] + public static DummyDoor? Get(BaseDummyDoor? baseDummyDoor) + { + if (baseDummyDoor == null) + { + return null; + } + + if (Dictionary.TryGetValue(baseDummyDoor, out DummyDoor door)) + { + return door; + } + + return (DummyDoor)CreateDoorWrapper(baseDummyDoor); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -30,34 +51,17 @@ internal DummyDoor(BaseDummyDoor baseDummyDoor) Base = baseDummyDoor; } - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); - } - /// <summary> /// The base <see cref="BaseDummyDoor"/> object. /// </summary> public new BaseDummyDoor Base { get; } /// <summary> - /// Gets the <see cref="DummyDoor"/> wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="baseDummyDoor">The <see cref="BaseDummyDoor"/> of the door.</param> - /// <returns>The requested door wrapper or null if the input was null.</returns> - [return: NotNullIfNotNull(nameof(baseDummyDoor))] - public static DummyDoor? Get(BaseDummyDoor? baseDummyDoor) + internal override void OnRemove() { - if (baseDummyDoor == null) - return null; - - if (Dictionary.TryGetValue(baseDummyDoor, out DummyDoor door)) - return door; - - return (DummyDoor)CreateDoorWrapper(baseDummyDoor); + base.OnRemove(); + Dictionary.Remove(Base); } } From 7fd0ea26c7e70c39c7b1a37579f988b8f16814f9 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:42:53 +0930 Subject: [PATCH 092/215] elevator --- .../Wrappers/Facility/Doors/ElevatorDoor.cs | 52 +++++++++++-------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Doors/ElevatorDoor.cs b/LabApi/Features/Wrappers/Facility/Doors/ElevatorDoor.cs index 5b34eb14..9021e7d4 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/ElevatorDoor.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/ElevatorDoor.cs @@ -14,12 +14,33 @@ public class ElevatorDoor : Door /// <summary> /// Contains all the cached <see cref="ElevatorDoor"/> instances, accessible through their <see cref="BaseElevatorDoor"/>. /// </summary> - public new static Dictionary<BaseElevatorDoor, ElevatorDoor> Dictionary { get; } = []; + public static new Dictionary<BaseElevatorDoor, ElevatorDoor> Dictionary { get; } = []; /// <summary> /// A reference to all <see cref="ElevatorDoor"/> instances currently in the game. /// </summary> - public new static IReadOnlyCollection<ElevatorDoor> List => Dictionary.Values; + public static new IReadOnlyCollection<ElevatorDoor> List => Dictionary.Values; + + /// <summary> + /// Gets the <see cref="ElevatorDoor"/> wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist. + /// </summary> + /// <param name="baseElevatorDoor">The <see cref="BaseElevatorDoor"/> of the door.</param> + /// <returns>The requested door wrapper or null if the input was null.</returns> + [return: NotNullIfNotNull(nameof(baseElevatorDoor))] + public static ElevatorDoor? Get(BaseElevatorDoor? baseElevatorDoor) + { + if (baseElevatorDoor == null) + { + return null; + } + + if (Dictionary.TryGetValue(baseElevatorDoor, out ElevatorDoor door)) + { + return door; + } + + return (ElevatorDoor)CreateDoorWrapper(baseElevatorDoor); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -31,16 +52,9 @@ internal ElevatorDoor(BaseElevatorDoor baseElevatorDoor) Base = baseElevatorDoor; if (CanCache) + { Dictionary.Add(baseElevatorDoor, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -59,19 +73,11 @@ internal override void OnRemove() public ElevatorGroup Group => Base.Group; /// <summary> - /// Gets the <see cref="ElevatorDoor"/> wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="baseElevatorDoor">The <see cref="BaseElevatorDoor"/> of the door.</param> - /// <returns>The requested door wrapper or null if the input was null.</returns> - [return: NotNullIfNotNull(nameof(baseElevatorDoor))] - public static ElevatorDoor? Get(BaseElevatorDoor? baseElevatorDoor) + internal override void OnRemove() { - if (baseElevatorDoor == null) - return null; - - if (Dictionary.TryGetValue(baseElevatorDoor, out ElevatorDoor door)) - return door; - - return (ElevatorDoor)CreateDoorWrapper(baseElevatorDoor); + base.OnRemove(); + Dictionary.Remove(Base); } } From 302438ca75ddcf64c02cb20d404625034482f1d0 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:42:56 +0930 Subject: [PATCH 093/215] gate --- .../Features/Wrappers/Facility/Doors/Gate.cs | 54 ++++++++++--------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Doors/Gate.cs b/LabApi/Features/Wrappers/Facility/Doors/Gate.cs index d05b5ad8..553a00d8 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/Gate.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/Gate.cs @@ -5,19 +5,40 @@ namespace LabApi.Features.Wrappers; /// <summary> -/// A wrapper representing the <see cref="PryableDoor"/> +/// A wrapper representing the <see cref="PryableDoor"/>. /// </summary> public class Gate : Door { /// <summary> /// Contains all the cached <see cref="Gate"/> instances, accessible through their <see cref="PryableDoor"/>. /// </summary> - public new static Dictionary<PryableDoor, Gate> Dictionary { get; } = []; + public static new Dictionary<PryableDoor, Gate> Dictionary { get; } = []; /// <summary> /// A reference to all <see cref="Gate"/> instances currently in the game. /// </summary> - public new static IReadOnlyCollection<Gate> List => Dictionary.Values; + public static new IReadOnlyCollection<Gate> List => Dictionary.Values; + + /// <summary> + /// Gets the <see cref="Gate"/> wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist. + /// </summary> + /// <param name="pryableDoor">The <see cref="PryableDoor"/> of the door.</param> + /// <returns>The requested door wrapper or null if the input was null.</returns> + [return: NotNullIfNotNull(nameof(pryableDoor))] + public static Gate? Get(PryableDoor? pryableDoor) + { + if (pryableDoor == null) + { + return null; + } + + if (Dictionary.TryGetValue(pryableDoor, out Gate door)) + { + return door; + } + + return (Gate)CreateDoorWrapper(pryableDoor); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -29,16 +50,9 @@ internal Gate(PryableDoor pryableDoor) Base = pryableDoor; if (CanCache) + { Dictionary.Add(pryableDoor, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -68,19 +82,11 @@ public bool Is106Passable public void Pry() => Base.RpcPryGate(); /// <summary> - /// Gets the <see cref="Gate"/> wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="pryableDoor">The <see cref="PryableDoor"/> of the door.</param> - /// <returns>The requested door wrapper or null if the input was null.</returns> - [return: NotNullIfNotNull(nameof(pryableDoor))] - public static Gate? Get(PryableDoor? pryableDoor) + internal override void OnRemove() { - if (pryableDoor == null) - return null; - - if (Dictionary.TryGetValue(pryableDoor, out Gate door)) - return door; - - return (Gate)CreateDoorWrapper(pryableDoor); + base.OnRemove(); + Dictionary.Remove(Base); } } From e93504bd16c8ca00d35f0401cddd6b6137616f65 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:43:03 +0930 Subject: [PATCH 094/215] noninteractable --- .../Facility/Doors/NonInteractableDoor.cs | 52 +++++++++++-------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Doors/NonInteractableDoor.cs b/LabApi/Features/Wrappers/Facility/Doors/NonInteractableDoor.cs index f2006c33..c18af8e6 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/NonInteractableDoor.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/NonInteractableDoor.cs @@ -12,12 +12,33 @@ public class NonInteractableDoor : Door /// <summary> /// Contains all the cached <see cref="NonInteractableDoor"/> instances, accessible through their <see cref="BasicNonInteractableDoor"/>. /// </summary> - public new static Dictionary<BasicNonInteractableDoor, NonInteractableDoor> Dictionary { get; } = []; + public static new Dictionary<BasicNonInteractableDoor, NonInteractableDoor> Dictionary { get; } = []; /// <summary> /// A reference to all <see cref="NonInteractableDoor"/> instances currently in the game. /// </summary> - public new static IReadOnlyCollection<NonInteractableDoor> List => Dictionary.Values; + public static new IReadOnlyCollection<NonInteractableDoor> List => Dictionary.Values; + + /// <summary> + /// Gets the <see cref="NonInteractableDoor"/> wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist. + /// </summary> + /// <param name="basicNonInteractableDoor">The <see cref="BasicNonInteractableDoor"/> of the door.</param> + /// <returns>The requested door wrapper or null if the input was null.</returns> + [return: NotNullIfNotNull(nameof(basicNonInteractableDoor))] + public static NonInteractableDoor? Get(BasicNonInteractableDoor? basicNonInteractableDoor) + { + if (basicNonInteractableDoor == null) + { + return null; + } + + if (Dictionary.TryGetValue(basicNonInteractableDoor, out NonInteractableDoor door)) + { + return door; + } + + return (NonInteractableDoor)CreateDoorWrapper(basicNonInteractableDoor); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -29,16 +50,9 @@ internal NonInteractableDoor(BasicNonInteractableDoor basicNonInteractableDoor) Base = basicNonInteractableDoor; if (CanCache) + { Dictionary.Add(basicNonInteractableDoor, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -56,19 +70,11 @@ public bool Is106Passable } /// <summary> - /// Gets the <see cref="NonInteractableDoor"/> wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="basicNonInteractableDoor">The <see cref="BasicNonInteractableDoor"/> of the door.</param> - /// <returns>The requested door wrapper or null if the input was null.</returns> - [return: NotNullIfNotNull(nameof(basicNonInteractableDoor))] - public static NonInteractableDoor? Get(BasicNonInteractableDoor? basicNonInteractableDoor) + internal override void OnRemove() { - if (basicNonInteractableDoor == null) - return null; - - if (Dictionary.TryGetValue(basicNonInteractableDoor, out NonInteractableDoor door)) - return door; - - return (NonInteractableDoor)CreateDoorWrapper(basicNonInteractableDoor); + base.OnRemove(); + Dictionary.Remove(Base); } } From 16a74adcdf0f57d6fce69ce1deeb43d0440e058d Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:43:11 +0930 Subject: [PATCH 095/215] timed173gate --- .../Wrappers/Facility/Doors/Timed173Gate.cs | 52 +++++++++++-------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Doors/Timed173Gate.cs b/LabApi/Features/Wrappers/Facility/Doors/Timed173Gate.cs index 6384f570..69d760d5 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/Timed173Gate.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/Timed173Gate.cs @@ -16,12 +16,33 @@ public class Timed173Gate : Gate /// <summary> /// Contains all the cached <see cref="Timed173Gate"/> instances, accessible through their <see cref="Timed173PryableDoor"/>. /// </summary> - public new static Dictionary<Timed173PryableDoor, Timed173Gate> Dictionary { get; } = []; + public static new Dictionary<Timed173PryableDoor, Timed173Gate> Dictionary { get; } = []; /// <summary> /// A reference to all <see cref="Timed173Gate"/> instances currently in the game. /// </summary> - public new static IReadOnlyCollection<Timed173Gate> List => Dictionary.Values; + public static new IReadOnlyCollection<Timed173Gate> List => Dictionary.Values; + + /// <summary> + /// Gets the <see cref="Timed173Gate"/> wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist. + /// </summary> + /// <param name="timed173PryableDoor">The <see cref="Timed173PryableDoor"/> of the door.</param> + /// <returns>The requested door wrapper or null if the input was null.</returns> + [return: NotNullIfNotNull(nameof(timed173PryableDoor))] + public static Timed173Gate? Get(Timed173PryableDoor? timed173PryableDoor) + { + if (timed173PryableDoor == null) + { + return null; + } + + if (Dictionary.TryGetValue(timed173PryableDoor, out Timed173Gate door)) + { + return door; + } + + return (Timed173Gate)CreateDoorWrapper(timed173PryableDoor); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -33,16 +54,9 @@ internal Timed173Gate(Timed173PryableDoor timed173PryableDoor) Base = timed173PryableDoor; if (CanCache) + { Dictionary.Add(timed173PryableDoor, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -77,19 +91,11 @@ public float Delay } /// <summary> - /// Gets the <see cref="Timed173Gate"/> wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="timed173PryableDoor">The <see cref="Timed173PryableDoor"/> of the door.</param> - /// <returns>The requested door wrapper or null if the input was null.</returns> - [return: NotNullIfNotNull(nameof(timed173PryableDoor))] - public static Timed173Gate? Get(Timed173PryableDoor? timed173PryableDoor) + internal override void OnRemove() { - if (timed173PryableDoor == null) - return null; - - if (Dictionary.TryGetValue(timed173PryableDoor, out Timed173Gate door)) - return door; - - return (Timed173Gate)CreateDoorWrapper(timed173PryableDoor); + base.OnRemove(); + Dictionary.Remove(Base); } } From 0fb54ac4c5b3745300ba753dca4c5e922a5ab30f Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:43:22 +0930 Subject: [PATCH 096/215] amnesticcloud --- .../Facility/Hazards/AmnesticCloudHazard.cs | 131 ++++++++++-------- 1 file changed, 70 insertions(+), 61 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Hazards/AmnesticCloudHazard.cs b/LabApi/Features/Wrappers/Facility/Hazards/AmnesticCloudHazard.cs index b23cafd3..b533b027 100644 --- a/LabApi/Features/Wrappers/Facility/Hazards/AmnesticCloudHazard.cs +++ b/LabApi/Features/Wrappers/Facility/Hazards/AmnesticCloudHazard.cs @@ -14,17 +14,83 @@ public class AmnesticCloudHazard : DecayableHazard /// <summary> /// Contains all the cached items, accessible through their <see cref="Base"/>. /// </summary> - public new static Dictionary<Scp939AmnesticCloudInstance, AmnesticCloudHazard> Dictionary { get; } = []; + public static new Dictionary<Scp939AmnesticCloudInstance, AmnesticCloudHazard> Dictionary { get; } = []; /// <summary> /// Gets all currently active tantrum hazards. /// </summary> - public new IReadOnlyCollection<AmnesticCloudHazard> List => Dictionary.Values; + public static new IReadOnlyCollection<AmnesticCloudHazard> List => Dictionary.Values; /// <summary> /// Prefab used to spawn the hazard. /// </summary> - protected static new Scp939AmnesticCloudInstance? BasePrefab; + protected static new Scp939AmnesticCloudInstance? BasePrefab { get; private set; } + + /// <summary> + /// Spawns a <see cref="AmnesticCloudHazard"/> at specified position with specified rotation, scale duration and size. + /// <para> Do note that changing scale doesn't change the effect size. Use the <see cref="Hazard.MaxDistance"/> and <see cref="Hazard.MaxHeightDistance"/> to match the visual size.</para> + /// </summary> + /// <param name="position">The target position to spawn this hazard at.</param> + /// <param name="rotation">The target rotation to spawn this hazard with.</param> + /// <param name="scale">The target scale to spawn with.</param> + /// <param name="duration">The duration in seconds for which this cloud will be alive for.</param> + /// <param name="size">The size of the cloud.</param> + /// <param name="owner">The owner of the cloud.</param> + /// <returns>A new hazard.</returns> + public static AmnesticCloudHazard Spawn(Vector3 position, Quaternion rotation, Vector3 scale, float duration = 90f, byte size = 255, Player? owner = null) + { + if (BasePrefab == null) + { + BasePrefab = GetPrefab<Scp939AmnesticCloudInstance>(); + } + + AmnesticCloudHazard hazard = (AmnesticCloudHazard)Hazard.Spawn(BasePrefab!, position, rotation, scale); + hazard.Base.State = CloudState.Created; + hazard.LiveDuration = duration; + hazard.VisualSize = size; + hazard.SyncedPosition = position; + + Vector2 minMax = hazard.Base.MinMaxTime; + hazard.MaxDistance = Mathf.Lerp(minMax.x, minMax.y, size / byte.MaxValue); + + if (owner != null) + { + hazard.Owner = owner; + } + + return hazard; + } + + /// <summary> + /// Gets the hazard wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="Scp939AmnesticCloudInstance"/> was not <see langword="null"/>. + /// </summary> + /// <param name="hazard">The <see cref="Base"/> of the hazard.</param> + /// <returns>The requested hazard or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(hazard))] + public static AmnesticCloudHazard? Get(Scp939AmnesticCloudInstance? hazard) + { + if (hazard == null) + { + return null; + } + + return Dictionary.TryGetValue(hazard, out AmnesticCloudHazard decHazard) ? decHazard : (AmnesticCloudHazard)CreateItemWrapper(hazard)!; + } + + /// <summary> + /// Internal constructor preventing external instantiation. + /// </summary> + /// <param name="hazard">The base amnestic cloud hazard.</param> + internal AmnesticCloudHazard(Scp939AmnesticCloudInstance hazard) + : base(hazard) + { + Base = hazard; + + if (CanCache) + { + Dictionary.Add(hazard, this); + } + } /// <summary> /// Gets or sets the world position of the hazard as it is synchronized with the client. @@ -92,53 +158,10 @@ public Player? Owner /// </summary> public new Scp939AmnesticCloudInstance Base { get; } - /// <summary> - /// Internal constructor preventing external instantiation. - /// </summary> - /// <param name="hazard">The base amnestic cloud hazard.</param> - internal AmnesticCloudHazard(Scp939AmnesticCloudInstance hazard) - : base(hazard) - { - Base = hazard; - - if (CanCache) - Dictionary.Add(hazard, this); - } - - /// <summary> - /// Spawns a <see cref="AmnesticCloudHazard"/> at specified position with specified rotation, scale duration and size. - /// <para> Do note that changing scale doesn't change the effect size. Use the <see cref="Hazard.MaxDistance"/> and <see cref="Hazard.MaxHeightDistance"/> to match the visual size.</para> - /// </summary> - /// <param name="position">The target position to spawn this hazard at.</param> - /// <param name="rotation">The target rotation to spawn this hazard with.</param> - /// <param name="scale">The target scale to spawn with.</param> - /// <param name="duration">The duration in seconds for which this cloud will be alive for.</param> - /// <param name="size">The size of the cloud.</param> - /// <param name="owner">The owner of the cloud.</param> - /// <returns>A new hazard.</returns> - public static AmnesticCloudHazard Spawn(Vector3 position, Quaternion rotation, Vector3 scale, float duration = 90f, byte size = 255, Player? owner = null) - { - if (BasePrefab == null) - BasePrefab = GetPrefab<Scp939AmnesticCloudInstance>(); - - AmnesticCloudHazard hazard = (AmnesticCloudHazard)Hazard.Spawn(BasePrefab, position, rotation, scale); - hazard.Base.State = CloudState.Created; - hazard.LiveDuration = duration; - hazard.VisualSize = size; - hazard.SyncedPosition = position; - - Vector2 minMax = hazard.Base.MinMaxTime; - hazard.MaxDistance = Mathf.Lerp(minMax.x, minMax.y, size / byte.MaxValue); - - if (owner != null) - hazard.Owner = owner; - return hazard; - } - /// <summary> /// Temporary pauses all amnesia effects based on <see cref="PauseDuration"/> or custom time. /// </summary> - /// <param name="customDuration">Custom duration of the pause. Values less than 0 will use the <see cref="PauseDuration"/></param> + /// <param name="customDuration">Custom duration of the pause. Values less than 0 will use the <see cref="PauseDuration"/>.</param> public void Pause(float customDuration = -1f) { if (customDuration > 0f) @@ -162,18 +185,4 @@ internal override void OnRemove() base.OnRemove(); Dictionary.Remove(Base); } - - /// <summary> - /// Gets the hazard wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="Scp939AmnesticCloudInstance"/> was not <see langword="null"/>. - /// </summary> - /// <param name="hazard">The <see cref="Base"/> of the hazard.</param> - /// <returns>The requested hazard or <see langword="null"/>.</returns> - [return: NotNullIfNotNull(nameof(hazard))] - public static AmnesticCloudHazard? Get(Scp939AmnesticCloudInstance? hazard) - { - if (hazard == null) - return null; - - return Dictionary.TryGetValue(hazard, out AmnesticCloudHazard decHazard) ? decHazard : (AmnesticCloudHazard)CreateItemWrapper(hazard); - } } \ No newline at end of file From 3c25a20374f39e1d49ef62da851ac18178a5f8a7 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:43:28 +0930 Subject: [PATCH 097/215] decayable --- .../Facility/Hazards/DecayableHazard.cs | 64 ++++++++++--------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Hazards/DecayableHazard.cs b/LabApi/Features/Wrappers/Facility/Hazards/DecayableHazard.cs index b78d6eff..2f96f670 100644 --- a/LabApi/Features/Wrappers/Facility/Hazards/DecayableHazard.cs +++ b/LabApi/Features/Wrappers/Facility/Hazards/DecayableHazard.cs @@ -13,12 +13,43 @@ public class DecayableHazard : Hazard /// <summary> /// Contains all the cached items, accessible through their <see cref="Base"/>. /// </summary> - public new static Dictionary<TemporaryHazard, DecayableHazard> Dictionary { get; } = []; + public static new Dictionary<TemporaryHazard, DecayableHazard> Dictionary { get; } = []; /// <summary> /// Gets all currently active decayable hazards. /// </summary> - public new IReadOnlyCollection<DecayableHazard> List => Dictionary.Values; + public static new IReadOnlyCollection<DecayableHazard> List => Dictionary.Values; + + /// <summary> + /// Gets the hazard wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="TemporaryHazard"/> was not <see langword="null"/>. + /// </summary> + /// <param name="hazard">The <see cref="Base"/> of the hazard.</param> + /// <returns>The requested hazard or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(hazard))] + public static DecayableHazard? Get(TemporaryHazard? hazard) + { + if (hazard == null) + { + return null; + } + + return Dictionary.TryGetValue(hazard, out DecayableHazard decHazard) ? decHazard : (DecayableHazard)CreateItemWrapper(hazard)!; + } + + /// <summary> + /// An internal constructor to prevent external instantiation. + /// </summary> + /// <param name="hazard">The base game object.</param> + protected DecayableHazard(TemporaryHazard hazard) + : base(hazard) + { + Base = hazard; + + if (CanCache) + { + Dictionary.Add(hazard, this); + } + } /// <summary> /// Gets or sets the modifier applied to <see cref="Time.deltaTime"/> when calculating how much time has passed.<br/> @@ -54,22 +85,9 @@ public float Elapsed /// </summary> public new TemporaryHazard Base { get; } - /// <summary> - /// An internal constructor to prevent external instantiation. - /// </summary> - /// <param name="hazard">The base game object.</param> - protected DecayableHazard(TemporaryHazard hazard) - : base(hazard) - { - Base = hazard; - - if (CanCache) - Dictionary.Add(hazard, this); - } - /// <summary> /// Destroys this hazard.<br/> - /// Do note that subclasses usually implement few seconds delay before the actual object is destroyed. (Usually to wait for animations to finish on clients) + /// Do note that subclasses usually implement few seconds delay before the actual object is destroyed (Usually to wait for animations to finish on clients). /// </summary> public override void Destroy() => Base.ServerDestroy(); @@ -79,18 +97,4 @@ internal override void OnRemove() base.OnRemove(); Dictionary.Remove(Base); } - - /// <summary> - /// Gets the hazard wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="TemporaryHazard"/> was not <see langword="null"/>. - /// </summary> - /// <param name="hazard">The <see cref="Base"/> of the hazard.</param> - /// <returns>The requested hazard or <see langword="null"/>.</returns> - [return: NotNullIfNotNull(nameof(hazard))] - public static DecayableHazard? Get(TemporaryHazard? hazard) - { - if (hazard == null) - return null; - - return Dictionary.TryGetValue(hazard, out DecayableHazard decHazard) ? decHazard : (DecayableHazard)CreateItemWrapper(hazard); - } } \ No newline at end of file From 7bff41cec58899ab49987143e27cf1b5ebba7d6f Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:43:33 +0930 Subject: [PATCH 098/215] hazard --- .../Wrappers/Facility/Hazards/Hazard.cs | 306 +++++++++--------- 1 file changed, 161 insertions(+), 145 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Hazards/Hazard.cs b/LabApi/Features/Wrappers/Facility/Hazards/Hazard.cs index 91a39baf..6b90eaa4 100644 --- a/LabApi/Features/Wrappers/Facility/Hazards/Hazard.cs +++ b/LabApi/Features/Wrappers/Facility/Hazards/Hazard.cs @@ -1,13 +1,13 @@ -using Hazards; +using Generators; +using Hazards; using InventorySystem; +using Mirror; +using PlayerRoles.PlayableScps.Scp939; using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; -using Generators; using UnityEngine; -using Mirror; -using System.Diagnostics.CodeAnalysis; -using PlayerRoles.PlayableScps.Scp939; using Logger = LabApi.Features.Console.Logger; namespace LabApi.Features.Wrappers; @@ -20,7 +20,7 @@ public class Hazard /// <summary> /// Contains all the handlers for constructing wrappers for the associated base game types. /// </summary> - private static readonly Dictionary<Type, Func<EnvironmentalHazard, Hazard>> typeWrappers = []; + private static readonly Dictionary<Type, Func<EnvironmentalHazard, Hazard>> TypeWrappers = []; /// <summary> /// Contains all the cached items, accessible through their <see cref="Base"/>. @@ -35,88 +35,72 @@ public class Hazard /// <summary> /// Prefab used to spawn the hazard. /// </summary> - protected static EnvironmentalHazard? BasePrefab; - - /// <summary> - /// Base game object. - /// </summary> - public EnvironmentalHazard Base { get; private set; } + protected static EnvironmentalHazard? BasePrefab { get; private set; } /// <summary> - /// Gets all affected players by this hazard. - /// </summary> - public IEnumerable<Player> AffectedPlayers => Base.AffectedPlayers.Select(n => Player.Get(n)); - - /// <summary> - /// Whether to cache the wrapper. - /// </summary> - protected bool CanCache => !IsDestroyed && Base.isActiveAndEnabled; - - /// <summary> - /// Gets or sets the maximum distance players have to be at, for this hazard to affect them. + /// Spawns a <see cref="Hazard"/> at specified position with specified rotation and scale. /// </summary> - public float MaxDistance + /// <param name="prefab">The target prefab.</param> + /// <param name="position">The target position to spawn this hazard at.</param> + /// <param name="rotation">The target rotation to spawn this hazard with.</param> + /// <param name="scale">The target scale to spawn with.</param> + /// <returns>A new hazard.</returns> + public static Hazard Spawn(EnvironmentalHazard prefab, Vector3 position, Quaternion rotation, Vector3 scale) { - get => Base.MaxDistance; - set => Base.MaxDistance = value; - } + EnvironmentalHazard hazard = GameObject.Instantiate(prefab); + hazard.transform.SetPositionAndRotation(position, rotation); + hazard.transform.localScale = scale; - /// <summary> - /// Gets or sets the maximum height players have to be at, for this hazard to affect them. - /// </summary> - public float MaxHeightDistance - { - get => Base.MaxHeightDistance; - set => Base.MaxHeightDistance = value; + return Get(hazard); } /// <summary> - /// Gets or sets the offset applied to the <see cref="SourcePosition"/>. + /// Gets the hazard wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="EnvironmentalHazard"/> was not <see langword="null"/>. /// </summary> - public virtual Vector3 SourceOffset + /// <param name="hazard">The <see cref="Base"/> of the hazard.</param> + /// <returns>The requested hazard or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(hazard))] + public static Hazard? Get(EnvironmentalHazard? hazard) { - get => Base.SourceOffset; - set => Base.SourceOffset = value; - } + if (hazard == null) + { + return null; + } - /// <summary> - /// Gets whether this environmental hazard and it's effects is enabled. - /// Setting to false also stops the decay of temporary hazards. - /// </summary> - public virtual bool IsActive - { - get => Base.IsActive; - set => Base.IsActive = value; + return Dictionary.TryGetValue(hazard, out Hazard wrapper) ? wrapper : CreateItemWrapper(hazard)!; } /// <summary> - /// Gets or sets the origin point from which the AoE effect will start. + /// Tries to get the hazard wrapper from the <see cref="Dictionary"/>. /// </summary> - public virtual Vector3 SourcePosition + /// <param name="envHazard">The <see cref="Base"/> of the hazard.</param> + /// <param name="wrapper">The requested hazard.</param> + /// <returns><see langword="true"/> if the item exists, otherwise <see langword="false"/>.</returns> + public static bool TryGet(EnvironmentalHazard? envHazard, [NotNullWhen(true)] out Hazard? wrapper) { - get => Base.SourcePosition; - set => Base.SourcePosition = value; + wrapper = Get(envHazard); + return wrapper != null; } /// <summary> - /// Gets whether the hazard is destroyed. - /// </summary> - public bool IsDestroyed => Base == null || Base.gameObject == null; - - /// <summary> - /// Gets the room in which this hazard is in. - /// </summary> - public Room? Room => Room.GetRoomAtPosition(SourcePosition); - - /// <summary> - /// Initializes the <see cref="Hazard"/> class to subscribe to <see cref="EnvironmentalHazard"/> events and handle the item caching. + /// Gets all hazards in a specified room. /// </summary> - protected Hazard(EnvironmentalHazard hazard) + /// <param name="room">The target room to check on.</param> + /// <returns>Hazards in specified room.</returns> + public static IEnumerable<Hazard> Get(Room? room) { - Base = hazard; + if (room == null) + { + yield break; + } - if (CanCache) - Dictionary.Add(hazard, this); + foreach (Hazard hazard in List) + { + if (hazard.Room == room) + { + yield return hazard; + } + } } /// <summary> @@ -136,46 +120,38 @@ internal static void Initialize() } /// <summary> - /// An internal virtual method to signal to derived implementations to uncache when the base object is destroyed. + /// Creates a new wrapper from the base environmental hazard object. /// </summary> - internal virtual void OnRemove() - { - } - - /// <inheritdoc /> - public override string ToString() - { - return $"[{GetType().Name}: MaxDistance={MaxDistance}, MaxHeightDistance={MaxHeightDistance}, SourcePosition={SourcePosition}, SourceOffset={SourceOffset}, IsActive={IsActive}, IsDestroyed={IsDestroyed}]"; - } - - /// <summary> - /// Spawns a <see cref="Hazard"/> at specified position with specified rotation and scale. - /// </summary> - /// <param name="prefab">The target prefab.</param> - /// <param name="position">The target position to spawn this hazard at.</param> - /// <param name="rotation">The target rotation to spawn this hazard with.</param> - /// <param name="scale">The target scale to spawn with.</param> - /// <returns>A new hazard.</returns> - public static Hazard Spawn(EnvironmentalHazard prefab, Vector3 position, Quaternion rotation, Vector3 scale) + /// <param name="hazard">The base object.</param> + /// <returns>The newly created wrapper.</returns> + protected static Hazard? CreateItemWrapper(EnvironmentalHazard hazard) { - EnvironmentalHazard hazard = GameObject.Instantiate(prefab); - hazard.transform.SetPositionAndRotation(position, rotation); - hazard.transform.localScale = scale; + Type targetType = hazard.GetType(); + if (!TypeWrappers.TryGetValue(targetType, out Func<EnvironmentalHazard, Hazard> ctorFunc)) + { +#if DEBUG + Logger.Warn($"Unable to find {nameof(Hazard)} wrapper for {targetType.Name}, backup up to base constructor!"); +#endif + return new Hazard(hazard); + } - return Get(hazard); + return ctorFunc.Invoke(hazard); } /// <summary> /// Attempts to get the prefab from <see cref="NetworkClient.prefabs"/>. /// </summary> /// <typeparam name="T">Type of the hazard.</typeparam> - /// <returns>Prefab <see cref="GameObject"/> if it was found. Otherwise <see langword="null"/></returns> - protected static T? GetPrefab<T>() where T : EnvironmentalHazard + /// <returns>Prefab <see cref="GameObject"/> if it was found. Otherwise <see langword="null"/>.</returns> + protected static T? GetPrefab<T>() + where T : EnvironmentalHazard { foreach (GameObject prefab in NetworkClient.prefabs.Values) { if (!prefab.TryGetComponent(out T hazard)) + { continue; + } return hazard; } @@ -183,22 +159,6 @@ public static Hazard Spawn(EnvironmentalHazard prefab, Vector3 position, Quatern return null; } - /// <summary> - /// Gets whether the player is in the hazard area. - /// </summary> - /// <param name="player">Target player to check on.</param> - /// <returns>Whether the player is within hazard area.</returns> - public bool IsInArea(Player player) => Base.IsInArea(SourcePosition, player.Position); - - /// <summary> - /// Destroys this hazard. - /// </summary> - public virtual void Destroy() - { - if (Base.gameObject != null) - NetworkServer.Destroy(Base.gameObject); - } - /// <summary> /// A private method to handle the creation of new hazards in the server. /// </summary> @@ -206,7 +166,9 @@ public virtual void Destroy() private static void AddHazard(EnvironmentalHazard hazard) { if (!Dictionary.ContainsKey(hazard)) + { _ = CreateItemWrapper(hazard); + } } /// <summary> @@ -226,71 +188,125 @@ private static void RemoveHazard(EnvironmentalHazard hazard) /// </summary> /// <typeparam name="T">The derived base game type to handle.</typeparam> /// <param name="constructor">A handler to construct the wrapper with the base game instance.</param> - private static void Register<T>(Func<T, Hazard> constructor) where T : EnvironmentalHazard + private static void Register<T>(Func<T, Hazard> constructor) + where T : EnvironmentalHazard { - typeWrappers.Add(typeof(T), x => constructor((T)x)); + TypeWrappers.Add(typeof(T), x => constructor((T)x)); } /// <summary> - /// Creates a new wrapper from the base envronental hazard object. + /// Initializes the <see cref="Hazard"/> class to subscribe to <see cref="EnvironmentalHazard"/> events and handle the item caching. /// </summary> - /// <param name="hazard">The base object.</param> - /// <returns>The newly created wrapper.</returns> - protected static Hazard? CreateItemWrapper(EnvironmentalHazard hazard) + /// <param name="hazard">The base game hazard component.</param> + protected Hazard(EnvironmentalHazard hazard) { - Type targetType = hazard.GetType(); - if (!typeWrappers.TryGetValue(targetType, out Func<EnvironmentalHazard, Hazard> ctorFunc)) + Base = hazard; + + if (CanCache) { -#if DEBUG - Logger.Warn($"Unable to find {nameof(Hazard)} wrapper for {targetType.Name}, backup up to base constructor!"); -#endif - return new Hazard(hazard); + Dictionary.Add(hazard, this); } + } - return ctorFunc.Invoke(hazard); + /// <summary> + /// Base game object. + /// </summary> + public EnvironmentalHazard Base { get; private set; } + + /// <summary> + /// Gets all affected players by this hazard. + /// </summary> + public IEnumerable<Player> AffectedPlayers => Base.AffectedPlayers.Select(n => Player.Get(n)); + + /// <summary> + /// Gets or sets the maximum distance players have to be at, for this hazard to affect them. + /// </summary> + public float MaxDistance + { + get => Base.MaxDistance; + set => Base.MaxDistance = value; } /// <summary> - /// Gets the hazard wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="EnvironmentalHazard"/> was not <see langword="null"/>. + /// Gets or sets the maximum height players have to be at, for this hazard to affect them. /// </summary> - /// <param name="hazard">The <see cref="Base"/> of the hazard.</param> - /// <returns>The requested hazard or <see langword="null"/>.</returns> - [return: NotNullIfNotNull(nameof(hazard))] - public static Hazard? Get(EnvironmentalHazard? hazard) + public float MaxHeightDistance { - if (hazard == null) - return null; + get => Base.MaxHeightDistance; + set => Base.MaxHeightDistance = value; + } - return Dictionary.TryGetValue(hazard, out Hazard wrapper) ? wrapper : CreateItemWrapper(hazard); + /// <summary> + /// Gets or sets the offset applied to the <see cref="SourcePosition"/>. + /// </summary> + public virtual Vector3 SourceOffset + { + get => Base.SourceOffset; + set => Base.SourceOffset = value; } + /// <summary> + /// Gets whether this environmental hazard and it's effects is enabled. + /// Setting to false also stops the decay of temporary hazards. + /// </summary> + public virtual bool IsActive + { + get => Base.IsActive; + set => Base.IsActive = value; + } /// <summary> - /// Tries to get the hazard wrapper from the <see cref="Dictionary"/>. + /// Gets or sets the origin point from which the AoE effect will start. /// </summary> - /// <param name="envHazard">The <see cref="Base"/> of the hazard.</param> - /// <param name="wrapper">The requested hazard.</param> - /// <returns><see langword="true"/> if the item exists, otherwise <see langword="false"/>.</returns> - public static bool TryGet(EnvironmentalHazard? envHazard, [NotNullWhen(true)] out Hazard? wrapper) + public virtual Vector3 SourcePosition { - wrapper = Get(envHazard); - return wrapper != null; + get => Base.SourcePosition; + set => Base.SourcePosition = value; } /// <summary> - /// Gets all hazards in a specified room. + /// Gets whether the hazard is destroyed. /// </summary> - /// <param name="room">The target room to check on.</param> - /// <returns>Hazards in specified room.</returns> - public static IEnumerable<Hazard> Get(Room? room) + public bool IsDestroyed => Base == null || Base.gameObject == null; + + /// <summary> + /// Gets the room in which this hazard is in. + /// </summary> + public Room? Room => Room.GetRoomAtPosition(SourcePosition); + + /// <summary> + /// Whether to cache the wrapper. + /// </summary> + protected bool CanCache => !IsDestroyed && Base.isActiveAndEnabled; + + /// <inheritdoc /> + public override string ToString() { - if (room == null) - yield break; + return $"[{GetType().Name}: MaxDistance={MaxDistance}, MaxHeightDistance={MaxHeightDistance}, SourcePosition={SourcePosition}, SourceOffset={SourceOffset}, IsActive={IsActive}, IsDestroyed={IsDestroyed}]"; + } - foreach (Hazard hazard in List) + /// <summary> + /// Gets whether the player is in the hazard area. + /// </summary> + /// <param name="player">Target player to check on.</param> + /// <returns>Whether the player is within hazard area.</returns> + public bool IsInArea(Player player) => Base.IsInArea(SourcePosition, player.Position); + + /// <summary> + /// Destroys this hazard. + /// </summary> + public virtual void Destroy() + { + if (Base.gameObject != null) { - if (hazard.Room == room) - yield return hazard; + NetworkServer.Destroy(Base.gameObject); } } + + /// <summary> + /// An internal virtual method to signal to derived implementations to uncache when the base object is destroyed. + /// </summary> + internal virtual void OnRemove() + { + } } \ No newline at end of file From 95d8e752557c4d4495bc065fa6f2af8bc423ac51 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:43:37 +0930 Subject: [PATCH 099/215] sinkhole --- .../Facility/Hazards/SinkholeHazard.cs | 72 ++++++++++--------- 1 file changed, 39 insertions(+), 33 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Hazards/SinkholeHazard.cs b/LabApi/Features/Wrappers/Facility/Hazards/SinkholeHazard.cs index 8e563a2e..9cd1eb3f 100644 --- a/LabApi/Features/Wrappers/Facility/Hazards/SinkholeHazard.cs +++ b/LabApi/Features/Wrappers/Facility/Hazards/SinkholeHazard.cs @@ -1,8 +1,8 @@ using Hazards; -using System.Collections.Generic; -using UnityEngine; using Mirror; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using UnityEngine; namespace LabApi.Features.Wrappers; @@ -15,7 +15,7 @@ public class SinkholeHazard : Hazard /// <summary> /// Contains all the cached items, accessible through their <see cref="Base"/>. /// </summary> - public new static Dictionary<SinkholeEnvironmentalHazard, SinkholeHazard> Dictionary { get; } = []; + public static new Dictionary<SinkholeEnvironmentalHazard, SinkholeHazard> Dictionary { get; } = []; /// <summary> /// Gets all currently active sinkholes. @@ -25,34 +25,7 @@ public class SinkholeHazard : Hazard /// <summary> /// Prefab used to spawn the hazard. /// </summary> - protected static new SinkholeEnvironmentalHazard? BasePrefab; - - /// <summary> - /// The base object. - /// </summary> - public new SinkholeEnvironmentalHazard Base { get; } - - /// <summary> - /// An internal constructor to prevent external instantiation. - /// </summary> - /// <param name="hazard">The base <see cref="SinkholeEnvironmentalHazard"/> object.</param> - internal SinkholeHazard(SinkholeEnvironmentalHazard hazard) - : base(hazard) - { - Base = hazard; - - if (CanCache) - Dictionary.Add(hazard, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); - } + protected static new SinkholeEnvironmentalHazard? BasePrefab { get; private set; } /// <summary> /// Spawns a <see cref="SinkholeHazard"/> at specified position with specified rotation and scale. @@ -65,9 +38,11 @@ internal override void OnRemove() public static SinkholeHazard Spawn(Vector3 position, Quaternion rotation, Vector3 scale) { if (BasePrefab == null) + { BasePrefab = GetPrefab<SinkholeEnvironmentalHazard>(); + } - SinkholeHazard hazard = (SinkholeHazard)Hazard.Spawn(BasePrefab, position, rotation, scale); + SinkholeHazard hazard = (SinkholeHazard)Hazard.Spawn(BasePrefab!, position, rotation, scale); hazard.IsActive = true; return hazard; } @@ -81,8 +56,39 @@ public static SinkholeHazard Spawn(Vector3 position, Quaternion rotation, Vector public static SinkholeHazard? Get(SinkholeEnvironmentalHazard? hazard) { if (hazard == null) + { return null; + } + + return Dictionary.TryGetValue(hazard, out SinkholeHazard sinkhole) ? sinkhole : (SinkholeHazard)CreateItemWrapper(hazard)!; + } - return Dictionary.TryGetValue(hazard, out SinkholeHazard sinkhole) ? sinkhole : (SinkholeHazard)CreateItemWrapper(hazard); + /// <summary> + /// An internal constructor to prevent external instantiation. + /// </summary> + /// <param name="hazard">The base <see cref="SinkholeEnvironmentalHazard"/> object.</param> + internal SinkholeHazard(SinkholeEnvironmentalHazard hazard) + : base(hazard) + { + Base = hazard; + + if (CanCache) + { + Dictionary.Add(hazard, this); + } + } + + /// <summary> + /// The base object. + /// </summary> + public new SinkholeEnvironmentalHazard Base { get; } + + /// <summary> + /// An internal method to remove itself from the cache when the base object is destroyed. + /// </summary> + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); } } \ No newline at end of file From 945aa9eda506bf53b528740aefb8ccc56d67bc52 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:43:44 +0930 Subject: [PATCH 100/215] tantrum --- .../Facility/Hazards/TantrumHazard.cs | 98 ++++++++++--------- 1 file changed, 52 insertions(+), 46 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Hazards/TantrumHazard.cs b/LabApi/Features/Wrappers/Facility/Hazards/TantrumHazard.cs index 4f9ed6b5..e87ba27b 100644 --- a/LabApi/Features/Wrappers/Facility/Hazards/TantrumHazard.cs +++ b/LabApi/Features/Wrappers/Facility/Hazards/TantrumHazard.cs @@ -13,44 +13,53 @@ public class TantrumHazard : DecayableHazard /// <summary> /// Contains all the cached items, accessible through their <see cref="Base"/>. /// </summary> - public new static Dictionary<TantrumEnvironmentalHazard, TantrumHazard> Dictionary { get; } = []; + public static new Dictionary<TantrumEnvironmentalHazard, TantrumHazard> Dictionary { get; } = []; /// <summary> /// Gets all currently active tantrum hazards. /// </summary> - public new IReadOnlyCollection<TantrumHazard> List => Dictionary.Values; + public static new IReadOnlyCollection<TantrumHazard> List => Dictionary.Values; /// <summary> /// Prefab used to spawn the hazard. /// </summary> - protected static new TantrumEnvironmentalHazard? BasePrefab; + protected static new TantrumEnvironmentalHazard? BasePrefab { get; private set; } /// <summary> - /// Gets or sets the world position of the hazard as it is synchronized with the client. - /// Note that this value is slightly inaccurate and is purely for visual effects.<br/> - /// For actual world position used to calculate whether the player is inside of this hazard use <see cref="Hazard.SourcePosition"/>. + /// Spawns a <see cref="TantrumHazard"/> at specified position with specified rotation and scale. + /// <para> Do note that changing scale doesn't change the effect size. Use the <see cref="Hazard.MaxDistance"/> and <see cref="Hazard.MaxHeightDistance"/> to match the visual size.</para> /// </summary> - public Vector3 SyncedPosition + /// <param name="position">The target position to spawn this hazard at.</param> + /// <param name="rotation">The target rotation to spawn this hazard with.</param> + /// <param name="scale">The target scale to spawn with.</param> + /// <returns>A new tantrum hazard.</returns> + public static TantrumHazard Spawn(Vector3 position, Quaternion rotation, Vector3 scale) { - get => Base.SynchronizedPosition.Position; - set => Base.SynchronizedPosition = new RelativePositioning.RelativePosition(value); + if (BasePrefab == null) + { + BasePrefab = Hazard.GetPrefab<TantrumEnvironmentalHazard>(); + } + + TantrumHazard hazard = (TantrumHazard)Hazard.Spawn(BasePrefab!, position, rotation, scale); + hazard.SyncedPosition = position; + return hazard; } /// <summary> - /// Gets or sets whether a slight sizzle sound effect will be played when this object is destroyed. - /// It is played by default if the tantrum gets destroyed by an explosion or by <see cref="Tesla"/>.<br/> - /// Note that this state may change right before it is destroyed by standard game means. + /// Gets the hazard wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="TantrumEnvironmentalHazard"/> was not <see langword="null"/>. /// </summary> - public bool PlaySizzle + /// <param name="hazard">The <see cref="Base"/> of the hazard.</param> + /// <returns>The requested hazard or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(hazard))] + public static TantrumHazard? Get(TantrumEnvironmentalHazard? hazard) { - get => Base.PlaySizzle; - set => Base.PlaySizzle = value; - } + if (hazard == null) + { + return null; + } - /// <summary> - /// The base object. - /// </summary> - public new TantrumEnvironmentalHazard Base { get; } + return Dictionary.TryGetValue(hazard, out TantrumHazard decHazard) ? decHazard : (TantrumHazard)CreateItemWrapper(hazard)!; + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -62,47 +71,44 @@ internal TantrumHazard(TantrumEnvironmentalHazard hazard) Base = hazard; if (CanCache) + { Dictionary.Add(hazard, this); + } } /// <summary> - /// Spawns a <see cref="TantrumHazard"/> at specified position with specified rotation and scale. - /// <para> Do note that changing scale doesn't change the effect size. Use the <see cref="Hazard.MaxDistance"/> and <see cref="Hazard.MaxHeightDistance"/> to match the visual size.</para> + /// Gets or sets the world position of the hazard as it is synchronized with the client. + /// Note that this value is slightly inaccurate and is purely for visual effects.<br/> + /// For actual world position used to calculate whether the player is inside of this hazard use <see cref="Hazard.SourcePosition"/>. /// </summary> - /// <param name="position">The target position to spawn this hazard at.</param> - /// <param name="rotation">The target rotation to spawn this hazard with.</param> - /// <param name="scale">The target scale to spawn with.</param> - /// <returns>A new tantrum hazard.</returns> - public static TantrumHazard Spawn(Vector3 position, Quaternion rotation, Vector3 scale) + public Vector3 SyncedPosition { - if (BasePrefab == null) - BasePrefab = Hazard.GetPrefab<TantrumEnvironmentalHazard>(); - - TantrumHazard hazard = (TantrumHazard)Hazard.Spawn(BasePrefab, position, rotation, scale); - hazard.SyncedPosition = position; - return hazard; + get => Base.SynchronizedPosition.Position; + set => Base.SynchronizedPosition = new RelativePositioning.RelativePosition(value); } /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. + /// Gets or sets whether a slight sizzle sound effect will be played when this object is destroyed. + /// It is played by default if the tantrum gets destroyed by an explosion or by <see cref="Tesla"/>.<br/> + /// Note that this state may change right before it is destroyed by standard game means. /// </summary> - internal override void OnRemove() + public bool PlaySizzle { - base.OnRemove(); - Dictionary.Remove(Base); + get => Base.PlaySizzle; + set => Base.PlaySizzle = value; } /// <summary> - /// Gets the hazard wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="TantrumEnvironmentalHazard"/> was not <see langword="null"/>. + /// The base object. /// </summary> - /// <param name="hazard">The <see cref="Base"/> of the hazard.</param> - /// <returns>The requested hazard or <see langword="null"/>.</returns> - [return: NotNullIfNotNull(nameof(hazard))] - public static TantrumHazard? Get(TantrumEnvironmentalHazard? hazard) - { - if (hazard == null) - return null; + public new TantrumEnvironmentalHazard Base { get; } - return Dictionary.TryGetValue(hazard, out TantrumHazard decHazard) ? decHazard : (TantrumHazard)CreateItemWrapper(hazard); + /// <summary> + /// An internal method to remove itself from the cache when the base object is destroyed. + /// </summary> + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); } } \ No newline at end of file From d59d720a106157aea27c093dc424953726dfec9c Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:43:49 +0930 Subject: [PATCH 101/215] tesla --- .../Wrappers/Facility/Hazards/Tesla.cs | 96 +++++++++---------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Hazards/Tesla.cs b/LabApi/Features/Wrappers/Facility/Hazards/Tesla.cs index 42908351..ec0eeb1d 100644 --- a/LabApi/Features/Wrappers/Facility/Hazards/Tesla.cs +++ b/LabApi/Features/Wrappers/Facility/Hazards/Tesla.cs @@ -1,9 +1,9 @@ -using System.Collections.Generic; +using Generators; +using MapGeneration; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using UnityEngine; using Utils.NonAllocLINQ; -using Generators; -using MapGeneration; namespace LabApi.Features.Wrappers; @@ -17,15 +17,58 @@ public class Tesla /// </summary> public static Dictionary<TeslaGate, Tesla> Dictionary { get; } = []; + /// <summary> + /// A reference to all instances of <see cref="Tesla"/>. + /// </summary> + public static IReadOnlyCollection<Tesla> List => Dictionary.Values; + /// <summary> /// Cached tesla gates by <see cref="Room"/> they are in. /// </summary> private static Dictionary<RoomIdentifier, Tesla> TeslaByRoom { get; } = []; /// <summary> - /// A reference to all instances of <see cref="Tesla"/>. + /// Gets the tesla wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist. /// </summary> - public static IReadOnlyCollection<Tesla> List => Dictionary.Values; + /// <param name="teslaGate">The <see cref="TeslaGate"/> of the tesla.</param> + /// <returns>The requested tesla.</returns> + public static Tesla Get(TeslaGate teslaGate) => Dictionary.TryGetValue(teslaGate, out Tesla tesla) ? tesla : new Tesla(teslaGate); + + /// <summary> + /// Gets the tesla wrapper inside of <see cref="Room"/> from the <see cref="TeslaByRoom"/>. + /// </summary> + /// <param name="room">The <see cref="Room"/> with the tesla.</param> + /// <param name="tesla">The tesla to be returned.</param> + /// <returns>Whether the tesla is in out parameter.</returns> + public static bool TryGet(Room room, [NotNullWhen(true)] out Tesla? tesla) + => TeslaByRoom.TryGetValue(room.Base, out tesla); + + /// <summary> + /// Initializes the <see cref="Tesla"/> class to subscribe to <see cref="TeslaGate"/> events and handle the tesla caching. + /// </summary> + [InitializeWrapper] + internal static void Initialize() + { + Dictionary.Clear(); + TeslaByRoom.Clear(); + TeslaGate.OnAdded += (tesla) => _ = new Tesla(tesla); + TeslaGate.OnRemoved += (tesla) => + { + Dictionary.Remove(tesla); + TeslaByRoom.Remove(tesla.Room); + }; + } + + /// <summary> + /// A private constructor to prevent external instantiation. + /// </summary> + /// <param name="tesla">The <see cref="TeslaGate"/> of the item.</param> + private Tesla(TeslaGate tesla) + { + Dictionary.Add(tesla, this); + TeslaByRoom.Add(tesla.Room, this); + Base = tesla; + } /// <summary> /// The base of the tesla. @@ -103,47 +146,4 @@ public float InactiveTime /// Tesla gate instant burst. /// </summary> public void InstantTrigger() => Base.RpcInstantBurst(); - - /// <summary> - /// Initializes the <see cref="Tesla"/> class to subscribe to <see cref="TeslaGate"/> events and handle the tesla caching. - /// </summary> - [InitializeWrapper] - internal static void Initialize() - { - Dictionary.Clear(); - TeslaByRoom.Clear(); - TeslaGate.OnAdded += (tesla) => _ = new Tesla(tesla); - TeslaGate.OnRemoved += (tesla) => - { - Dictionary.Remove(tesla); - TeslaByRoom.Remove(tesla.Room); - }; - } - - /// <summary> - /// A private constructor to prevent external instantiation. - /// </summary> - /// <param name="tesla">The <see cref="TeslaGate"/> of the item.</param> - private Tesla(TeslaGate tesla) - { - Dictionary.Add(tesla, this); - TeslaByRoom.Add(tesla.Room, this); - Base = tesla; - } - - /// <summary> - /// Gets the tesla wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist. - /// </summary> - /// <param name="teslaGate">The <see cref="TeslaGate"/> of the tesla.</param> - /// <returns>The requested tesla.</returns> - public static Tesla Get(TeslaGate teslaGate) => Dictionary.TryGetValue(teslaGate, out Tesla tesla) ? tesla : new Tesla(teslaGate); - - /// <summary> - /// Gets the tesla wrapper inside of <see cref="Room"/> from the <see cref="TeslaByRoom"/>. - /// </summary> - /// <param name="room">The <see cref="Room"/> with the tesla.</param> - /// <param name="tesla">The tesla to be returned.</param> - /// <returns>Whether the tesla is in out parameter.</returns> - public static bool TryGet(Room room, [NotNullWhen(true)] out Tesla? tesla) - => TeslaByRoom.TryGetValue(room.Base, out tesla); } \ No newline at end of file From 02d1512eb0dad75fe09ce20f1890550c4fd4a5c6 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:43:58 +0930 Subject: [PATCH 102/215] waves --- .../Facility/Respawning/RespawnWaves.cs | 27 ++++++++++--------- .../Facility/Respawning/Waves/ChaosWave.cs | 11 +++++--- .../Respawning/Waves/MiniChaosWave.cs | 7 ++--- .../Facility/Respawning/Waves/MiniMtfWave.cs | 8 +++--- .../Respawning/Waves/MiniRespawnWave.cs | 9 +++++-- .../Facility/Respawning/Waves/MtfWave.cs | 7 +++-- .../Facility/Respawning/Waves/RespawnWave.cs | 15 ++++++++--- 7 files changed, 53 insertions(+), 31 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Respawning/RespawnWaves.cs b/LabApi/Features/Wrappers/Facility/Respawning/RespawnWaves.cs index 323b1379..ec689e05 100644 --- a/LabApi/Features/Wrappers/Facility/Respawning/RespawnWaves.cs +++ b/LabApi/Features/Wrappers/Facility/Respawning/RespawnWaves.cs @@ -1,6 +1,6 @@ -using Respawning; +using Generators; +using Respawning; using Respawning.Waves; -using Generators; namespace LabApi.Features.Wrappers; @@ -29,16 +29,6 @@ public static class RespawnWaves /// </summary> public static MiniChaosWave? MiniChaosWave { get; private set; } - /// <summary> - /// Initializes the <see cref="RespawnWaves"/> wrapper and its wave wrapper instances. - /// </summary> - [InitializeWrapper] - internal static void Initialize() - { - foreach (SpawnableWaveBase wave in WaveManager.Waves) - Get(wave); - } - /// <summary> /// Gets the respawn wave wrapper from the static references or creates a new one if it doesn't exist and the provided <see cref="SpawnableWaveBase"/> was not <see langword="null"/> or not valid subclass. /// </summary> @@ -55,5 +45,16 @@ internal static void Initialize() _ => null, }; } -} + /// <summary> + /// Initializes the <see cref="RespawnWaves"/> wrapper and its wave wrapper instances. + /// </summary> + [InitializeWrapper] + internal static void Initialize() + { + foreach (SpawnableWaveBase wave in WaveManager.Waves) + { + Get(wave); + } + } +} diff --git a/LabApi/Features/Wrappers/Facility/Respawning/Waves/ChaosWave.cs b/LabApi/Features/Wrappers/Facility/Respawning/Waves/ChaosWave.cs index e7295052..d6389454 100644 --- a/LabApi/Features/Wrappers/Facility/Respawning/Waves/ChaosWave.cs +++ b/LabApi/Features/Wrappers/Facility/Respawning/Waves/ChaosWave.cs @@ -8,18 +8,20 @@ namespace LabApi.Features.Wrappers; /// </summary> public class ChaosWave : RespawnWave { - /// <inheritdoc/> - internal ChaosWave(ChaosSpawnWave wave) : base(wave) + /// <inheritdoc cref="RespawnWave(TimeBasedWave)"/> + internal ChaosWave(ChaosSpawnWave wave) + : base(wave) { Base = wave; } + /// <summary> /// The base <see cref="ChaosSpawnWave"/> object. /// </summary> public new ChaosSpawnWave Base { get; private set; } /// <summary> - /// Percentage of chaos supressors per wave. + /// Percentage of chaos suppressors per wave. /// </summary> public float LogicerPercent { @@ -44,8 +46,9 @@ public override int MaxWaveSize { float percentageValue = (float)value / ReferenceHub.AllHubs.Count; if (Base.Configuration is PrimaryWaveConfig<ChaosSpawnWave> config) + { config.SizePercentage = percentageValue; + } } } } - diff --git a/LabApi/Features/Wrappers/Facility/Respawning/Waves/MiniChaosWave.cs b/LabApi/Features/Wrappers/Facility/Respawning/Waves/MiniChaosWave.cs index dde945a3..d1a8fd84 100644 --- a/LabApi/Features/Wrappers/Facility/Respawning/Waves/MiniChaosWave.cs +++ b/LabApi/Features/Wrappers/Facility/Respawning/Waves/MiniChaosWave.cs @@ -7,12 +7,13 @@ namespace LabApi.Features.Wrappers; /// </summary> public class MiniChaosWave : MiniRespawnWave { - /// <inheritdoc/> - internal MiniChaosWave(ChaosMiniWave miniWave) : base(miniWave) + /// <inheritdoc cref="MiniRespawnWave(IMiniWave)"/> + internal MiniChaosWave(ChaosMiniWave miniWave) + : base(miniWave) { Base = miniWave; } - /// <inheritdoc/> + /// <inheritdoc cref="MiniRespawnWave.Base"/> public new ChaosMiniWave Base { get; private set; } } diff --git a/LabApi/Features/Wrappers/Facility/Respawning/Waves/MiniMtfWave.cs b/LabApi/Features/Wrappers/Facility/Respawning/Waves/MiniMtfWave.cs index d7f85c8d..2939edf4 100644 --- a/LabApi/Features/Wrappers/Facility/Respawning/Waves/MiniMtfWave.cs +++ b/LabApi/Features/Wrappers/Facility/Respawning/Waves/MiniMtfWave.cs @@ -7,13 +7,13 @@ namespace LabApi.Features.Wrappers; /// </summary> public class MiniMtfWave : MiniRespawnWave { - /// <inheritdoc/> - internal MiniMtfWave(NtfMiniWave miniWave) : base(miniWave) + /// <inheritdoc cref="MiniRespawnWave(IMiniWave)"/> + internal MiniMtfWave(NtfMiniWave miniWave) + : base(miniWave) { Base = miniWave; } - /// <inheritdoc/> + /// <inheritdoc cref="MiniRespawnWave.Base"/> public new NtfMiniWave Base { get; private set; } } - diff --git a/LabApi/Features/Wrappers/Facility/Respawning/Waves/MiniRespawnWave.cs b/LabApi/Features/Wrappers/Facility/Respawning/Waves/MiniRespawnWave.cs index bea28b4f..0008344e 100644 --- a/LabApi/Features/Wrappers/Facility/Respawning/Waves/MiniRespawnWave.cs +++ b/LabApi/Features/Wrappers/Facility/Respawning/Waves/MiniRespawnWave.cs @@ -12,7 +12,8 @@ public abstract class MiniRespawnWave : RespawnWave /// Internal constructor preventing external instantiation. /// </summary> /// <param name="miniWave">The base game object.</param> - internal MiniRespawnWave(IMiniWave miniWave) : base((TimeBasedWave)miniWave) + internal MiniRespawnWave(IMiniWave miniWave) + : base((TimeBasedWave)miniWave) { Base = miniWave; } @@ -28,14 +29,19 @@ public override int MaxWaveSize get { if (Base is TimeBasedWave baseWave) + { return baseWave.MaxWaveSize; + } return 0; } + set { if (value < 0) + { return; + } float percentageValue = (float)value / ReferenceHub.AllHubs.Count; Base.WaveSizeMultiplier = percentageValue; @@ -77,4 +83,3 @@ public override void InitiateRespawn() /// </summary> public virtual void Lock() => Base.ResetTokens(); } - diff --git a/LabApi/Features/Wrappers/Facility/Respawning/Waves/MtfWave.cs b/LabApi/Features/Wrappers/Facility/Respawning/Waves/MtfWave.cs index b4e7c58f..cfc94fbb 100644 --- a/LabApi/Features/Wrappers/Facility/Respawning/Waves/MtfWave.cs +++ b/LabApi/Features/Wrappers/Facility/Respawning/Waves/MtfWave.cs @@ -8,8 +8,9 @@ namespace LabApi.Features.Wrappers; /// </summary> public class MtfWave : RespawnWave { - /// <inheritdoc/> - internal MtfWave(NtfSpawnWave wave) : base(wave) + /// <inheritdoc cref="RespawnWave(TimeBasedWave)"/> + internal MtfWave(NtfSpawnWave wave) + : base(wave) { Base = wave; } @@ -45,7 +46,9 @@ public override int MaxWaveSize { float percentageValue = (float)value / ReferenceHub.AllHubs.Count; if (Base.Configuration is PrimaryWaveConfig<NtfSpawnWave> config) + { config.SizePercentage = percentageValue; + } } } } \ No newline at end of file diff --git a/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs b/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs index 52246ae7..a7c9feb4 100644 --- a/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs +++ b/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs @@ -53,7 +53,9 @@ public float AnimationTime get { if (Base is IAnimatedWave wave) + { return wave.AnimationDuration; + } return 0f; } @@ -67,14 +69,19 @@ public int RespawnTokens get { if (Base is ILimitedWave wave) + { return wave.RespawnTokens; + } return 0; } + set { if (Base is not ILimitedWave wave) + { return; + } wave.RespawnTokens = value; WaveUpdateMessage.ServerSendUpdate(Base, UpdateMessageFlags.Tokens); @@ -117,12 +124,12 @@ public float PausedTime public float TimePassed => Base.Timer.TimePassed; /// <summary> - /// Attempts to get milestone for next <see cref="RespawnTokens"/>. + /// Attempts to get milestone for next <see cref="RespawnTokens"/>. /// Returns <see langword="false"/> if this <see cref="Faction"/> has maximum influence possible. /// </summary> - /// <param name="influenceTreshold">Out param containing next target influence.</param> + /// <param name="influenceThreshold">Out param containing next target influence.</param> /// <returns>Whether there is next available milestone.</returns> - public bool TryGetCurrentMilestone(out int influenceTreshold) => RespawnTokensManager.TryGetNextThreshold(Faction, Influence, out influenceTreshold); + public bool TryGetCurrentMilestone(out int influenceThreshold) => RespawnTokensManager.TryGetNextThreshold(Faction, Influence, out influenceThreshold); /// <summary> /// Initiates the respawn with animation. @@ -140,6 +147,8 @@ public float PausedTime public void PlayAnnouncement() { if (Base is IAnnouncedWave wave) + { wave.Announcement.PlayAnnouncement(); + } } } From 29c19d2470588373a4898f950a16977b621f5fb5 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:44:08 +0930 Subject: [PATCH 103/215] pocket dimension --- .../Rooms/PocketDimension/PocketDimension.cs | 56 ++++++----- .../Rooms/PocketDimension/PocketItem.cs | 92 ++++++++++--------- .../Rooms/PocketDimension/PocketTeleport.cs | 89 +++++++++--------- 3 files changed, 127 insertions(+), 110 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Rooms/PocketDimension/PocketDimension.cs b/LabApi/Features/Wrappers/Facility/Rooms/PocketDimension/PocketDimension.cs index af10e71b..de4d55c3 100644 --- a/LabApi/Features/Wrappers/Facility/Rooms/PocketDimension/PocketDimension.cs +++ b/LabApi/Features/Wrappers/Facility/Rooms/PocketDimension/PocketDimension.cs @@ -48,7 +48,7 @@ public static float MinPocketItemTriggerDelay get => Scp106PocketItemManager.TimerRange.x; set => Scp106PocketItemManager.TimerRange = Scp106PocketItemManager.TimerRange with { - x = value + x = value, }; } @@ -60,30 +60,10 @@ public static float MaxPocketItemTriggerDelay get => Scp106PocketItemManager.TimerRange.y; set => Scp106PocketItemManager.TimerRange = Scp106PocketItemManager.TimerRange with { - y = value + y = value, }; } - /// <summary> - /// An internal constructor to prevent external instantiation. - /// </summary> - /// <param name="room">The room identifier for the pocket dimension.</param> - internal PocketDimension(RoomIdentifier room) - : base(room) - { - if (CanCache) - Instance = this; - } - - /// <summary> - /// An internal method to set the instance to null when the base object is destroyed. - /// </summary> - internal override void OnRemoved() - { - base.OnRemoved(); - Instance = null; - } - /// <summary> /// Force a <see cref="Player"/> inside the pocket dimension. /// </summary> @@ -107,7 +87,9 @@ public static Vector3 GetCaughtPosition(Player player) PocketCorroding? effect = player.GetEffect<PocketCorroding>(); if (effect != null && effect.Intensity > 0) + { return effect.CapturePosition.Position; + } return Vector3.zero; } @@ -143,7 +125,7 @@ public static bool IsPickupInside(Pickup pickup) => Scp106PocketItemManager.TrackedItems.ContainsKey(pickup.Base); /// <summary> - /// Randomizes which pocket dimension's teleports are exits. + /// Randomizes which pocket dimension's teleports are exits. /// </summary> public static void RandomizeExits() => PocketDimensionGenerator.RandomizeTeleports(); @@ -164,9 +146,11 @@ public static void AddExitPosesForZone(FacilityZone zone, IEnumerable<Pose> pose { // Attempts to generate the pose array as it could be empty. if (!Scp106PocketExitFinder.PosesForZoneCache.ContainsKey(zone)) + { Scp106PocketExitFinder.GetPosesForZone(zone); + } - Scp106PocketExitFinder.PosesForZoneCache[zone] = Scp106PocketExitFinder.PosesForZoneCache[zone].Concat(poses).ToArray(); + Scp106PocketExitFinder.PosesForZoneCache[zone] = [.. Scp106PocketExitFinder.PosesForZoneCache[zone], .. poses]; } /// <summary> @@ -192,7 +176,9 @@ public static void RemoveExitPosesForZone(FacilityZone zone, IEnumerable<Pose> p { // Attempts to generate the pose array as it could be empty. if (!Scp106PocketExitFinder.PosesForZoneCache.ContainsKey(zone)) + { Scp106PocketExitFinder.GetPosesForZone(zone); + } Scp106PocketExitFinder.PosesForZoneCache[zone] = Scp106PocketExitFinder.PosesForZoneCache[zone].Except(poses).ToArray(); } @@ -226,4 +212,26 @@ public static int GetRarity(Pickup pickup) /// <returns>The rarity of the item.</returns> public static int GetRarity(ItemBase item) => Scp106PocketItemManager.GetRarity(item); + + /// <summary> + /// An internal constructor to prevent external instantiation. + /// </summary> + /// <param name="room">The room identifier for the pocket dimension.</param> + internal PocketDimension(RoomIdentifier room) + : base(room) + { + if (CanCache) + { + Instance = this; + } + } + + /// <summary> + /// An internal method to set the instance to null when the base object is destroyed. + /// </summary> + internal override void OnRemoved() + { + base.OnRemoved(); + Instance = null; + } } diff --git a/LabApi/Features/Wrappers/Facility/Rooms/PocketDimension/PocketItem.cs b/LabApi/Features/Wrappers/Facility/Rooms/PocketDimension/PocketItem.cs index 161be7b1..fc9b9155 100644 --- a/LabApi/Features/Wrappers/Facility/Rooms/PocketDimension/PocketItem.cs +++ b/LabApi/Features/Wrappers/Facility/Rooms/PocketDimension/PocketItem.cs @@ -18,6 +18,52 @@ namespace LabApi.Features.Wrappers; /// </remarks> public class PocketItem { + /// <summary> + /// Contains all the cached <see cref="PocketItem"/> instances, accessible through their <see cref="ItemBase"/>. + /// </summary> + private static readonly Dictionary<ItemPickupBase, PocketItem> Dictionary = []; + + /// <summary> + /// A reference to all <see cref="PocketItem"/> instances currently in the game. + /// </summary> + public static IReadOnlyCollection<PocketItem> List => Dictionary.Values; + + /// <summary> + /// Tries to get the <see cref="PocketItem"/> associated with the <see cref="Wrappers.Pickup"/>. + /// </summary> + /// <param name="pickup">The <see cref="Wrappers.Pickup"/> inside the pocket dimension to get the <see cref="PocketItem"/> from.</param> + /// <param name="pocketItem">The <see cref="PocketItem"/> associated with <see cref="Wrappers.Pickup"/> or null if it doesn't exists.</param> + /// <returns>Whether the <see cref="PocketItem"/> was successfully retrieved.</returns> + public static bool TryGet(Pickup pickup, [NotNullWhen(true)] out PocketItem? pocketItem) + => Dictionary.TryGetValue(pickup.Base, out pocketItem); + + /// <summary> + /// Gets the <see cref="PocketItem"/> associated with the <see cref="Wrappers.Pickup"/>. + /// </summary> + /// <param name="pickup">The <see cref="Wrappers.Pickup"/> inside the pocket dimension to get the <see cref="PocketItem"/> from.</param> + /// <returns>The associated <see cref="PocketItem"/> for the <see cref="Wrappers.Pickup"/> or null if it doesn't exist.</returns> + public static PocketItem? Get(Pickup pickup) => TryGet(pickup, out PocketItem? pocketItem) ? pocketItem : null; + + /// <summary> + /// Gets or adds a <see cref="PocketItem"/>. + /// </summary> + /// <param name="pickup">The <see cref="Wrappers.Pickup"/> to get or add to the pocket dimension.</param> + /// <returns>The <see cref="PocketItem"/> instance.</returns> + /// <remarks> + /// If the pickup is not in the pocket dimension it is teleported there on creation of the <see cref="PocketItem"/>. + /// </remarks> + public static PocketItem GetOrAdd(Pickup pickup) + { + if (Dictionary.TryGetValue(pickup.Base, out PocketItem? pocketItem)) + { + return pocketItem; + } + + pickup.Position = PocketDimension.Instance!.Position + Vector3.up; + Scp106PocketItemManager.AddItem(pickup.Base); + return Get(pickup)!; + } + /// <summary> /// Initializes the PocketItem wrapper by subscribing to the PocketDimensionTeleport events. /// </summary> @@ -28,16 +74,6 @@ internal static void Initialize() Scp106PocketItemManager.OnPocketItemRemoved += (itemPickupBase) => Dictionary.Remove(itemPickupBase); } - /// <summary> - /// Contains all the cached <see cref="PocketItem"/> instances, accessible through their <see cref="ItemBase"/>. - /// </summary> - private static Dictionary<ItemPickupBase, PocketItem> Dictionary = []; - - /// <summary> - /// A reference to all <see cref="PocketItem"/> instances currently in the game. - /// </summary> - public static IReadOnlyCollection<PocketItem> List => Dictionary.Values; - /// <summary> /// An internal constructor to prevent external instantiation. /// </summary> @@ -88,41 +124,7 @@ public Vector3 DropPosition } /// <summary> - /// Gets whether a warning cue was sent to the players about a dropping item pickup. + /// Gets whether a warning cue was sent to the players about a dropping item pickup. /// </summary> public bool IsWarningSent => Base.WarningSent; - - /// <summary> - /// Tries to get the <see cref="PocketItem"/> associated with the <see cref="Wrappers.Pickup"/>. - /// </summary> - /// <param name="pickup">The <see cref="Wrappers.Pickup"/> inside the pocket dimension to get the <see cref="PocketItem"/> from.</param> - /// <param name="pocketItem">The <see cref="PocketItem"/> associated with <see cref="Wrappers.Pickup"/> or null if it doesn't exists.</param> - /// <returns>Whether the <see cref="PocketItem"/> was successfully retrieved.</returns> - public static bool TryGet(Pickup pickup, [NotNullWhen(true)] out PocketItem? pocketItem) - => Dictionary.TryGetValue(pickup.Base, out pocketItem); - - /// <summary> - /// Gets the <see cref="PocketItem"/> associated with the <see cref="Wrappers.Pickup"/>. - /// </summary> - /// <param name="pickup">The <see cref="Wrappers.Pickup"/> inside the pocket dimension to get the <see cref="PocketItem"/> from.</param> - /// <returns>The associated <see cref="PocketItem"/> for the <see cref="Wrappers.Pickup"/> or null if it doesn't exist.</returns> - public static PocketItem? Get(Pickup pickup) => TryGet(pickup, out PocketItem? pocketItem) ? pocketItem : null; - - /// <summary> - /// Gets or adds a <see cref="PocketItem"/>. - /// </summary> - /// <param name="pickup">The <see cref="Wrappers.Pickup"/> to get or add to the pocket dimension.</param> - /// <returns>The <see cref="PocketItem"/> instance.</returns> - /// <remarks> - /// If the pickup is not in the pocket dimension it is teleported there on creation of the <see cref="PocketItem"/>. - /// </remarks> - public static PocketItem GetOrAdd(Pickup pickup) - { - if (Dictionary.TryGetValue(pickup.Base, out PocketItem? pocketItem)) - return pocketItem; - - pickup.Position = PocketDimension.Instance!.Position + Vector3.up; - Scp106PocketItemManager.AddItem(pickup.Base); - return Get(pickup)!; - } } diff --git a/LabApi/Features/Wrappers/Facility/Rooms/PocketDimension/PocketTeleport.cs b/LabApi/Features/Wrappers/Facility/Rooms/PocketDimension/PocketTeleport.cs index 46160e95..2bd897dc 100644 --- a/LabApi/Features/Wrappers/Facility/Rooms/PocketDimension/PocketTeleport.cs +++ b/LabApi/Features/Wrappers/Facility/Rooms/PocketDimension/PocketTeleport.cs @@ -11,6 +11,37 @@ namespace LabApi.Features.Wrappers; /// </summary> public class PocketTeleport { + /// <summary> + /// A reference to all <see cref="PocketTeleport"/> instances currently in the game. + /// </summary> + public static IReadOnlyCollection<PocketTeleport> List => Dictionary.Values; + + /// <summary> + /// Contains all the cached teleports in the game, accessible through their <see cref="PocketDimensionTeleport"/>. + /// </summary> + private static Dictionary<PocketDimensionTeleport, PocketTeleport> Dictionary { get; } = []; + + /// <summary> + /// Gets the wrapper given the base game <see cref="PocketDimensionTeleport"/> instance. + /// </summary> + /// <param name="pocketTeleport">The base game object.</param> + /// <returns>The associated wrapper.</returns> + [return: NotNullIfNotNull(nameof(pocketTeleport))] + public static PocketTeleport? Get(PocketDimensionTeleport? pocketTeleport) + { + if (pocketTeleport == null) + { + return null; + } + + if (Dictionary.TryGetValue(pocketTeleport, out PocketTeleport pt)) + { + return pt; + } + + return new PocketTeleport(pocketTeleport); + } + /// <summary> /// Initializes the Teleport wrapper by subscribing to the PocketDimensionTeleport events. /// </summary> @@ -22,14 +53,25 @@ internal static void Initialize() } /// <summary> - /// Contains all the cached teleports in the game, accessible through their <see cref="PocketDimensionTeleport"/>. + /// A private method to handle the addition of <see cref="PocketDimensionTeleport"/> instances. /// </summary> - private static Dictionary<PocketDimensionTeleport, PocketTeleport> Dictionary { get; } = []; + /// <param name="pocketTeleport">The base game instance.</param> + private static void OnAdded(PocketDimensionTeleport pocketTeleport) + { + if (!Dictionary.ContainsKey(pocketTeleport)) + { + _ = new PocketTeleport(pocketTeleport); + } + } /// <summary> - /// A reference to all <see cref="PocketTeleport"/> instances currently in the game. + /// A private method to handle the removal of <see cref="PocketDimensionTeleport"/> instances. /// </summary> - public static IReadOnlyCollection<PocketTeleport> List => Dictionary.Values; + /// <param name="pocketTeleport">The base game instance.</param> + private static void OnRemoved(PocketDimensionTeleport pocketTeleport) + { + Dictionary.Remove(pocketTeleport); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -113,6 +155,8 @@ public float Radius /// <summary> /// Spawns a new pocket teleport. /// </summary> + /// <param name="localPosition">The position relative to the pocket dimension.</param> + /// <returns>The created <see cref="PocketTeleport"/>.</returns> public PocketTeleport Spawn(Vector3 localPosition) { GameObject obj = new("Teleport", typeof(PocketDimensionTeleport), typeof(SphereCollider), typeof(NetworkIdentity)); @@ -125,41 +169,4 @@ public PocketTeleport Spawn(Vector3 localPosition) /// Destroys the <see cref="PocketTeleport"/> removing it from the server. /// </summary> public void Destroy() => Object.Destroy(Base); - - /// <summary> - /// Gets the wrapper given the base game <see cref="PocketDimensionTeleport"/> instance. - /// </summary> - /// <param name="pocketTeleport">The base game object.</param> - /// <returns>The associated wrapper.</returns> - [return: NotNullIfNotNull(nameof(pocketTeleport))] - public static PocketTeleport? Get(PocketDimensionTeleport? pocketTeleport) - { - if(pocketTeleport == null) - return null; - - if (Dictionary.TryGetValue(pocketTeleport, out PocketTeleport pt)) - return pt; - - return new PocketTeleport(pocketTeleport); - } - - /// <summary> - /// A private method to handle the addition of <see cref="PocketDimensionTeleport"/> instances. - /// </summary> - /// <param name="pocketTeleport">The base game instance.</param> - private static void OnAdded(PocketDimensionTeleport pocketTeleport) - { - if (!Dictionary.ContainsKey(pocketTeleport)) - _ = new PocketTeleport(pocketTeleport); - } - - /// <summary> - /// A private method to handle the removal of <see cref="PocketDimensionTeleport"/> instances. - /// </summary> - /// <param name="pocketTeleport">The base game instance.</param> - private static void OnRemoved(PocketDimensionTeleport pocketTeleport) - { - Dictionary.Remove(pocketTeleport); - } } - From 50cf59871347cd06e0a078910b93f937ffb3fc3a Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:44:12 +0930 Subject: [PATCH 104/215] scp914 --- .../Rooms/Scp914/BaseGameItemProcessor.cs | 1 - .../Rooms/Scp914/ItemProcessorAdapter.cs | 8 ++ .../Wrappers/Facility/Rooms/Scp914/Scp914.cs | 130 +++++++++++------- 3 files changed, 90 insertions(+), 49 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Rooms/Scp914/BaseGameItemProcessor.cs b/LabApi/Features/Wrappers/Facility/Rooms/Scp914/BaseGameItemProcessor.cs index 7a42cefb..5bc42590 100644 --- a/LabApi/Features/Wrappers/Facility/Rooms/Scp914/BaseGameItemProcessor.cs +++ b/LabApi/Features/Wrappers/Facility/Rooms/Scp914/BaseGameItemProcessor.cs @@ -1,7 +1,6 @@ using LabApi.Features.Interfaces; using Scp914; using Scp914.Processors; -using UnityEngine; namespace LabApi.Features.Wrappers; diff --git a/LabApi/Features/Wrappers/Facility/Rooms/Scp914/ItemProcessorAdapter.cs b/LabApi/Features/Wrappers/Facility/Rooms/Scp914/ItemProcessorAdapter.cs index 8a127b83..ad502299 100644 --- a/LabApi/Features/Wrappers/Facility/Rooms/Scp914/ItemProcessorAdapter.cs +++ b/LabApi/Features/Wrappers/Facility/Rooms/Scp914/ItemProcessorAdapter.cs @@ -19,10 +19,15 @@ internal class ItemProcessorAdapter : Scp914ItemProcessor /// <summary> /// Used internally by the base game. /// </summary> + /// <param name="setting">The setting to update the item.</param> + /// <param name="item">The base game item instance.</param> + /// <returns>The <see cref="Scp914Result"/>.</returns> public override Scp914Result UpgradeInventoryItem(Scp914KnobSetting setting, ItemBase item) { if (Processor.UsePickupMethodOnly) + { return base.UpgradeInventoryItem(setting, item); + } return Processor.UpgradeItem(setting, Item.Get(item)); } @@ -30,6 +35,9 @@ public override Scp914Result UpgradeInventoryItem(Scp914KnobSetting setting, Ite /// <summary> /// Used internally by the base game. /// </summary> + /// <param name="setting">The setting to update the item.</param> + /// <param name="pickup">The base game pickup instance.</param> + /// <returns>The <see cref="Scp914Result"/>.</returns> public override Scp914Result UpgradePickup(Scp914KnobSetting setting, ItemPickupBase pickup) => Processor.UpgradePickup(setting, Pickup.Get(pickup)); } diff --git a/LabApi/Features/Wrappers/Facility/Rooms/Scp914/Scp914.cs b/LabApi/Features/Wrappers/Facility/Rooms/Scp914/Scp914.cs index 9410cde1..f7f610da 100644 --- a/LabApi/Features/Wrappers/Facility/Rooms/Scp914/Scp914.cs +++ b/LabApi/Features/Wrappers/Facility/Rooms/Scp914/Scp914.cs @@ -25,49 +25,9 @@ public class Scp914 : Room public static Scp914? Instance { get; private set; } /// <summary> - /// Contains all <see cref="IScp914ItemProcessor"/> instances, accessible by their <see cref="ItemBase"/>. + /// Contains all <see cref="IScp914ItemProcessor"/> instances, accessible by their <see cref="ItemBase"/>. /// </summary> - public static Dictionary<ItemBase, IScp914ItemProcessor> ItemProcessorCache = []; - - /// <summary> - /// An internal constructor to prevent external instantiation. - /// </summary> - /// <param name="roomIdentifier">The room identifier for the pocket dimension.</param> - internal Scp914(RoomIdentifier roomIdentifier) - : base(roomIdentifier) - { - if (CanCache) - Instance = this; - } - - /// <summary> - /// An internal method to set the instance to null when the base object is destroyed. - /// </summary> - internal override void OnRemoved() - { - base.OnRemoved(); - Instance = null; - } - - /// <summary> - /// Gets the main <see cref="Wrappers.Gate"/> of the SCP-914 room. - /// </summary> - public Gate Gate => (Gate)Doors.FirstOrDefault(x => x is Gate); - - /// <summary> - /// Gets the entrance <see cref="Door"/> of the SCP-914 room. - /// </summary> - public Door Entrance => Doors.FirstOrDefault(x => x.Rooms.Length == 2); - - /// <summary> - /// Gets the intake <see cref="Door"/> of the SCP-914 machine. - /// </summary> - public Door IntakeDoor => Door.Get(Scp914Controller.Singleton.Doors.Last()); - - /// <summary> - /// Gets the output <see cref="Door"/> of the SCP-914 machine. - /// </summary> - public Door OutputDoor => Door.Get(Scp914Controller.Singleton.Doors.First()); + public static Dictionary<ItemBase, IScp914ItemProcessor> ItemProcessorCache { get; } = []; /// <summary> /// Gets or sets the <see cref="Scp914KnobSetting"/> of the SCP-914 machine. @@ -87,10 +47,14 @@ public static bool IsUpgrading set { if (Scp914Controller.Singleton.IsUpgrading == value) + { return; + } if (value) + { Scp914Controller.Singleton.Upgrade(); + } else { Scp914Controller.Singleton.IsUpgrading = value; @@ -202,7 +166,7 @@ public static float DoorOpenDelay /// </remarks> public static void Interact(Scp914InteractCode interactCode, Player? player = null) { - player ??= Server.Host; + player ??= Server.Host!; Scp914Controller.Singleton.ServerInteract(player.ReferenceHub, (byte)interactCode); } @@ -225,18 +189,28 @@ public static void PlaySound(Scp914Sound sound) public static IScp914ItemProcessor? GetItemProcessor(ItemType type) { if (!InventoryItemLoader.TryGetItem(type, out ItemBase item)) + { return null; + } if (ItemProcessorCache.TryGetValue(item, out var processor)) + { return processor; + } if (!item.TryGetComponent(out Scp914ItemProcessor baseProcessor)) + { return null; + } if (baseProcessor is ItemProcessorAdapter adaptor) + { ItemProcessorCache[item] = adaptor.Processor; + } else + { ItemProcessorCache[item] = new BaseGameItemProcessor(baseProcessor); + } return ItemProcessorCache[item]; } @@ -254,7 +228,9 @@ public static void PlaySound(Scp914Sound sound) foreach (ItemType type in Enum.GetValues(typeof(ItemType))) { if (!InventoryItemLoader.TryGetItem(type, out ItemBase _)) + { continue; + } result.Add(type, GetItemProcessor(type)); } @@ -268,13 +244,18 @@ public static void PlaySound(Scp914Sound sound) /// <typeparam name="T">The class type that implements the <see cref="IScp914ItemProcessor"/> interface.</typeparam> /// <param name="type">The <see cref="ItemType"/> to set the processor to.</param> /// <param name="processor">An instance of the processor.</param> - public static void SetItemProcessor<T>(ItemType type, T processor) where T : class, IScp914ItemProcessor + public static void SetItemProcessor<T>(ItemType type, T processor) + where T : class, IScp914ItemProcessor { if (!InventoryItemLoader.TryGetItem(type, out ItemBase item)) + { return; + } if (item.TryGetComponent(out Scp914ItemProcessor baseProcessor)) + { UnityEngine.Object.Destroy(baseProcessor); + } item.gameObject.AddComponent<ItemProcessorAdapter>().Processor = processor; ItemProcessorCache[item] = processor; @@ -286,12 +267,15 @@ public static void SetItemProcessor<T>(ItemType type, T processor) where T : cla /// <typeparam name="T">The class type that implements the <see cref="IScp914ItemProcessor"/> interface.</typeparam> /// <param name="predicate">A predicate to match which <see cref="ItemType">Item Types</see> to set the processor on using <see cref="Item"/> as a wrapper.</param> /// <param name="processor">An instance of the processor.</param> - public static void SetItemProcessor<T>(Func<Item, bool> predicate, T processor) where T : class, IScp914ItemProcessor + public static void SetItemProcessor<T>(Func<Item, bool> predicate, T processor) + where T : class, IScp914ItemProcessor { - foreach(ItemType type in Enum.GetValues(typeof(ItemType))) + foreach (ItemType type in Enum.GetValues(typeof(ItemType))) { if (!InventoryItemLoader.TryGetItem(type, out ItemBase item) || !predicate(Item.Get(item))) + { continue; + } SetItemProcessor(type, processor); } @@ -305,14 +289,19 @@ public static void SetItemProcessor<T>(Func<Item, bool> predicate, T processor) /// <remarks> /// Note that this is for setting the base game <see cref="Scp914ItemProcessor"/> for an item, you should always use <see cref="IScp914ItemProcessor"/> instead unless using already existing code see <see cref="SetItemProcessor{T}(ItemType, T)"/>. /// </remarks> - public static void SetItemProcessor<T>(ItemType type) where T : Scp914ItemProcessor, new() + public static void SetItemProcessor<T>(ItemType type) + where T : Scp914ItemProcessor, new() { if (!InventoryItemLoader.TryGetItem(type, out ItemBase item)) + { return; + } ItemProcessorCache.Remove(item); if (item.TryGetComponent(out Scp914ItemProcessor baseProcessor)) + { UnityEngine.Object.Destroy(baseProcessor); + } item.gameObject.AddComponent<T>(); } @@ -325,14 +314,59 @@ public static void SetItemProcessor<T>(Func<Item, bool> predicate, T processor) /// <remarks> /// Note that this is for setting the base game <see cref="Scp914ItemProcessor"/> for an item, you should always use <see cref="IScp914ItemProcessor"/> instead unless using already existing code. /// </remarks> - public static void SetItemProcessor<T>(Func<Item, bool> predicate) where T : Scp914ItemProcessor, new() + public static void SetItemProcessor<T>(Func<Item, bool> predicate) + where T : Scp914ItemProcessor, new() { foreach (ItemType type in Enum.GetValues(typeof(ItemType))) { if (!InventoryItemLoader.TryGetItem(type, out ItemBase item) || !predicate(Item.Get(item))) + { continue; + } SetItemProcessor<T>(type); } } + + /// <summary> + /// An internal constructor to prevent external instantiation. + /// </summary> + /// <param name="roomIdentifier">The room identifier for the pocket dimension.</param> + internal Scp914(RoomIdentifier roomIdentifier) + : base(roomIdentifier) + { + if (CanCache) + { + Instance = this; + } + } + + /// <summary> + /// Gets the main <see cref="Wrappers.Gate"/> of the SCP-914 room. + /// </summary> + public Gate Gate => (Gate)Doors.FirstOrDefault(x => x is Gate); + + /// <summary> + /// Gets the entrance <see cref="Door"/> of the SCP-914 room. + /// </summary> + public Door Entrance => Doors.FirstOrDefault(x => x.Rooms.Length == 2); + + /// <summary> + /// Gets the intake <see cref="Door"/> of the SCP-914 machine. + /// </summary> + public Door IntakeDoor => Door.Get(Scp914Controller.Singleton.Doors.Last()); + + /// <summary> + /// Gets the output <see cref="Door"/> of the SCP-914 machine. + /// </summary> + public Door OutputDoor => Door.Get(Scp914Controller.Singleton.Doors.First()); + + /// <summary> + /// An internal method to set the instance to null when the base object is destroyed. + /// </summary> + internal override void OnRemoved() + { + base.OnRemoved(); + Instance = null; + } } From d3a87a100152a9125894fc6ba35c6d68a5d7ca8c Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:44:18 +0930 Subject: [PATCH 105/215] rooms --- .../Wrappers/Facility/Rooms/Camera.cs | 78 ++-- .../Facility/Rooms/LightsController.cs | 50 ++- .../Features/Wrappers/Facility/Rooms/Room.cs | 423 ++++++++++-------- 3 files changed, 293 insertions(+), 258 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Rooms/Camera.cs b/LabApi/Features/Wrappers/Facility/Rooms/Camera.cs index a5eac553..d28a1d9a 100644 --- a/LabApi/Features/Wrappers/Facility/Rooms/Camera.cs +++ b/LabApi/Features/Wrappers/Facility/Rooms/Camera.cs @@ -1,7 +1,7 @@ -using PlayerRoles.PlayableScps.Scp079.Cameras; +using Generators; +using PlayerRoles.PlayableScps.Scp079.Cameras; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; -using Generators; using UnityEngine; namespace LabApi.Features.Wrappers; @@ -22,7 +22,35 @@ public class Camera public static IReadOnlyCollection<Camera> List => Dictionary.Values; /// <summary> - /// Initializes the <see cref="Camera"/> class to subscribe to + /// Gets the <see cref="Camera"/> associated with the <see cref="Scp079Camera"/>. + /// </summary> + /// <param name="camera">The <see cref="Scp079Camera"/> to get the camera from.</param> + /// <returns>The <see cref="Camera"/> associated with the <see cref="Scp079Camera"/> or <see langword="null"/> if it doesn't exist.</returns> + [return: NotNullIfNotNull(nameof(camera))] + public static Camera? Get(Scp079Camera? camera) + { + if (camera == null) + { + return null; + } + + return TryGet(camera, out Camera? cam) ? cam : new Camera(camera); + } + + /// <summary> + /// Tries to get the <see cref="Camera"/> associated with the <see cref="Scp079Camera"/>. + /// </summary> + /// <param name="camera">The <see cref="Scp079Camera"/> to get the camera from.</param> + /// <param name="wrapper">The <see cref="Camera"/> associated with the <see cref="Scp079Camera"/> or <see langword="null"/> if it doesn't exist.</param> + /// <returns>Whether the camera was successfully retrieved.</returns> + public static bool TryGet(Scp079Camera camera, [NotNullWhen(true)] out Camera? wrapper) + { + wrapper = null; + return camera != null && Dictionary.TryGetValue(camera, out wrapper); + } + + /// <summary> + /// Initializes the <see cref="Camera"/> class to subscribe to. /// </summary> [InitializeWrapper] internal static void Initialize() @@ -33,6 +61,15 @@ internal static void Initialize() Scp079Camera.OnInstanceRemoved += (camera) => Remove(camera); } + /// <summary> + /// Handles the removal of a camera from the dictionary. + /// </summary> + /// <param name="camera">The camera to remove.</param> + private static void Remove(Scp079Camera camera) + { + Dictionary.Remove(camera); + } + /// <summary> /// A private constructor to prevent external instantiation. /// </summary> @@ -91,39 +128,4 @@ public override string ToString() { return $"[Camera: Position={Position}, Rotation={Rotation}, Room={Room}, Zoom={Zoom}, IsBeingUsed={IsBeingUsed}]"; } - - /// <summary> - /// Gets the <see cref="Camera"/> associated with the <see cref="Scp079Camera"/>. - /// </summary> - /// <param name="camera">The <see cref="Scp079Camera"/> to get the camera from.</param> - /// <returns>The <see cref="Camera"/> associated with the <see cref="Scp079Camera"/> or <see langword="null"/> if it doesn't exist.</returns> - [return: NotNullIfNotNull(nameof(camera))] - public static Camera? Get(Scp079Camera? camera) - { - if (camera == null) - return null; - - return TryGet(camera, out Camera? cam) ? cam : new Camera(camera); - } - - /// <summary> - /// Tries to get the <see cref="Camera"/> associated with the <see cref="Scp079Camera"/>. - /// </summary> - /// <param name="camera">The <see cref="Scp079Camera"/> to get the camera from.</param> - /// <param name="wrapper">The <see cref="Camera"/> associated with the <see cref="Scp079Camera"/> or <see langword="null"/> if it doesn't exist.</param> - /// <returns>Whether the camera was successfully retrieved.</returns> - public static bool TryGet(Scp079Camera camera, [NotNullWhen(true)] out Camera? wrapper) - { - wrapper = null; - return camera != null && Dictionary.TryGetValue(camera, out wrapper); - } - - /// <summary> - /// Handles the removal of a camera from the dictionary. - /// </summary> - /// <param name="camera">The camera to remove.</param> - private static void Remove(Scp079Camera camera) - { - Dictionary.Remove(camera); - } } \ No newline at end of file diff --git a/LabApi/Features/Wrappers/Facility/Rooms/LightsController.cs b/LabApi/Features/Wrappers/Facility/Rooms/LightsController.cs index 01ede3af..dedba386 100644 --- a/LabApi/Features/Wrappers/Facility/Rooms/LightsController.cs +++ b/LabApi/Features/Wrappers/Facility/Rooms/LightsController.cs @@ -11,23 +11,29 @@ namespace LabApi.Features.Wrappers; public class LightsController { /// <summary> - /// Contains all the cached rooms in the game, accessible through their <see cref="RoomLightController"/>. + /// A reference to all <see cref="LightsController"/> instances currently in the game. /// </summary> - private static Dictionary<RoomLightController, LightsController> Dictionary { get; } = []; + public static IReadOnlyCollection<LightsController> List => Dictionary.Values; /// <summary> - /// A reference to all <see cref="LightsController"/> instances currently in the game. + /// Contains all the cached rooms in the game, accessible through their <see cref="RoomLightController"/>. /// </summary> - public static IReadOnlyCollection<LightsController> List => Dictionary.Values; + private static Dictionary<RoomLightController, LightsController> Dictionary { get; } = []; /// <summary> - /// A private constructor to prevent external instantiation. + /// Gets the controller wrapper from <see cref="Dictionary"/>, or creates a new one if it doesn't exists. /// </summary> - /// <param name="original">The original object.</param> - private LightsController(RoomLightController original) + /// <param name="roomLightController">The original light controller.</param> + /// <returns>The requested light controller wrapper.</returns> + [return: NotNullIfNotNull(nameof(roomLightController))] + public static LightsController? Get(RoomLightController roomLightController) { - Dictionary.Add(original, this); - Base = original; + if (roomLightController == null) + { + return null; + } + + return Dictionary.TryGetValue(roomLightController, out LightsController lightController) ? lightController : new LightsController(roomLightController); } /// <summary> @@ -40,6 +46,16 @@ internal static void Initialize() RoomLightController.OnRemoved += (roomLightController) => Dictionary.Remove(roomLightController); } + /// <summary> + /// A private constructor to prevent external instantiation. + /// </summary> + /// <param name="original">The original object.</param> + private LightsController(RoomLightController original) + { + Dictionary.Add(original, this); + Base = original; + } + /// <summary> /// The base game object. /// </summary> @@ -48,7 +64,7 @@ internal static void Initialize() /// <summary> /// The room this controller is assigned to. /// </summary> - public Room? Room => Room.Get(Base.Room); + public Room Room => Room.Get(Base.Room)!; /// <summary> /// Gets or sets whether the lights are enabled in this room. @@ -73,18 +89,4 @@ public Color OverrideLightsColor /// </summary> /// <param name="duration">Duration of light shutdown in seconds.</param> public void FlickerLights(float duration) => Base.ServerFlickerLights(duration); - - /// <summary> - /// Gets the controller wrapper from <see cref="Dictionary"/>, or creates a new one if it doesnt exists. - /// </summary> - /// <param name="roomLightController">The original light controller.</param> - /// <returns>The requested light controller wrapper.</returns> - [return: NotNullIfNotNull(nameof(roomLightController))] - public static LightsController? Get(RoomLightController roomLightController) - { - if (roomLightController == null) - return null; - - return Dictionary.TryGetValue(roomLightController, out LightsController lightController) ? lightController : new LightsController(roomLightController); - } } \ No newline at end of file diff --git a/LabApi/Features/Wrappers/Facility/Rooms/Room.cs b/LabApi/Features/Wrappers/Facility/Rooms/Room.cs index 6967b25b..04c7e1d3 100644 --- a/LabApi/Features/Wrappers/Facility/Rooms/Room.cs +++ b/LabApi/Features/Wrappers/Facility/Rooms/Room.cs @@ -16,16 +16,6 @@ namespace LabApi.Features.Wrappers; /// </summary> public class Room { - /// <summary> - /// Initializes the Room wrapper by subscribing to the RoomIdentifier events. - /// </summary> - [InitializeWrapper] - internal static void Initialize() - { - RoomIdentifier.OnAdded += AddRoom; - RoomIdentifier.OnRemoved += RemoveRoom; - } - /// <summary> /// Contains all the cached rooms in the game, accessible through their <see cref="RoomIdentifier"/>. /// </summary> @@ -36,190 +26,6 @@ internal static void Initialize() /// </summary> public static IReadOnlyCollection<Room> List => Dictionary.Values; - /// <summary> - /// An internal constructor to prevent external instantiation. - /// </summary> - /// <param name="roomIdentifier">The identifier of the room.</param> - internal Room(RoomIdentifier roomIdentifier) - { - Base = roomIdentifier; - - if (CanCache) - Dictionary.Add(roomIdentifier, this); - } - - /// <summary> - /// An internal virtual method to signal to derived wrappers that the base has been destroyed. - /// </summary> - internal virtual void OnRemoved() - { - Dictionary.Remove(Base); - _adjacentRooms = null; - _connectedRooms = null; - } - - /// <summary> - /// The base object. - /// </summary> - public RoomIdentifier Base { get; } - - /// <summary> - /// Gets whether the base room instance was destroyed. - /// </summary> - public bool IsDestroyed => Base == null || GameObject == null; - - /// <summary> - /// The room's shape. - /// </summary> - public RoomShape Shape => Base.Shape; - - /// <summary> - /// The room's name. - /// </summary> - public RoomName Name => Base.Name; - - /// <summary> - /// The zone in which this room is located. - /// </summary> - public FacilityZone Zone => Base.Zone; - - /// <summary> - /// Gets the room's neighbors. - /// </summary> - public HashSet<RoomIdentifier> ConnectedRooms => Base.ConnectedRooms; - - /// <summary> - /// Gets the room's adjacent rooms where the player can traverse to. - /// Includes rooms that can be traversed to via elevator. - /// </summary> - public IReadOnlyCollection<Room> AdjacentRooms - { - get - { - if (_adjacentRooms != null) - return _adjacentRooms; - - List<Room> rooms = [.. ConnectedRooms.Select(Get)]; - - // Check if the room has elevator - Elevator? target = null; - foreach (Elevator elevator in Elevator.List) - { - if (elevator.Rooms.Contains(this)) - target = elevator; - } - - // Add rooms that are on other floors of this elevator - if (target != null) - { - foreach (Room room in target.Rooms) - { - if (room == this) - continue; - - rooms.Add(room); - } - } - - //Hcz-Ez checkpoints - if (Name == RoomName.HczCheckpointToEntranceZone) - { - FacilityZone targetZone = Zone == FacilityZone.HeavyContainment ? FacilityZone.Entrance : FacilityZone.HeavyContainment; - - Room? match = List - .Where(n => n.Name == RoomName.HczCheckpointToEntranceZone && n.Zone == targetZone) - .MinBy(n => (n.Position - Position).sqrMagnitude); - - if (match != null) - rooms.Add(match); - } - - _adjacentRooms = rooms.AsReadOnly(); - return _adjacentRooms; - } - } - - /// <summary> - /// Gets the doors that are a part of this room. - /// </summary> - public IEnumerable<Door> Doors - { - get - { - return DoorVariant.DoorsByRoom.TryGetValue(Base, out HashSet<DoorVariant> doors) ? doors.Where(static x => x != null).Select(static x => Door.Get(x!)) : []; - } - } - - /// <summary> - /// Gets the first light controller for this room.<br/> - /// <note> - /// Use <see cref="AllLightControllers"/> if you wish to modify all lights in this room. - /// </note> - /// </summary> - public LightsController? LightController => Base.LightControllers.Count > 0 ? LightsController.Get(Base.LightControllers[0]) : null; - - /// <summary> - /// Gets all light controllers for this specified room.<br/> - /// Some rooms such as 049, warhead and such may have multiple light controllers as they are split by the elevator. - /// </summary> - public IEnumerable<LightsController> AllLightControllers => Base.LightControllers.Select(LightsController.Get); - - /// <summary> - /// Gets the room's <see cref="UnityEngine.Transform"/>. - /// </summary> - public Transform Transform => Base.transform; - - /// <summary> - /// Gets the room's <see cref="UnityEngine.GameObject"/>. - /// </summary> - public GameObject GameObject => Base.gameObject; - - /// <summary> - /// Gets the room's position. - /// </summary> - public Vector3 Position => Transform.position; - - /// <summary> - /// Gets the room's rotation. - /// </summary> - public Quaternion Rotation => Transform.rotation; - - /// <summary> - /// Gets a collection of players in the room. - /// </summary> - public IEnumerable<Player> Players => Player.List.Where(p => p.Room == this); - - /// <summary> - /// Gets a collection of cameras in the room. - /// </summary> - public IEnumerable<Camera> Cameras => Camera.List.Where(x => x.Room == this); - - /// <inheritdoc /> - public override string ToString() - { - return $"[{GetType().Name}: Name={Name}, Shape={Shape}, Zone={Zone}]"; - } - - /// <summary> - /// Gets whether the room wrapper is allowed to be cached. - /// </summary> - protected bool CanCache => !IsDestroyed && Base.isActiveAndEnabled; - - private HashSet<Room>? _connectedRooms; - - private IReadOnlyCollection<Room>? _adjacentRooms; - - /// <summary> - /// Gets the closest <see cref="LightsController"/> to the specified player. - /// </summary> - /// <param name="player">The player to check the closest light controller for.</param> - /// <returns>The closest light controller. May return <see langword="null"/> if player is not alive or is not in any room.</returns> - public LightsController? GetClosestLightController(Player player) - { - RoomLightController rlc = Base.GetClosestLightController(player.ReferenceHub); - return rlc == null ? null : LightsController.Get(rlc); - } - /// <summary> /// Gets path from <paramref name="start"/> to <paramref name="end"/>.<br/> /// Path is found via <see href="https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm">Dijkstra's algorithm</see>. Path still works between zones (including via elevators) as it uses <see cref="AdjacentRooms"/>.<br/> @@ -234,7 +40,9 @@ public static List<Room> FindPath(Room start, Room end, Func<Room, int> weightFu List<Room> path = NorthwoodLib.Pools.ListPool<Room>.Shared.Rent(); if (start == null || end == null || start == end) + { return path; + } Dictionary<Room, Room?> previous = DictionaryPool<Room, Room?>.Get(); Dictionary<Room, int> distances = DictionaryPool<Room, int>.Get(); @@ -256,17 +64,23 @@ public static List<Room> FindPath(Room start, Room end, Func<Room, int> weightFu Room current = queue.Dequeue(); if (visited.Contains(current)) + { continue; + } visited.Add(current); if (current == end) + { break; + } foreach (Room neighbor in current.AdjacentRooms) { if (visited.Contains(neighbor)) + { continue; + } int newDistance = distances[current] + weightFunction(neighbor); if (newDistance < distances[neighbor]) @@ -287,9 +101,11 @@ public static List<Room> FindPath(Room start, Room end, Func<Room, int> weightFu step = previous[step]; } - // If only entry is the end room, clear the path as it wasnt found + // If only entry is the end room, clear the path as it wasn't found if (path.Count == 1 && path[0] == end) + { path.Clear(); + } DictionaryPool<Room, Room?>.Release(previous); DictionaryPool<Room, int>.Release(distances); @@ -311,10 +127,14 @@ public static List<Room> FindPath(Room start, Room end, Func<Room, int> weightFu public static Room? Get(RoomIdentifier? roomIdentifier) { if (roomIdentifier == null) + { return null; + } if (Dictionary.TryGetValue(roomIdentifier, out Room room)) + { return room; + } return CreateRoomWrapper(roomIdentifier); } @@ -349,7 +169,7 @@ public static IEnumerable<Room> Get(FacilityZone facilityZone) => /// <param name="roomIdentifiers">The room identifiers to get the rooms from.</param> /// <returns>The requested rooms.</returns> public static IEnumerable<Room> Get(IEnumerable<RoomIdentifier> roomIdentifiers) => - roomIdentifiers.Select(Get); + roomIdentifiers.Select(Get)!; /// <summary> /// Tries to get the room at the specified position. @@ -376,6 +196,16 @@ public static bool TryGetRoomAtPosition(Vector3 position, [NotNullWhen(true)] ou /// <returns>The room at the specified position or <see langword="null"/> if no room was found.</returns> public static Room? GetRoomAtPosition(Vector3 position) => TryGetRoomAtPosition(position, out Room? room) ? room : null; + /// <summary> + /// Initializes the Room wrapper by subscribing to the RoomIdentifier events. + /// </summary> + [InitializeWrapper] + internal static void Initialize() + { + RoomIdentifier.OnAdded += AddRoom; + RoomIdentifier.OnRemoved += RemoveRoom; + } + /// <summary> /// Creates a new wrapper from the base room object. /// </summary> @@ -384,11 +214,17 @@ public static bool TryGetRoomAtPosition(Vector3 position, [NotNullWhen(true)] ou protected static Room CreateRoomWrapper(RoomIdentifier roomIdentifier) { if (roomIdentifier.Name == RoomName.Pocket) + { return new PocketDimension(roomIdentifier); + } else if (roomIdentifier.Name == RoomName.Lcz914) + { return new Scp914(roomIdentifier); + } else + { return new Room(roomIdentifier); + } } /// <summary> @@ -400,7 +236,9 @@ private static void AddRoom(RoomIdentifier roomIdentifier) try { if (!Dictionary.ContainsKey(roomIdentifier)) + { _ = CreateRoomWrapper(roomIdentifier); + } } catch (Exception e) { @@ -417,11 +255,204 @@ private static void RemoveRoom(RoomIdentifier roomIdentifier) try { if (Dictionary.TryGetValue(roomIdentifier, out Room room)) + { room.OnRemoved(); + } } catch (Exception e) { Console.Logger.InternalError($"Failed to handle item destruction with error: {e}"); } } + + private IReadOnlyCollection<Room>? _adjacentRooms; + + /// <summary> + /// An internal constructor to prevent external instantiation. + /// </summary> + /// <param name="roomIdentifier">The identifier of the room.</param> + internal Room(RoomIdentifier roomIdentifier) + { + Base = roomIdentifier; + + if (CanCache) + { + Dictionary.Add(roomIdentifier, this); + } + } + + /// <summary> + /// The base object. + /// </summary> + public RoomIdentifier Base { get; } + + /// <summary> + /// Gets whether the base room instance was destroyed. + /// </summary> + public bool IsDestroyed => Base == null || GameObject == null; + + /// <summary> + /// The room's shape. + /// </summary> + public RoomShape Shape => Base.Shape; + + /// <summary> + /// The room's name. + /// </summary> + public RoomName Name => Base.Name; + + /// <summary> + /// The zone in which this room is located. + /// </summary> + public FacilityZone Zone => Base.Zone; + + /// <summary> + /// Gets the room's neighbors. + /// </summary> + public HashSet<RoomIdentifier> ConnectedRooms => Base.ConnectedRooms; + + /// <summary> + /// Gets the room's adjacent rooms where the player can traverse to. + /// Includes rooms that can be traversed to via elevator. + /// </summary> + public IReadOnlyCollection<Room> AdjacentRooms + { + get + { + if (_adjacentRooms != null) + { + return _adjacentRooms; + } + + List<Room> rooms = [.. ConnectedRooms.Select(Get)]; + + // Check if the room has elevator + Elevator? target = null; + foreach (Elevator elevator in Elevator.List) + { + if (elevator.Rooms.Contains(this)) + { + target = elevator; + } + } + + // Add rooms that are on other floors of this elevator + if (target != null) + { + foreach (Room room in target.Rooms) + { + if (room == this) + { + continue; + } + + rooms.Add(room); + } + } + + // Hcz-Ez checkpoints + if (Name == RoomName.HczCheckpointToEntranceZone) + { + FacilityZone targetZone = Zone == FacilityZone.HeavyContainment ? FacilityZone.Entrance : FacilityZone.HeavyContainment; + + Room? match = List + .Where(n => n.Name == RoomName.HczCheckpointToEntranceZone && n.Zone == targetZone) + .MinBy(n => (n.Position - Position).sqrMagnitude); + + if (match != null) + { + rooms.Add(match); + } + } + + _adjacentRooms = rooms.AsReadOnly(); + return _adjacentRooms; + } + } + + /// <summary> + /// Gets the doors that are a part of this room. + /// </summary> + public IEnumerable<Door> Doors + { + get + { + return DoorVariant.DoorsByRoom.TryGetValue(Base, out HashSet<DoorVariant> doors) ? doors.Where(static x => x != null).Select(static x => Door.Get(x!)) : []; + } + } + + /// <summary> + /// Gets the first light controller for this room.<br/> + /// <note> + /// Use <see cref="AllLightControllers"/> if you wish to modify all lights in this room. + /// </note> + /// </summary> + public LightsController? LightController => Base.LightControllers.Count > 0 ? LightsController.Get(Base.LightControllers[0]) : null; + + /// <summary> + /// Gets all light controllers for this specified room.<br/> + /// Some rooms such as 049, warhead and such may have multiple light controllers as they are split by the elevator. + /// </summary> + public IEnumerable<LightsController> AllLightControllers => Base.LightControllers.Select(LightsController.Get)!; + + /// <summary> + /// Gets the room's <see cref="UnityEngine.Transform"/>. + /// </summary> + public Transform Transform => Base.transform; + + /// <summary> + /// Gets the room's <see cref="UnityEngine.GameObject"/>. + /// </summary> + public GameObject GameObject => Base.gameObject; + + /// <summary> + /// Gets the room's position. + /// </summary> + public Vector3 Position => Transform.position; + + /// <summary> + /// Gets the room's rotation. + /// </summary> + public Quaternion Rotation => Transform.rotation; + + /// <summary> + /// Gets a collection of players in the room. + /// </summary> + public IEnumerable<Player> Players => Player.List.Where(p => p.Room == this); + + /// <summary> + /// Gets a collection of cameras in the room. + /// </summary> + public IEnumerable<Camera> Cameras => Camera.List.Where(x => x.Room == this); + + /// <summary> + /// Gets whether the room wrapper is allowed to be cached. + /// </summary> + protected bool CanCache => !IsDestroyed && Base.isActiveAndEnabled; + + /// <inheritdoc /> + public override string ToString() + { + return $"[{GetType().Name}: Name={Name}, Shape={Shape}, Zone={Zone}]"; + } + + /// <summary> + /// Gets the closest <see cref="LightsController"/> to the specified player. + /// </summary> + /// <param name="player">The player to check the closest light controller for.</param> + /// <returns>The closest light controller. May return <see langword="null"/> if player is not alive or is not in any room.</returns> + public LightsController? GetClosestLightController(Player player) + { + RoomLightController rlc = Base.GetClosestLightController(player.ReferenceHub); + return rlc == null ? null : LightsController.Get(rlc); + } + + /// <summary> + /// An internal virtual method to signal to derived wrappers that the base has been destroyed. + /// </summary> + internal virtual void OnRemoved() + { + Dictionary.Remove(Base); + _adjacentRooms = null; + } } \ No newline at end of file From bae43ff3a1c50a1202a0cc35b720ebbae5dee652 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:44:27 +0930 Subject: [PATCH 106/215] experimental --- .../Structures/ExperimentalWeaponLocker.cs | 48 ++++++++++--------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Structures/ExperimentalWeaponLocker.cs b/LabApi/Features/Wrappers/Facility/Structures/ExperimentalWeaponLocker.cs index 4311f7d0..5806244a 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/ExperimentalWeaponLocker.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/ExperimentalWeaponLocker.cs @@ -1,9 +1,7 @@ using Interactables.Interobjects.DoorUtils; -using MapGeneration.Distributors; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; -using System.Security; using BaseExperimentalWeaponLocker = MapGeneration.Distributors.ExperimentalWeaponLocker; namespace LabApi.Features.Wrappers; @@ -14,14 +12,30 @@ namespace LabApi.Features.Wrappers; public class ExperimentalWeaponLocker : Locker { /// <summary> - /// Contains all the cached experimental weapon lockers, accessible through their <see cref="BaseExperimentalWeaponLocler"/>. + /// Contains all the cached experimental weapon lockers, accessible through their <see cref="BaseExperimentalWeaponLocker"/>. /// </summary> - public new static Dictionary<BaseExperimentalWeaponLocker, ExperimentalWeaponLocker> Dictionary { get; } = []; + public static new Dictionary<BaseExperimentalWeaponLocker, ExperimentalWeaponLocker> Dictionary { get; } = []; /// <summary> /// A reference to all <see cref="ExperimentalWeaponLocker"/> instances. /// </summary> - public new static IReadOnlyCollection<ExperimentalWeaponLocker> List => Dictionary.Values; + public static new IReadOnlyCollection<ExperimentalWeaponLocker> List => Dictionary.Values; + + /// <summary> + /// Gets the experimental weapon locker wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist and the provided <see cref="BaseExperimentalWeaponLocker"/> was not <see langword="null"/>. + /// </summary> + /// <param name="baseLocker">The <see cref="Base"/> of the experimental weapon locker.</param> + /// <returns>The requested wrapper or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(baseLocker))] + public static ExperimentalWeaponLocker? Get(BaseExperimentalWeaponLocker? baseLocker) + { + if (baseLocker == null) + { + return null; + } + + return Dictionary.TryGetValue(baseLocker, out ExperimentalWeaponLocker found) ? found : (ExperimentalWeaponLocker)CreateStructureWrapper(baseLocker); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -33,16 +47,9 @@ internal ExperimentalWeaponLocker(BaseExperimentalWeaponLocker baseExperimentalW Base = baseExperimentalWeaponLocker; if (CanCache) + { Dictionary.Add(baseExperimentalWeaponLocker, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the abase object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -141,16 +148,11 @@ public ItemType[] AcceptableItems public void PlayDeniedSound(DoorPermissionFlags flags = DoorPermissionFlags.None) => Chamber.PlayDeniedSound(flags); /// <summary> - /// Gets the experimental weapon locker wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist and the provided <see cref="BaseExperimentalWeaponLocker"/> was not <see langword="null"/>. + /// An internal method to remove itself from the cache when the abase object is destroyed. /// </summary> - /// <param name="baseLocker">The <see cref="Base"/> of the experimental weapon locker.</param> - /// <returns>The requested wrapper or <see langword="null"/>.</returns> - [return: NotNullIfNotNull(nameof(baseLocker))] - public static ExperimentalWeaponLocker? Get(BaseExperimentalWeaponLocker? baseLocker) + internal override void OnRemove() { - if (baseLocker == null) - return null; - - return Dictionary.TryGetValue(baseLocker, out ExperimentalWeaponLocker found) ? found : (ExperimentalWeaponLocker)CreateStructureWrapper(baseLocker); + base.OnRemove(); + Dictionary.Remove(Base); } } From b75c70be19811a8fb69fdc6d9334001f7f795686 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:44:31 +0930 Subject: [PATCH 107/215] generator --- .../Wrappers/Facility/Structures/Generator.cs | 175 ++++++++++-------- 1 file changed, 93 insertions(+), 82 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Structures/Generator.cs b/LabApi/Features/Wrappers/Facility/Structures/Generator.cs index c807f641..3a762db3 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/Generator.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/Generator.cs @@ -1,10 +1,10 @@ -using Interactables.Interobjects.DoorUtils; +using Generators; +using Interactables.Interobjects.DoorUtils; +using MapGeneration; using MapGeneration.Distributors; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using static MapGeneration.Distributors.Scp079Generator; -using Generators; -using MapGeneration; namespace LabApi.Features.Wrappers; @@ -16,34 +16,42 @@ public class Generator : Structure /// <summary> /// Contains all the cached <see cref="Scp079Generator">generators</see> in the game, accessible through their <see cref="Scp079Generator"/>. /// </summary> - public new static Dictionary<Scp079Generator, Generator> Dictionary { get; } = []; + public static new Dictionary<Scp079Generator, Generator> Dictionary { get; } = []; /// <summary> - /// Contains generators in a list by room they are in. Generators that have been spawned without an assigned room are not inside of this collection. + /// A reference to all <see cref="Generator"/> instances currently in the game. /// </summary> - private static Dictionary<Room, List<Generator>> GeneratorsByRoom { get; } = []; + public static new IReadOnlyCollection<Generator> List => Dictionary.Values; /// <summary> - /// A reference to all <see cref="Generator"/> instances currently in the game. + /// Contains generators in a list by room they are in. Generators that have been spawned without an assigned room are not inside of this collection. /// </summary> - public new static IReadOnlyCollection<Generator> List => Dictionary.Values; + private static Dictionary<Room, List<Generator>> GeneratorsByRoom { get; } = []; /// <summary> - /// An internal constructor to prevent external instantiation. + /// Gets the generator wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist and the provided <see cref="Scp079Generator"/> was not <see langword="null"/>. /// </summary> - /// <param name="generator">The <see cref="Scp079Generator"/> of the generator.</param> - internal Generator(Scp079Generator generator) - : base(generator) + /// <param name="scp079Generator">The <see cref="Scp079Generator"/> of the generator.</param> + /// <returns>The requested wrapper or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(scp079Generator))] + public static Generator? Get(Scp079Generator? scp079Generator) { - Base = generator; - - if (CanCache) + if (scp079Generator == null) { - Dictionary.Add(generator, this); - TryRegisterByRoom(); + return null; } + + return Dictionary.TryGetValue(scp079Generator, out Generator generator) ? generator : (Generator)CreateStructureWrapper(scp079Generator); } + /// <summary> + /// Gets the generator wrapper from the <see cref="GeneratorsByRoom"/> or returns <see langword="null"/> if specified room does not have any. + /// </summary> + /// <param name="room">Target room.</param> + /// <param name="generators">Generators found.</param> + /// <returns>Whether the generator was found.</returns> + public static bool TryGetFromRoom(Room room, [NotNullWhen(true)] out List<Generator>? generators) => GeneratorsByRoom.TryGetValue(room, out generators); + /// <summary> /// Initializes the generators by room caching for map generation. /// </summary> @@ -56,50 +64,25 @@ internal static void InitializeCaching() private static void SeedSynchronizer_OnGenerationFinished() { foreach (Generator generator in List) + { generator.TryRegisterByRoom(); + } } /// <summary> - /// An internal method remove itself from the cache when the base object is destroyed. + /// An internal constructor to prevent external instantiation. /// </summary> - internal override void OnRemove() + /// <param name="generator">The <see cref="Scp079Generator"/> of the generator.</param> + internal Generator(Scp079Generator generator) + : base(generator) { - base.OnRemove(); - - if (Base.ParentRoom == null) - { - Dictionary.Remove(Base); - return; - } - - Room? room = Room.Get(Base.ParentRoom); - - if (room == null) // Room is null after round restart, try find it by iterating over the existing dictionary - { - Room? potentialRoom = null; - foreach (var kvp in GeneratorsByRoom) - { - if (kvp.Value.Contains(this)) - { - potentialRoom = kvp.Key; - break; - } - } - - room = potentialRoom; - } + Base = generator; - if (room != null && GeneratorsByRoom.TryGetValue(room, out List<Generator> list)) + if (CanCache) { - list.Remove(this); - - if (list.Count == 0) - { - GeneratorsByRoom.Remove(room); - } + Dictionary.Add(generator, this); + TryRegisterByRoom(); } - - Dictionary.Remove(Base); } /// <summary> @@ -168,7 +151,7 @@ public bool IsUnlocked public float ActivationTime => Base.ActivationTime; /// <summary> - /// Gets or sets whether the generator is engaged. + /// Gets or sets whether the generator is engaged. /// </summary> public bool Engaged { @@ -201,55 +184,83 @@ public short RemainingTime /// <param name="collider">The <see cref="GeneratorColliderId"/> triggered.</param> public void ServerInteract(Player player, GeneratorColliderId collider) => Base.ServerInteract(player.ReferenceHub, (byte)collider); + /// <summary> + /// Plays the denied sound cue on the client. + /// </summary> + /// <param name="flags">The permissions used to attempt opening the generator. Used to animate the generator panel.</param> + public void PlayerDeniedBeep(DoorPermissionFlags flags) => Base.RpcDenied(flags); + + /// <summary> + /// An internal method remove itself from the cache when the base object is destroyed. + /// </summary> + internal override void OnRemove() + { + base.OnRemove(); + + if (Base.ParentRoom == null) + { + Dictionary.Remove(Base); + return; + } + + Room? room = Room.Get(Base.ParentRoom); + + if (room == null) // Room is null after round restart, try find it by iterating over the existing dictionary + { + Room? potentialRoom = null; + foreach (var kvp in GeneratorsByRoom) + { + if (kvp.Value.Contains(this)) + { + potentialRoom = kvp.Key; + break; + } + } + + room = potentialRoom; + } + + if (room != null && GeneratorsByRoom.TryGetValue(room, out List<Generator> list)) + { + list.Remove(this); + + if (list.Count == 0) + { + GeneratorsByRoom.Remove(room); + } + } + + Dictionary.Remove(Base); + } + private void TryRegisterByRoom() { foreach (var kvp in GeneratorsByRoom) { if (kvp.Value.Contains(this)) + { return; + } } if (Base.ParentRoom == null) + { return; + } + Room? room = Room.Get(Base.ParentRoom); if (room == null) + { return; + } if (!GeneratorsByRoom.TryGetValue(room, out List<Generator> list)) { - list = new List<Generator>(); + list = []; GeneratorsByRoom.Add(room, list); } list.Add(this); } - - /// <summary> - /// Plays the denied sound cue on the client. - /// </summary> - /// <param name="flags">The permissions used to attempt opening the generator. Used to animate the generator panel.</param> - public void PlayerDeniedBeep(DoorPermissionFlags flags) => Base.RpcDenied(flags); - - /// <summary> - /// Gets the generator wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist and the provided <see cref="Scp079Generator"/> was not <see langword="null"/>. - /// </summary> - /// <param name="scp079Generator">The <see cref="Scp079Generator"/> of the generator.</param> - /// <returns>The requested wrapper or <see langword="null"/>.</returns> - [return: NotNullIfNotNull(nameof(scp079Generator))] - public static Generator? Get(Scp079Generator? scp079Generator) - { - if (scp079Generator == null) - return null; - - return Dictionary.TryGetValue(scp079Generator, out Generator generator) ? generator : (Generator)CreateStructureWrapper(scp079Generator); - } - - /// <summary> - /// Gets the generator wrapper from the <see cref="GeneratorsByRoom"/> or returns <see langword="null"/> if specified room does not have any. - /// </summary> - /// <param name="room">Target room.</param> - /// <param name="generators">Generators found.</param> - /// <returns>Whether the generator was found.</returns> - public static bool TryGetFromRoom(Room room, [NotNullWhen(true)] out List<Generator>? generators) => GeneratorsByRoom.TryGetValue(room, out generators); } \ No newline at end of file From f07492e720eab11c904caef486372fb8ac1a9c66 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:44:38 +0930 Subject: [PATCH 108/215] large --- .../Facility/Structures/LargeLocker.cs | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Structures/LargeLocker.cs b/LabApi/Features/Wrappers/Facility/Structures/LargeLocker.cs index e64e6d68..c4d5cc4e 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/LargeLocker.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/LargeLocker.cs @@ -11,12 +11,12 @@ public class LargeLocker : Locker /// <summary> /// Contains all the cached large lockers, accessible through their <see cref="BaseLocker"/>. /// </summary> - public new static Dictionary<BaseLocker, LargeLocker> Dictionary = []; + public static new Dictionary<BaseLocker, LargeLocker> Dictionary { get; } = []; /// <summary> /// A reference to all <see cref="LargeLocker"/> instances. /// </summary> - public new static IReadOnlyCollection<LargeLocker> List => Dictionary.Values; + public static new IReadOnlyCollection<LargeLocker> List => Dictionary.Values; /// <summary> /// An internal constructor to prevent external instantiation. @@ -26,16 +26,9 @@ internal LargeLocker(BaseLocker baseLocker) : base(baseLocker) { if (CanCache) + { Dictionary.Add(baseLocker, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -87,4 +80,13 @@ internal override void OnRemove() /// Gets the drawer chamber that is at the bottom. /// </summary> public LockerChamber Drawer => Chambers[9]; + + /// <summary> + /// An internal method to remove itself from the cache when the base object is destroyed. + /// </summary> + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); + } } From 703ab68e3d0e1af35d503134b611cecf78bc8deb Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:44:43 +0930 Subject: [PATCH 109/215] locker --- .../Wrappers/Facility/Structures/Locker.cs | 70 ++++++++++++------- 1 file changed, 43 insertions(+), 27 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Structures/Locker.cs b/LabApi/Features/Wrappers/Facility/Structures/Locker.cs index 647f6d20..9633cf1d 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/Locker.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/Locker.cs @@ -1,5 +1,4 @@ -using InventorySystem.Items.MicroHID; -using MapGeneration.Distributors; +using MapGeneration.Distributors; using NorthwoodLib.Pools; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; @@ -17,12 +16,28 @@ public class Locker : Structure /// <summary> /// Contains all the cached lockers, accessible through their <see cref="BaseLocker"/>. /// </summary> - public new static Dictionary<BaseLocker, Locker> Dictionary { get; } = []; + public static new Dictionary<BaseLocker, Locker> Dictionary { get; } = []; /// <summary> /// A reference to all <see cref="Locker"/> instances. /// </summary> - public new static IReadOnlyCollection<Locker> List => Dictionary.Values; + public static new IReadOnlyCollection<Locker> List => Dictionary.Values; + + /// <summary> + /// Gets the locker wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist and the provided <see cref="BaseLocker"/> was not <see langword="null"/>. + /// </summary> + /// <param name="baseLocker">The <see cref="Base"/> of the locker.</param> + /// <returns>The requested wrapper or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(baseLocker))] + public static Locker? Get(BaseLocker? baseLocker) + { + if (baseLocker == null) + { + return null; + } + + return Dictionary.TryGetValue(baseLocker, out Locker found) ? found : (Locker)CreateStructureWrapper(baseLocker); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -35,19 +50,9 @@ internal Locker(BaseLocker baseLocker) Chambers = baseLocker.Chambers.Select(static x => LockerChamber.Get(x)).ToArray(); if (CanCache) + { Dictionary.Add(baseLocker, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); - - foreach (LockerChamber chamber in Chambers) - chamber.OnRemove(); + } } /// <summary> @@ -103,7 +108,7 @@ public int MaxChambersToFill /// <summary> /// Adds a new <see cref="LockerLoot"/> entry to the possible spawnable <see cref="Loot"/>. /// </summary> - /// <param name="type">The <see cref="ItemType"/> to spawn. <see cref="LockerChamber"/> might only support certain <see cref="ItemType"/> values see <see cref="LockerChamber.AcceptableItems"/></param> + /// <param name="type">The <see cref="ItemType"/> to spawn. <see cref="LockerChamber"/> might only support certain <see cref="ItemType"/> values see <see cref="LockerChamber.AcceptableItems"/>.</param> /// <param name="remainingUses">The number of times this loot is selected to spawn in a chamber.</param> /// <param name="probabilityPoints">The probability weight given for this loot to spawn over other <see cref="LockerLoot"/> instances.</param> /// <param name="minPerChamber">The minimum number of items to spawn per chamber.</param> @@ -120,7 +125,7 @@ public void AddLockerLoot(ItemType type, int remainingUses, int probabilityPoint RemainingUses = remainingUses, ProbabilityPoints = probabilityPoints, MinPerChamber = minPerChamber, - MaxPerChamber = maxPerChamber + MaxPerChamber = maxPerChamber, }; Base.Loot = [.. Base.Loot, loot]; @@ -147,11 +152,15 @@ public void FillChambers() { int removeCount = Chambers.Count - Random.Range(MinChambersToFill, MaxChambersToFill + 1); for (int i = 0; i < removeCount; i++) + { chambers.RemoveAt(Random.Range(0, chambers.Count)); + } } foreach (LockerChamber chamber in chambers) + { chamber.Fill(); + } ListPool<LockerChamber>.Shared.Return(chambers); } @@ -165,7 +174,9 @@ public void FillChambers() public void FillAllChambers() { foreach (LockerChamber chamber in Chambers) + { chamber.Fill(); + } } /// <summary> @@ -174,7 +185,9 @@ public void FillAllChambers() public void ClearAllChambers() { foreach (LockerChamber chamber in Chambers) + { chamber.RemoveAllItems(); + } } /// <summary> @@ -183,7 +196,9 @@ public void ClearAllChambers() public void OpenAllChambers() { foreach (LockerChamber chamber in Chambers) + { chamber.IsOpen = true; + } } /// <summary> @@ -192,21 +207,22 @@ public void OpenAllChambers() public void CloseAllChambers() { foreach (LockerChamber chamber in Chambers) + { chamber.IsOpen = false; + } } /// <summary> - /// Gets the locker wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist and the provided <see cref="BaseLocker"/> was not <see langword="null"/>. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="baseLocker">The <see cref="Base"/> of the locker.</param> - /// <returns>The requested wrapper or <see langword="null"/>.</returns> - [return: NotNullIfNotNull(nameof(baseLocker))] - public static Locker? Get(BaseLocker? baseLocker) + internal override void OnRemove() { - if (baseLocker == null) - return null; + base.OnRemove(); + Dictionary.Remove(Base); - return Dictionary.TryGetValue(baseLocker, out Locker found) ? found : (Locker)CreateStructureWrapper(baseLocker); + foreach (LockerChamber chamber in Chambers) + { + chamber.OnRemove(); + } } } - From 9af2e3cab3f8ae7bbab7458121d2ff012afe090a Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:44:51 +0930 Subject: [PATCH 110/215] chamber --- .../Facility/Structures/LockerChamber.cs | 64 +++++++++++-------- 1 file changed, 39 insertions(+), 25 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Structures/LockerChamber.cs b/LabApi/Features/Wrappers/Facility/Structures/LockerChamber.cs index 80f5e08a..bd6bb558 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/LockerChamber.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/LockerChamber.cs @@ -6,8 +6,8 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using UnityEngine; -using BaseLockerChamber = MapGeneration.Distributors.LockerChamber; using BaseLocker = MapGeneration.Distributors.Locker; +using BaseLockerChamber = MapGeneration.Distributors.LockerChamber; namespace LabApi.Features.Wrappers; @@ -21,6 +21,28 @@ public class LockerChamber /// </summary> public static Dictionary<BaseLockerChamber, LockerChamber> Dictionary { get; } = []; + /// <summary> + /// Gets the locker chamber wrapper from the <see cref="Dictionary"/> or creates a new if it doesn't exist and the provided <see cref="BaseLockerChamber"/> was not null. + /// </summary> + /// <param name="baseLockerChamber">The <see cref="BaseLockerChamber"/> object.</param> + /// <returns>The requested locker chamber wrapper or null.</returns> + [return: NotNullIfNotNull(nameof(baseLockerChamber))] + public static LockerChamber? Get(BaseLockerChamber? baseLockerChamber) + { + if (baseLockerChamber == null) + { + return null; + } + + return Dictionary.TryGetValue(baseLockerChamber, out LockerChamber lockerChamber) ? lockerChamber : CreateLockerChamberWrapper(baseLockerChamber); + } + + private static LockerChamber CreateLockerChamberWrapper(BaseLockerChamber baseLockerChamber) + { + BaseLocker locker = baseLockerChamber.GetComponentInParent<BaseLocker>(); + return new LockerChamber(baseLockerChamber, (Locker)Structure.Get(locker), (byte)locker.Chambers.IndexOf(baseLockerChamber)); + } + /// <summary> /// An internal constructor to prevent external instantiation. /// </summary> @@ -34,15 +56,9 @@ internal LockerChamber(BaseLockerChamber baseLockerChamber, Locker locker, byte Id = id; if (locker.CanCache) + { Dictionary.Add(baseLockerChamber, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal void OnRemove() - { - Dictionary.Remove(Base); + } } /// <summary> @@ -130,7 +146,9 @@ public void Fill() foreach (ItemPickupBase pickupBase in Base.Content) { if (!pickupBase.TryGetComponent(out Rigidbody rigidbody)) + { continue; + } rigidbody.isKinematic = false; } @@ -163,7 +181,9 @@ public HashSet<Pickup> GetAllItems() public void RemoveAllItems() { foreach (ItemPickupBase pickupBase in Base.Content) + { pickupBase.DestroySelf(); + } Base.Content.Clear(); Base.ToBeSpawned.Clear(); @@ -187,7 +207,7 @@ public void RemoveItem(Pickup pickup) /// <returns>The created <see cref="Pickup"/>.</returns> public Pickup AddItem(ItemType type) { - Pickup pickup = Pickup.Create(type, Base.Spawnpoint.position, Base.Spawnpoint.rotation); + Pickup pickup = Pickup.Create(type, Base.Spawnpoint.position, Base.Spawnpoint.rotation)!; pickup.Transform.SetParent(Base.Spawnpoint); Base.Content.Add(pickup.Base); (pickup.Base as IPickupDistributorTrigger)?.OnDistributed(); @@ -198,9 +218,13 @@ public Pickup AddItem(ItemType type) } if (Base.SpawnOnFirstChamberOpening && !IsOpen) + { Base.ToBeSpawned.Add(pickup.Base); + } else + { pickup.Spawn(); + } return pickup; } @@ -215,7 +239,9 @@ public Pickup AddItem(ItemType type) public void Interact(Player player) { if (player == null) + { throw new ArgumentNullException(nameof(player)); + } Locker.Base.ServerInteract(player.ReferenceHub, Id); } @@ -227,22 +253,10 @@ public void Interact(Player player) public void PlayDeniedSound(DoorPermissionFlags permissionUsed) => Locker.Base.RpcPlayDenied(Id, permissionUsed); /// <summary> - /// Gets the locker chamber wrapper from the <see cref="Dictionary"/> or creates a new if it doesn't exist and the provided <see cref="BaseLockerChamber"/> was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="baseLockerChamber">The <see cref="BaseLockerChamber"/> object.</param> - /// <returns>The requested locker chamber wrapper or null.</returns> - [return: NotNullIfNotNull(nameof(baseLockerChamber))] - public static LockerChamber? Get(BaseLockerChamber? baseLockerChamber) - { - if (baseLockerChamber == null) - return null; - - return Dictionary.TryGetValue(baseLockerChamber, out LockerChamber lockerChamber) ? lockerChamber : CreateLockerChamberWrapper(baseLockerChamber); - } - - private static LockerChamber CreateLockerChamberWrapper(BaseLockerChamber baseLockerChamber) + internal void OnRemove() { - BaseLocker locker = baseLockerChamber.GetComponentInParent<BaseLocker>(); - return new LockerChamber(baseLockerChamber, (Locker)Structure.Get(locker), (byte)locker.Chambers.IndexOf(baseLockerChamber)); + Dictionary.Remove(Base); } } \ No newline at end of file From ae6a440dbb668b5bf157b3a0c27a77b916c0bc1d Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:44:56 +0930 Subject: [PATCH 111/215] micro --- .../Facility/Structures/MicroPedestal.cs | 39 +++++++++++-------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Structures/MicroPedestal.cs b/LabApi/Features/Wrappers/Facility/Structures/MicroPedestal.cs index 96ba5b06..00f5377c 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/MicroPedestal.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/MicroPedestal.cs @@ -12,23 +12,42 @@ public class MicroPedestal : Locker /// <summary> /// Contains all the micro pedestals, accessible through their <see cref="Base"/>. /// </summary> - public new static Dictionary<MicroHIDPedestal, MicroPedestal> Dictionary { get; } = []; + public static new Dictionary<MicroHIDPedestal, MicroPedestal> Dictionary { get; } = []; /// <summary> /// A reference to all <see cref="MicroPedestal"/> instances. /// </summary> - public new static IReadOnlyCollection<MicroPedestal> List => Dictionary.Values; + public static new IReadOnlyCollection<MicroPedestal> List => Dictionary.Values; + + /// <summary> + /// Gets the micro pedestal wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist and the provided <see cref="MicroHIDPedestal"/> was not <see langword="null"/>. + /// </summary> + /// <param name="basePedestal">The <see cref="Base"/> of the experimental weapon locker.</param> + /// <returns>The requested wrapper or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(basePedestal))] + public static MicroPedestal? Get(MicroHIDPedestal? basePedestal) + { + if (basePedestal == null) + { + return null; + } + + return Dictionary.TryGetValue(basePedestal, out MicroPedestal found) ? found : (MicroPedestal)CreateStructureWrapper(basePedestal); + } /// <summary> /// An internal constructor to prevent external instantiation. /// </summary> /// <param name="pedestal">The base <see cref="Base"/> object.</param> - internal MicroPedestal(MicroHIDPedestal pedestal) : base(pedestal) + internal MicroPedestal(MicroHIDPedestal pedestal) + : base(pedestal) { Base = pedestal; if (CanCache) + { Dictionary.Add(pedestal, this); + } } /// <summary> @@ -44,18 +63,4 @@ internal override void OnRemove() base.OnRemove(); Dictionary.Remove(Base); } - - /// <summary> - /// Gets the micro pedestal wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist and the provided <see cref="MicroHIDPedestal"/> was not <see langword="null"/>. - /// </summary> - /// <param name="basePedestal">The <see cref="Base"/> of the experimental weapon locker.</param> - /// <returns>The requested wrapper or <see langword="null"/>.</returns> - [return: NotNullIfNotNull(nameof(basePedestal))] - public static MicroPedestal? Get(MicroHIDPedestal? basePedestal) - { - if (basePedestal == null) - return null; - - return Dictionary.TryGetValue(basePedestal, out MicroPedestal found) ? found : (MicroPedestal)CreateStructureWrapper(basePedestal); - } } From 80ebd7cbff2f79284b0e9a53e9fbd91ff1fae7a6 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:45:02 +0930 Subject: [PATCH 112/215] pedestal --- .../Facility/Structures/PedestalLocker.cs | 45 ++++++++++--------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Structures/PedestalLocker.cs b/LabApi/Features/Wrappers/Facility/Structures/PedestalLocker.cs index f7307e17..31955cdb 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/PedestalLocker.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/PedestalLocker.cs @@ -1,5 +1,4 @@ using Interactables.Interobjects.DoorUtils; -using InventorySystem.Items.MicroHID; using MapGeneration.Distributors; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; @@ -15,12 +14,28 @@ public class PedestalLocker : Locker /// <summary> /// Contains all the cached pedestal lockers, accessible through their <see cref="PedestalScpLocker"/>. /// </summary> - public new static Dictionary<PedestalScpLocker, PedestalLocker> Dictionary { get; } = []; + public static new Dictionary<PedestalScpLocker, PedestalLocker> Dictionary { get; } = []; /// <summary> /// A reference to all <see cref="PedestalLocker"/> instances. /// </summary> - public new static IReadOnlyCollection<PedestalLocker> List => Dictionary.Values; + public static new IReadOnlyCollection<PedestalLocker> List => Dictionary.Values; + + /// <summary> + /// Gets the pedestal wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist and the provided <see cref="PedestalScpLocker"/> was not <see langword="null"/>. + /// </summary> + /// <param name="basePedestal">The <see cref="Base"/> of the pedestal locker.</param> + /// <returns>The requested wrapper or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(basePedestal))] + public static PedestalLocker? Get(PedestalScpLocker? basePedestal) + { + if (basePedestal == null) + { + return null; + } + + return Dictionary.TryGetValue(basePedestal, out PedestalLocker found) ? found : (PedestalLocker)CreateStructureWrapper(basePedestal); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -32,16 +47,9 @@ internal PedestalLocker(PedestalScpLocker pedestalScpLocker) Base = pedestalScpLocker; if (CanCache) + { Dictionary.Add(pedestalScpLocker, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -140,16 +148,11 @@ public ItemType[] AcceptableItems public void PlayDeniedSound(DoorPermissionFlags flags = DoorPermissionFlags.None) => Chamber.PlayDeniedSound(flags); /// <summary> - /// Gets the pedestal wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist and the provided <see cref="PedestalScpLocker"/> was not <see langword="null"/>. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="basePedestal">The <see cref="Base"/> of the pedestal locker.</param> - /// <returns>The requested wrapper or <see langword="null"/>.</returns> - [return: NotNullIfNotNull(nameof(basePedestal))] - public static PedestalLocker? Get(PedestalScpLocker? basePedestal) + internal override void OnRemove() { - if (basePedestal == null) - return null; - - return Dictionary.TryGetValue(basePedestal, out PedestalLocker found) ? found : (PedestalLocker)CreateStructureWrapper(basePedestal); + base.OnRemove(); + Dictionary.Remove(Base); } } From 9c635be03760cc75240b9e36f366652c5db0cdf7 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:45:07 +0930 Subject: [PATCH 113/215] riflerack --- .../Facility/Structures/RifleRackLocker.cs | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Structures/RifleRackLocker.cs b/LabApi/Features/Wrappers/Facility/Structures/RifleRackLocker.cs index af09bdea..5f4a7bc5 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/RifleRackLocker.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/RifleRackLocker.cs @@ -12,31 +12,24 @@ public class RifleRackLocker : Locker /// <summary> /// Contains all the cached rifle rack lockers, accessible through their <see cref="BaseLocker"/>. /// </summary> - public new static Dictionary<BaseLocker, RifleRackLocker> Dictionary { get; } = []; + public static new Dictionary<BaseLocker, RifleRackLocker> Dictionary { get; } = []; /// <summary> /// A reference to all <see cref="RifleRackLocker"/> instances. /// </summary> - public new static IReadOnlyCollection<RifleRackLocker> List => Dictionary.Values; + public static new IReadOnlyCollection<RifleRackLocker> List => Dictionary.Values; /// <summary> /// An internal constructor to prevent external instantiation. /// </summary> /// <param name="baseLocker">The base <see cref="BaseLocker"/> object.</param> internal RifleRackLocker(BaseLocker baseLocker) - :base(baseLocker) + : base(baseLocker) { if (CanCache) + { Dictionary.Add(baseLocker, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -47,7 +40,7 @@ public bool IsOpen get => MainChamber.IsOpen; set => MainChamber.IsOpen = value; } - + /// <summary> /// Gets whether the rifle rack can be interacted with by a <see cref="Player"/>. /// </summary> @@ -111,4 +104,13 @@ public float TargetCooldown /// Gets the chamber used for grenade spawn 2. /// </summary> public LockerChamber HeGrenade2 => Chambers[6]; + + /// <summary> + /// An internal method to remove itself from the cache when the base object is destroyed. + /// </summary> + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); + } } From d6a00eecde1632e2f0572faae94abaea3cb79854 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:45:11 +0930 Subject: [PATCH 114/215] standard --- .../Facility/Structures/StandardLocker.cs | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Structures/StandardLocker.cs b/LabApi/Features/Wrappers/Facility/Structures/StandardLocker.cs index 3c893892..79b4e76d 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/StandardLocker.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/StandardLocker.cs @@ -11,12 +11,12 @@ public class StandardLocker : Locker /// <summary> /// Contains all the cached standard lockers, accessible through their <see cref="BaseLocker"/>. /// </summary> - public new static Dictionary<BaseLocker, StandardLocker> Dictionary { get; } = []; + public static new Dictionary<BaseLocker, StandardLocker> Dictionary { get; } = []; /// <summary> /// A reference to all <see cref="StandardLocker"/> instances. /// </summary> - public new static IReadOnlyCollection<StandardLocker> List => Dictionary.Values; + public static new IReadOnlyCollection<StandardLocker> List => Dictionary.Values; /// <summary> /// An internal constructor to prevent external instantiation. @@ -26,16 +26,9 @@ internal StandardLocker(BaseLocker baseLocker) : base(baseLocker) { if (CanCache) + { Dictionary.Add(baseLocker, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the abase object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -85,4 +78,13 @@ internal override void OnRemove() /// This chamber does not control any doors. /// </remarks> public LockerChamber BottomRight => Chambers[3]; + + /// <summary> + /// An internal method to remove itself from the cache when the abase object is destroyed. + /// </summary> + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); + } } From 5d0afbac1f4321e71ce2dc630e156e676f2d37b0 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:45:16 +0930 Subject: [PATCH 115/215] structure --- .../Wrappers/Facility/Structures/Structure.cs | 201 +++++++++--------- 1 file changed, 105 insertions(+), 96 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Structures/Structure.cs b/LabApi/Features/Wrappers/Facility/Structures/Structure.cs index 7e10c1ab..b1da20ce 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/Structure.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/Structure.cs @@ -15,6 +15,49 @@ namespace LabApi.Features.Wrappers; /// </summary> public class Structure { + /// <summary> + /// Contains all the handlers for constructing wrappers for the associated base game types. + /// </summary> + private static readonly Dictionary<Type, Func<SpawnableStructure, Structure>> TypeWrappers = []; + + /// <summary> + /// Contains all the cached structures, accessible through their <see cref="SpawnableStructure"/>. + /// </summary> + public static Dictionary<SpawnableStructure, Structure> Dictionary { get; } = []; + + /// <summary> + /// A reference to all <see cref="Structure"/> instances. + /// </summary> + public static IReadOnlyCollection<Structure> List => Dictionary.Values; + + /// <summary> + /// Gets the structure wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="SpawnableStructure"/> was not null. + /// </summary> + /// <param name="spawnableStructure">The <see cref="Base"/> of the structure.</param> + /// <returns>The requested structure or null.</returns> + [return: NotNullIfNotNull(nameof(spawnableStructure))] + public static Structure? Get(SpawnableStructure? spawnableStructure) + { + if (spawnableStructure == null) + { + return null; + } + + return Dictionary.TryGetValue(spawnableStructure, out Structure structure) ? structure : CreateStructureWrapper(spawnableStructure); + } + + /// <summary> + /// Tries to get the structure wrapper from the <see cref="Dictionary"/>. + /// </summary> + /// <param name="spawnableStructure">The <see cref="Base"/> of the structure.</param> + /// <param name="structure">The requested structure.</param> + /// <returns>True of the structure exists, otherwise false.</returns> + public static bool TryGet(SpawnableStructure? spawnableStructure, [NotNullWhen(true)] out Structure? structure) + { + structure = Get(spawnableStructure); + return structure != null; + } + /// <summary> /// Initializes the <see cref="Structure"/> wrapper by subscribing to <see cref="SpawnableStructure"/> events. /// </summary> @@ -42,19 +85,65 @@ internal static void Initialize() } /// <summary> - /// Contains all the handlers for constructing wrappers for the associated base game types. + /// Creates a new wrapper from the base game object. + /// </summary> + /// <param name="structure">The base game structure to wrap.</param> + /// <returns>The newly created wrapper.</returns> + protected static Structure CreateStructureWrapper(SpawnableStructure structure) + { + Type targetType = structure.GetType(); + if (!TypeWrappers.TryGetValue(targetType, out Func<SpawnableStructure, Structure> handler)) + { +#if DEBUG + Logger.Warn($"Unable to find {nameof(Structure)} wrapper for {targetType.Name}, backup up to base constructor!"); +#endif + return new Structure(structure); + } + + Structure? wrapper = handler?.Invoke(structure); + if (wrapper == null) + { + Logger.Error($"Failed to create structure wrapper. A handler returned null for type {structure.GetType()}"); + return null!; + } + + return wrapper!; + } + + /// <summary> + /// Private method to handle the creation of new structures in the server. /// </summary> - private static readonly Dictionary<Type, Func<SpawnableStructure, Structure>> typeWrappers = []; + /// <param name="structure">The <see cref="SpawnableStructure"/> that was created.</param> + private static void OnAdded(SpawnableStructure structure) + { + if (!Dictionary.ContainsKey(structure)) + { + _ = CreateStructureWrapper(structure); + } + } /// <summary> - /// Contains all the cached structures, accessible through their <see cref="SpawnableStructure"/>. + /// Private method to handle the removal of structures from the server. /// </summary> - public static Dictionary<SpawnableStructure, Structure> Dictionary { get; } = []; + /// <param name="spawnableStructure">The <see cref="SpawnableStructure"/> that was removed.</param> + private static void OnRemoved(SpawnableStructure spawnableStructure) + { + if (Dictionary.TryGetValue(spawnableStructure, out Structure structure)) + { + structure.OnRemove(); + } + } /// <summary> - /// A reference to all <see cref="Structure"/> instances. + /// A private method to handle the addition of wrapper handlers. /// </summary> - public static IReadOnlyCollection<Structure> List => Dictionary.Values; + /// <typeparam name="T">The derived base game type to handle.</typeparam> + /// <param name="constructor">A handler to construct the wrapper with the base game instance.</param> + private static void Register<T>(Func<T, Structure> constructor) + where T : SpawnableStructure + { + TypeWrappers.Add(typeof(T), x => constructor((T)x)); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -66,22 +155,11 @@ internal Structure(SpawnableStructure spawnableStructure) StructurePositionSync = Base.gameObject.GetComponent<StructurePositionSync>(); if (CanCache) + { Dictionary.Add(spawnableStructure, this); + } } - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal virtual void OnRemove() - { - Dictionary.Remove(Base); - } - - /// <summary> - /// Whether to cache the wrapper. - /// </summary> - protected internal bool CanCache => !IsDestroyed && Base.isActiveAndEnabled; - /// <summary> /// The base <see cref="SpawnableStructure"/> object. /// </summary> @@ -144,6 +222,11 @@ public float RotationY /// </summary> public Room? Room => Room.Get(Base.ParentRoom); + /// <summary> + /// Whether to cache the wrapper. + /// </summary> + protected internal bool CanCache => !IsDestroyed && Base.isActiveAndEnabled; + // TODO: implement structure spawning. /// <summary> @@ -169,84 +252,10 @@ public override string ToString() } /// <summary> - /// Gets the structure wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="SpawnableStructure"/> was not null. - /// </summary> - /// <param name="spawnableStructure">The <see cref="Base"/> of the structure.</param> - /// <returns>The requested structure or null.</returns> - [return: NotNullIfNotNull(nameof(spawnableStructure))] - public static Structure? Get(SpawnableStructure? spawnableStructure) - { - if (spawnableStructure == null) - return null; - - return Dictionary.TryGetValue(spawnableStructure, out Structure structure) ? structure : CreateStructureWrapper(spawnableStructure); - } - - /// <summary> - /// Tries to get the structure wrapper from the <see cref="Dictionary"/>. - /// </summary> - /// <param name="spawnableStructure">The <see cref="Base"/> of the structure.</param> - /// <param name="structure">The requested structure.</param> - /// <returns>True of the structure exists, otherwise false.</returns> - public static bool TryGet(SpawnableStructure? spawnableStructure, [NotNullWhen(true)] out Structure? structure) - { - structure = Get(spawnableStructure); - return structure != null; - } - - /// <summary> - /// Creates a new wrapper from the base game object. - /// </summary> - /// <param name="structure">The base game structure to wrap.</param> - /// <returns>The newly created wrapper.</returns> - protected static Structure CreateStructureWrapper(SpawnableStructure structure) - { - Type targetType = structure.GetType(); - if (!typeWrappers.TryGetValue(targetType, out Func<SpawnableStructure, Structure> handler)) - { -#if DEBUG - Logger.Warn($"Unable to find {nameof(Structure)} wrapper for {targetType.Name}, backup up to base constructor!"); -#endif - return new Structure(structure); - } - - Structure? wrapper = handler?.Invoke(structure); - if (wrapper == null) - { - Logger.Error($"Failed to create structure wrapper. A handler returned null for type {structure.GetType()}"); - return null; - } - - return wrapper!; - } - - /// <summary> - /// Private method to handle the creation of new structures in the server. - /// </summary> - /// <param name="structure">The <see cref="SpawnableStructure"/> that was created.</param> - private static void OnAdded(SpawnableStructure structure) - { - if (!Dictionary.ContainsKey(structure)) - _ = CreateStructureWrapper(structure); - } - - /// <summary> - /// Private method to handle the removal of structures from the server. - /// </summary> - /// <param name="spawnableStructure">The <see cref="SpawnableStructure"/> that was removed.</param> - private static void OnRemoved(SpawnableStructure spawnableStructure) - { - if (Dictionary.TryGetValue(spawnableStructure, out Structure structure)) - structure.OnRemove(); - } - - /// <summary> - /// A private method to handle the addition of wrapper handlers. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <typeparam name="T">The derived base game type to handle.</typeparam> - /// <param name="constructor">A handler to construct the wrapper with the base game instance.</param> - private static void Register<T>(Func<T, Structure> constructor) where T : SpawnableStructure + internal virtual void OnRemove() { - typeWrappers.Add(typeof(T), x => constructor((T)x)); + Dictionary.Remove(Base); } } From 42f994832ca8746574d27449261a9fa780816222 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:45:23 +0930 Subject: [PATCH 116/215] wallcabinet --- .../Facility/Structures/WallCabinet.cs | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Structures/WallCabinet.cs b/LabApi/Features/Wrappers/Facility/Structures/WallCabinet.cs index ab26423f..4f5efd98 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/WallCabinet.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/WallCabinet.cs @@ -1,5 +1,4 @@ using Interactables.Interobjects.DoorUtils; -using MapGeneration.Distributors; using System.Collections.Generic; using BaseLocker = MapGeneration.Distributors.Locker; @@ -13,12 +12,12 @@ public class WallCabinet : Locker /// <summary> /// Contains all the cached wall cabinets, accessible through their <see cref="BaseLocker"/>. /// </summary> - public new static Dictionary<BaseLocker, WallCabinet> Dictionary { get; } = []; + public static new Dictionary<BaseLocker, WallCabinet> Dictionary { get; } = []; /// <summary> /// A reference to all <see cref="WallCabinet"/> instances. /// </summary> - public new static IReadOnlyCollection<WallCabinet> List => Dictionary.Values; + public static new IReadOnlyCollection<WallCabinet> List => Dictionary.Values; /// <summary> /// An internal constructor to prevent external instantiation. @@ -28,16 +27,9 @@ internal WallCabinet(BaseLocker baseLocker) : base(baseLocker) { if (CanCache) + { Dictionary.Add(baseLocker, this); - } - - /// <summary> - /// An internal method to remove itself form the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -98,4 +90,13 @@ public float TargetCooldown /// This chamber does not control any doors. /// </remarks> public LockerChamber UpperShelf => Chambers[2]; + + /// <summary> + /// An internal method to remove itself form the cache when the base object is destroyed. + /// </summary> + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); + } } From 0da17e83deaaae0aae0b0f59e8e8602a037debdb Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:45:29 +0930 Subject: [PATCH 117/215] workstation --- .../Facility/Structures/Workstation.cs | 47 ++++++++++--------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Structures/Workstation.cs b/LabApi/Features/Wrappers/Facility/Structures/Workstation.cs index 4d8b952e..10d9f0ed 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/Workstation.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/Workstation.cs @@ -16,32 +16,42 @@ public class Workstation : Structure /// <summary> /// Contains all the cached workstations, accessible through their <see cref="SpawnableStructure"/>. /// </summary> - public new static Dictionary<SpawnableStructure, Workstation> Dictionary = []; + public static new Dictionary<SpawnableStructure, Workstation> Dictionary { get; } = []; /// <summary> /// A reference to all <see cref="Workstation"/> instances. /// </summary> - public new static IReadOnlyCollection<Workstation> List => Dictionary.Values; + public static new IReadOnlyCollection<Workstation> List => Dictionary.Values; /// <summary> - /// An internal constructor to prevent external instantiation. + /// Gets the workstation wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist and the provided <see cref="SpawnableStructure"/> was not <see langword="null"/>. /// </summary> - /// <param name="spawnableStructure">The base <see cref="SpawnableStructure"/> object.</param> - internal Workstation(SpawnableStructure spawnableStructure) : base(spawnableStructure) + /// <param name="spawnableStructure">The <see cref="Structure.Base"/> of the workstation.</param> + /// <returns>The requested wrapper or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(spawnableStructure))] + public static new Workstation? Get(SpawnableStructure? spawnableStructure) { - BaseController = spawnableStructure.GetComponent<WorkstationController>(); + if (spawnableStructure == null) + { + return null; + } - if (CanCache) - Dictionary.Add(spawnableStructure, this); + return Dictionary.TryGetValue(spawnableStructure, out Workstation found) ? found : (Workstation)CreateStructureWrapper(spawnableStructure); } /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. + /// An internal constructor to prevent external instantiation. /// </summary> - internal override void OnRemove() + /// <param name="spawnableStructure">The base <see cref="SpawnableStructure"/> object.</param> + internal Workstation(SpawnableStructure spawnableStructure) + : base(spawnableStructure) { - base.OnRemove(); - Dictionary.Remove(Base); + BaseController = spawnableStructure.GetComponent<WorkstationController>(); + + if (CanCache) + { + Dictionary.Add(spawnableStructure, this); + } } /// <summary> @@ -88,16 +98,11 @@ public void Interact(Player player) => BaseController.ServerInteract(player.ReferenceHub, BaseController.ActivateCollider.ColliderId); /// <summary> - /// Gets the workstation wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist and the provided <see cref="SpawnableStructure"/> was not <see langword="null"/>. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="spawnableStructure">The <see cref="Structure.Base"/> of the workstation.</param> - /// <returns>The requested wrapper or <see langword="null"/>.</returns> - [return: NotNullIfNotNull(nameof(spawnableStructure))] - public static new Workstation? Get(SpawnableStructure? spawnableStructure) + internal override void OnRemove() { - if (spawnableStructure == null) - return null; - - return Dictionary.TryGetValue(spawnableStructure, out Workstation found) ? found : (Workstation)CreateStructureWrapper(spawnableStructure); + base.OnRemove(); + Dictionary.Remove(Base); } } From 632b3cd42e13bf1a67b753fa4737517f83d62913 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:45:35 +0930 Subject: [PATCH 118/215] cassie --- LabApi/Features/Wrappers/Facility/Cassie.cs | 35 +++++++++++---------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Cassie.cs b/LabApi/Features/Wrappers/Facility/Cassie.cs index 79d267e8..338d7d79 100644 --- a/LabApi/Features/Wrappers/Facility/Cassie.cs +++ b/LabApi/Features/Wrappers/Facility/Cassie.cs @@ -8,27 +8,27 @@ namespace LabApi.Features.Wrappers; /// <summary> -/// The wrapper for in game Cassie announcer. +/// The wrapper for in game CASSIE announcer. /// </summary> public static class Cassie { /// <summary> - /// Gets whether Cassie is currently speaking. + /// Gets whether CASSIE is currently speaking. /// </summary> public static bool IsSpeaking => singleton.queue.Count != 0; /// <summary> - /// Gets all available voice lines for Cassie. + /// Gets all available voice lines for CASSIE. /// </summary> public static VoiceLine[] AllLines => singleton.voiceLines; /// <summary> - /// Gets all collection names in which voicelines are in. + /// Gets all collection names in which voice lines are in. /// </summary> public static string[] CollectionNames => singleton.voiceLines.Select(n => n.collection).Distinct().ToArray(); /// <summary> - /// Checks whether a specified word is valid for cassie. + /// Checks whether a specified word is valid for CASSIE. /// <note>String comparison is case-insensitive.</note> /// </summary> /// <param name="word">The word to check.</param> @@ -40,23 +40,24 @@ public static class Cassie /// </summary> /// <param name="message">The message.</param> /// <param name="rawNumber">Raw numbers.</param> + /// <param name="speed">The speed.</param> /// <returns>Duration of the specific message in seconds.</returns> public static float CalculateDuration(string message, bool rawNumber = false, float speed = 1f) => singleton.CalculateDuration(message, rawNumber, speed); /// <summary> - /// Plays a custom announcement. + /// Plays a custom announcement. /// </summary> - /// <param name="message">The sentence Cassie is supposed to say.</param> - /// <param name="isHeld">Sets a minimal 3-second moment of silence before the announcement. For most cases you wanna keep it true.</param> - /// <param name="isNoisy">Whether the background noises play.</param> - /// <param name="isSubtitles">Show subtitles.</param> - /// <param name="customSubtitles">Custom subtitles to appear instead of the actual message.</param> + /// <param name="message">The sentence CASSIE is supposed to say.</param> + /// <param name="isHeld">Sets a minimal 3-second moment of silence before the announcement. For most cases you wanna keep it true.</param> + /// <param name="isNoisy">Whether the background noises play.</param> + /// <param name="isSubtitles">Show subtitles.</param> + /// <param name="customSubtitles">Custom subtitles to appear instead of the actual message.</param> public static void Message(string message, bool isHeld = false, bool isNoisy = true, bool isSubtitles = true, string customSubtitles = "") => RespawnEffectsController.PlayCassieAnnouncement(message, isHeld, isNoisy, isSubtitles, customSubtitles); /// <summary> /// Plays the custom announcement with chance of 0f to 1f of adding a glitch or jam before each word. Values closer to 1f are higher chances. /// </summary> - /// <param name="message">The sentence Cassie is supposed to say.</param> + /// <param name="message">The sentence CASSIE is supposed to say.</param> /// <param name="glitchChance">The chance for glitch sound to be added before each word. Range from 0f to 1f.</param> /// <param name="jamChance">The chance for jam sound to be added before each word. Range from 0f to 1f.</param> public static void GlitchyMessage(string message, float glitchChance, float jamChance) => singleton.ServerOnlyAddGlitchyPhrase(message, glitchChance, jamChance); @@ -69,12 +70,12 @@ public static class Cassie public static void ScpTermination(Player player, DamageHandlerBase info) => AnnounceScpTermination(player.ReferenceHub, info); /// <summary> - /// Clears the Cassie announcements queue. + /// Clears the CASSIE announcements queue. /// </summary> public static void Clear() => singleton.ClearQueue(); /// <summary> - /// Converts player's team into Cassie-able word. Unit names are converted into NATO_X words, followed by a number. For example "Alpha-5" is converted to "NATO_A 5". + /// Converts player's team into CASSIE-able word. Unit names are converted into NATO_X words, followed by a number. For example "Alpha-5" is converted to "NATO_A 5". /// </summary> /// <param name="team">Target team.</param> /// <param name="unitName">MTF Unit name (for team <see cref="Team.FoundationForces"/>).</param> @@ -92,15 +93,15 @@ public static class Cassie /// Converts player's <see cref="RoleTypeId"/> into an SCP <b>number</b> identifier. /// </summary> /// <param name="role">The target <see cref="RoleTypeId"/>.</param> - /// <param name="withoutSpace">The SCP number without spaces between. Used by Cassie.</param> + /// <param name="withoutSpace">The SCP number without spaces between. Used by CASSIE.</param> /// <param name="withSpace">The SCP number with spaces between. Used by Subtitles.</param> public static void ConvertScp(RoleTypeId role, out string withoutSpace, out string withSpace) => NineTailedFoxAnnouncer.ConvertSCP(role, out withoutSpace, out withSpace); /// <summary> /// Converts player's role name into an SCP <b>number</b> identifier. /// </summary> - /// <param name="roleName">The targets role name</param> - /// <param name="withoutSpace">The SCP number without spaces between. Used by Cassie.</param> + /// <param name="roleName">The targets role name.</param> + /// <param name="withoutSpace">The SCP number without spaces between. Used by CASSIE.</param> /// <param name="withSpace">The SCP number with spaces between. Used by Subtitles.</param> public static void ConvertScp(string roleName, out string withoutSpace, out string withSpace) => NineTailedFoxAnnouncer.ConvertSCP(roleName, out withoutSpace, out withSpace); } \ No newline at end of file From 8d7df323c2eb9d543ed8936852dea18c0b2b4a6e Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:45:46 +0930 Subject: [PATCH 119/215] decontamination --- LabApi/Features/Wrappers/Facility/Decontamination.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LabApi/Features/Wrappers/Facility/Decontamination.cs b/LabApi/Features/Wrappers/Facility/Decontamination.cs index d28b258e..5c048120 100644 --- a/LabApi/Features/Wrappers/Facility/Decontamination.cs +++ b/LabApi/Features/Wrappers/Facility/Decontamination.cs @@ -22,7 +22,7 @@ public static DecontaminationStatus Status public static bool IsDecontaminating => Singleton.IsDecontaminating; /// <summary> - /// Gets the current server time since round has started plus the <see cref="Offset"/> + /// Gets the current server time since round has started plus the <see cref="Offset"/>. /// </summary> public static double ServerTime => GetServerTime; From d683f2656354825573542b20c7c8b39c7a72120c Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:45:51 +0930 Subject: [PATCH 120/215] elevator --- LabApi/Features/Wrappers/Facility/Elevator.cs | 88 ++++++++++--------- 1 file changed, 46 insertions(+), 42 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Elevator.cs b/LabApi/Features/Wrappers/Facility/Elevator.cs index b9bf631c..05888144 100644 --- a/LabApi/Features/Wrappers/Facility/Elevator.cs +++ b/LabApi/Features/Wrappers/Facility/Elevator.cs @@ -1,10 +1,10 @@ -using Interactables.Interobjects; +using Generators; +using Interactables.Interobjects; using Interactables.Interobjects.DoorUtils; using MapGeneration.Distributors; using System.Collections.Generic; using System.Linq; using UnityEngine; -using Generators; using BaseElevatorDoor = Interactables.Interobjects.ElevatorDoor; namespace LabApi.Features.Wrappers; @@ -25,19 +25,41 @@ public class Elevator public static IReadOnlyCollection<Elevator> List => Dictionary.Values; /// <summary> - /// A private constructor to prevent external instantiation. + /// Locks every door of every elevator on map. /// </summary> - /// <param name="elevator">The <see cref="ElevatorChamber"/> of the elevator.</param> - private Elevator(ElevatorChamber elevator) + public static void LockAll() { - Dictionary.Add(elevator, this); - Base = elevator; + foreach (Elevator el in List) + { + el.LockAllDoors(); + } } /// <summary> - /// The base object. + /// Unlocks every door of every elevator on map. /// </summary> - public ElevatorChamber Base { get; } + public static void UnlockAll() + { + foreach (Elevator el in List) + { + el.UnlockAllDoors(); + } + } + + /// <summary> + /// Gets the elevator wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist. + /// </summary> + /// <param name="elevatorChamber">The <see cref="ElevatorChamber"/> of the elevator.</param> + /// <returns>The requested elevator.</returns> + public static Elevator Get(ElevatorChamber elevatorChamber) => + Dictionary.TryGetValue(elevatorChamber, out Elevator generator) ? generator : new Elevator(elevatorChamber); + + /// <summary> + /// Gets the enumerable of elevators that are assigned to the specific group. + /// </summary> + /// <param name="group">The specified elevator group.</param> + /// <returns>Enumerable where the group is equal to the one specified.</returns> + public static IEnumerable<Elevator> GetByGroup(ElevatorGroup group) => List.Where(n => n.Group == group); /// <summary> /// Initializes the <see cref="Elevator"/> class to subscribe to <see cref="ElevatorChamber"/> events. @@ -51,6 +73,21 @@ internal static void Initialize() ElevatorChamber.OnElevatorRemoved += (chamber) => Dictionary.Remove(chamber); } + /// <summary> + /// A private constructor to prevent external instantiation. + /// </summary> + /// <param name="elevator">The <see cref="ElevatorChamber"/> of the elevator.</param> + private Elevator(ElevatorChamber elevator) + { + Dictionary.Add(elevator, this); + Base = elevator; + } + + /// <summary> + /// The base object. + /// </summary> + public ElevatorChamber Base { get; } + /// <summary> /// Gets all the doors associated with this elevator. /// </summary> @@ -137,24 +174,6 @@ public override string ToString() return $"[Elevator: Group={Group}, IsReady={IsReady}, GoingUp={GoingUp}, CurrentSequence={CurrentSequence}]"; } - /// <summary> - /// Locks every door of every elevator on map. - /// </summary> - public static void LockAll() - { - foreach (Elevator el in List) - el.LockAllDoors(); - } - - /// <summary> - /// Unlocks every door of every elevator on map. - /// </summary> - public static void UnlockAll() - { - foreach (Elevator el in List) - el.UnlockAllDoors(); - } - /// <summary> /// Attempts to send the elevator to target destination. /// </summary> @@ -182,19 +201,4 @@ public static void UnlockAll() /// Unlocks all elevator doors assigned to this chamber. /// </summary> public void UnlockAllDoors() => Base.ServerLockAllDoors(DoorLockReason.AdminCommand, false); - - /// <summary> - /// Gets the elevator wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist. - /// </summary> - /// <param name="elevatorChamber">The <see cref="ElevatorChamber"/> of the elevator.</param> - /// <returns>The requested elevator.</returns> - public static Elevator Get(ElevatorChamber elevatorChamber) => - Dictionary.TryGetValue(elevatorChamber, out Elevator generator) ? generator : new Elevator(elevatorChamber); - - /// <summary> - /// Gets the enumerable of elevators that are assigned to the specific group. - /// </summary> - /// <param name="group">The specified elevator group.</param> - /// <returns>Enumerable where the group is equal to the one specified.</returns> - public static IEnumerable<Elevator> GetByGroup(ElevatorGroup group) => List.Where(n => n.Group == group); } \ No newline at end of file From afab20877d8c51a6e67cc53ccd88c313bc2520f3 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:45:55 +0930 Subject: [PATCH 121/215] map --- LabApi/Features/Wrappers/Facility/Map.cs | 44 +++++++++++++++++++----- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Map.cs b/LabApi/Features/Wrappers/Facility/Map.cs index c85765a1..c4fcd8a8 100644 --- a/LabApi/Features/Wrappers/Facility/Map.cs +++ b/LabApi/Features/Wrappers/Facility/Map.cs @@ -68,7 +68,7 @@ public static class Map /// <remarks> /// By default this is included in the <see cref="EscapeZones"/> list. /// </remarks> - public static Bounds DefaultEscapeZone = Escape.DefaultEscapeZone; + public static Bounds DefaultEscapeZone { get; } = Escape.DefaultEscapeZone; /// <summary> /// A list of all bounds used as escape zones. @@ -91,10 +91,11 @@ public static class Map public static void RemoveEscapeZone(Bounds escapeZone) => EscapeZones.Remove(escapeZone); #region Get Random - /// <summary> - /// Gets a random <see cref="Room"/>. - /// </summary> - /// <returns>The random room if there were any rooms otherwise null.</returns> + + /// <summary> + /// Gets a random <see cref="Room"/>. + /// </summary> + /// <returns>The random room if there were any rooms otherwise null.</returns> public static Room? GetRandomRoom() { return Rooms.Count != 0 ? Rooms.ElementAt(UnityEngine.Random.Range(0, Rooms.Count)) : null; @@ -369,7 +370,9 @@ public static class Map public static void TurnOffLights(float duration) { foreach (LightsController lc in LightsController.List) + { lc.FlickerLights(duration); + } } /// <summary> @@ -383,11 +386,13 @@ public static void TurnOffLights(float duration) /// <param name="zone">The zone to turn the lights off in.</param> public static void TurnOffLights(FacilityZone zone) { - //TODO: use zone wrapper? + // TODO: use zone wrapper? foreach (LightsController lc in LightsController.List) { if (lc.Room.Zone != zone) + { continue; + } lc.FlickerLights(float.MaxValue); } @@ -403,13 +408,14 @@ public static void TurnOffLights(IEnumerable<FacilityZone> zones) foreach (LightsController lc in LightsController.List) { if (!zones.Contains(lc.Room.Zone)) + { continue; + } lc.FlickerLights(float.MaxValue); } } - /// <summary> /// Turns off all lights in a zone for a certain duration. /// </summary> @@ -421,7 +427,9 @@ public static void TurnOffLights(float duration, FacilityZone zone) foreach (LightsController lc in LightsController.List) { if (lc.Room.Zone != zone) + { continue; + } lc.FlickerLights(duration); } @@ -438,7 +446,9 @@ public static void TurnOffLights(float duration, IEnumerable<FacilityZone> zones foreach (LightsController lc in LightsController.List) { if (!zones.Contains(lc.Room.Zone)) + { continue; + } lc.FlickerLights(duration); } @@ -450,7 +460,9 @@ public static void TurnOffLights(float duration, IEnumerable<FacilityZone> zones public static void TurnOnLights() { foreach (LightsController lc in LightsController.List) + { lc.LightsEnabled = true; + } } /// <summary> @@ -463,7 +475,9 @@ public static void TurnOnLights(FacilityZone zone) foreach (LightsController lc in LightsController.List) { if (lc.Room.Zone != zone) + { continue; + } lc.LightsEnabled = true; } @@ -479,7 +493,9 @@ public static void TurnOnLights(IEnumerable<FacilityZone> zones) foreach (LightsController lc in LightsController.List) { if (!zones.Contains(lc.Room.Zone)) + { continue; + } lc.LightsEnabled = true; } @@ -494,7 +510,9 @@ public static void TurnOnLights(IEnumerable<FacilityZone> zones) public static void SetColorOfLights(UnityEngine.Color color) { foreach (LightsController lc in LightsController.List) + { lc.OverrideLightsColor = color; + } } /// <summary> @@ -508,7 +526,9 @@ public static void SetColorOfLights(UnityEngine.Color color, FacilityZone zone) foreach (LightsController lc in LightsController.List) { if (lc.Room.Zone != zone) + { continue; + } lc.OverrideLightsColor = color; } @@ -525,7 +545,9 @@ public static void SetColorOfLights(UnityEngine.Color color, IEnumerable<Facilit foreach (LightsController lc in LightsController.List) { if (!zones.Contains(lc.Room.Zone)) + { continue; + } lc.OverrideLightsColor = color; } @@ -537,11 +559,13 @@ public static void SetColorOfLights(UnityEngine.Color color, IEnumerable<Facilit public static void ResetColorOfLights() { foreach (LightsController lc in LightsController.List) + { lc.OverrideLightsColor = UnityEngine.Color.clear; + } } /// <summary> - /// Sets the color of all the lights in a zone back to their default; + /// Sets the color of all the lights in a zone back to their default. /// </summary> /// <param name="zone">The zone to effect.</param> public static void ResetColorOfLights(FacilityZone zone) @@ -550,7 +574,9 @@ public static void ResetColorOfLights(FacilityZone zone) foreach (LightsController lc in LightsController.List) { if (lc.Room.Zone != zone) + { continue; + } lc.OverrideLightsColor = UnityEngine.Color.clear; } @@ -566,7 +592,9 @@ public static void ResetColorOfLights(IEnumerable<FacilityZone> zones) foreach (LightsController lc in LightsController.List) { if (!zones.Contains(lc.Room.Zone)) + { continue; + } lc.OverrideLightsColor = UnityEngine.Color.clear; } From d952fd2aaece3b27ba7154ca38f46b0a62a845b6 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:46:00 +0930 Subject: [PATCH 122/215] round --- LabApi/Features/Wrappers/Facility/Round.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/LabApi/Features/Wrappers/Facility/Round.cs b/LabApi/Features/Wrappers/Facility/Round.cs index 93855682..8a10c506 100644 --- a/LabApi/Features/Wrappers/Facility/Round.cs +++ b/LabApi/Features/Wrappers/Facility/Round.cs @@ -36,8 +36,10 @@ public static bool CanRoundEnd { get { - if (IsLocked || KeepRoundOnOne && ReferenceHub.AllHubs.Count(x => x.authManager.InstanceMode != ClientInstanceMode.DedicatedServer) < 2 || !IsRoundStarted) + if (IsLocked || (KeepRoundOnOne && (ReferenceHub.AllHubs.Count(x => x.authManager.InstanceMode != ClientInstanceMode.DedicatedServer) < 2)) || !IsRoundStarted) + { return false; + } return IsRoundStarted && !IsLocked; } @@ -133,7 +135,9 @@ public static int ExtraTargets public static void Restart(bool fastRestart = false, bool overrideRestartAction = false, NextRoundAction restartAction = NextRoundAction.DoNothing) { if (overrideRestartAction) + { StopNextRound = restartAction; + } bool prevValue = CustomNetworkManager.EnableFastRestart; CustomNetworkManager.EnableFastRestart = fastRestart; @@ -160,7 +164,9 @@ public static bool End(bool force = false) } if (!CanRoundEnd) + { return false; + } RoundSummary.singleton.ForceEnd(); return true; From c3b20523fa7a35189df9e83da9f5f857659b6406 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:46:05 +0930 Subject: [PATCH 123/215] warhead --- LabApi/Features/Wrappers/Facility/Warhead.cs | 79 ++++++++++++-------- 1 file changed, 47 insertions(+), 32 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Warhead.cs b/LabApi/Features/Wrappers/Facility/Warhead.cs index 963495fc..fdc3557e 100644 --- a/LabApi/Features/Wrappers/Facility/Warhead.cs +++ b/LabApi/Features/Wrappers/Facility/Warhead.cs @@ -13,13 +13,6 @@ namespace LabApi.Features.Wrappers; /// </summary> public static class Warhead { - [InitializeWrapper] - internal static void Initialize() - { - ServerEvents.WaitingForPlayers += OnWaitingForPlayers; - // TODO: Might want to handle this a different way as we are missing on destroy - } - /// <summary> /// The base <see cref="AlphaWarheadController"/>. /// Null if they have not been created yet, see <see cref="Exists"/>. @@ -60,7 +53,9 @@ public static bool LeverStatus set { if (BaseNukesitePanel != null) + { BaseNukesitePanel.Networkenabled = value; + } } } @@ -82,7 +77,9 @@ public static bool IsLocked set { if (BaseController != null) + { BaseController.IsLocked = value; + } } } @@ -102,11 +99,7 @@ public static bool IsLocked public static float DetonationTime { get => AlphaWarheadController.TimeUntilDetonation; - set - { - if (BaseController != null) - BaseController.ForceTime(value); - } + set => BaseController?.ForceTime(value); } /// <summary> @@ -118,7 +111,9 @@ public static double CooldownTime set { if (BaseController != null) + { BaseController.NetworkCooldownEndTime = NetworkTime.time + value; + } } } @@ -132,8 +127,8 @@ public static bool ForceCountdownToggle } /// <summary> - /// Indicates how much time is left for the DMS to activate. - /// Value is capped by <see cref="DeadManSwitchMaxTime"/>. + /// Indicates how much time is left for the DMS to activate. + /// Value is capped by <see cref="DeadManSwitchMaxTime"/>. /// </summary> public static float DeadManSwitchRemaining { @@ -162,20 +157,25 @@ public static DetonationScenario Scenario get { if (BaseController == null) - return new DetonationScenario(); + { + return default; + } return ScenarioType switch { WarheadScenarioType.Start => StartScenarios[BaseController.Info.ScenarioId], WarheadScenarioType.Resume => ResumeScenarios[BaseController.Info.ScenarioId], WarheadScenarioType.DeadmanSwitch => DeadmanSwitchScenario, - _ => new DetonationScenario() + _ => default, }; } + set { if (BaseController == null) + { return; + } if (value.Equals(default)) { @@ -224,7 +224,7 @@ public static DetonationScenario Scenario /// <summary> /// Gets the deadman switch scenario. /// </summary> - public static DetonationScenario DeadmanSwitchScenario { get; private set; } = new DetonationScenario(); + public static DetonationScenario DeadmanSwitchScenario { get; private set; } = default; /// <summary> /// Starts the detonation countdown. @@ -261,7 +261,9 @@ public static void Detonate() public static void OpenBlastDoors() { foreach (BlastDoor door in BlastDoor.Instances) + { door.ServerSetTargetState(true); + } } /// <summary> @@ -270,7 +272,9 @@ public static void OpenBlastDoors() public static void CloseBlastDoors() { foreach (BlastDoor door in BlastDoor.Instances) + { door.ServerSetTargetState(false); + } } /// <summary> @@ -278,6 +282,17 @@ public static void CloseBlastDoors() /// </summary> public static void Shake() => BaseController?.RpcShake(false); + /// <summary> + /// Initializes the warhead class. + /// </summary> + [InitializeWrapper] + internal static void Initialize() + { + ServerEvents.WaitingForPlayers += OnWaitingForPlayers; + + // TODO: Might want to handle this a different way as we are missing on destroy + } + /// <summary> /// Handles the creation of the warhead components. /// </summary> @@ -285,7 +300,7 @@ private static void OnWaitingForPlayers() { BaseOutsidePanel = UnityEngine.Object.FindObjectOfType<AlphaWarheadOutsitePanel>(); - StartScenarios = BaseController.StartScenarios.Select((x, i) => new DetonationScenario(x, (byte)i, WarheadScenarioType.Start)).ToArray(); + StartScenarios = BaseController!.StartScenarios.Select((x, i) => new DetonationScenario(x, (byte)i, WarheadScenarioType.Start)).ToArray(); ResumeScenarios = BaseController.ResumeScenarios.Select((x, i) => new DetonationScenario(x, (byte)i, WarheadScenarioType.Resume)).ToArray(); DeadmanSwitchScenario = new DetonationScenario(BaseController.DeadmanSwitchScenario, 0, WarheadScenarioType.DeadmanSwitch); } @@ -303,20 +318,6 @@ private static void OnMapDestroyed() /// </summary> public readonly struct DetonationScenario { - /// <summary> - /// Internal constructor to prevent external instantiation. - /// </summary> - /// <param name="detonationScenario">The <see cref="DetonationScenario"/>.</param> - /// <param name="id">The <see cref="byte"/> id of the scenario.</param> - /// <param name="type">The <see cref="WarheadScenarioType"/>.</param> - internal DetonationScenario(AlphaWarheadController.DetonationScenario detonationScenario, byte id, WarheadScenarioType type) - { - TimeToDetonate = detonationScenario.TimeToDetonate; - AdditionalTime = detonationScenario.AdditionalTime; - Type = type; - Id = id; - } - /// <summary> /// The countdown time announced. /// </summary> @@ -337,6 +338,20 @@ internal DetonationScenario(AlphaWarheadController.DetonationScenario detonation /// </summary> public readonly byte Id; + /// <summary> + /// Internal constructor to prevent external instantiation. + /// </summary> + /// <param name="detonationScenario">The <see cref="DetonationScenario"/>.</param> + /// <param name="id">The <see cref="byte"/> id of the scenario.</param> + /// <param name="type">The <see cref="WarheadScenarioType"/>.</param> + internal DetonationScenario(AlphaWarheadController.DetonationScenario detonationScenario, byte id, WarheadScenarioType type) + { + TimeToDetonate = detonationScenario.TimeToDetonate; + AdditionalTime = detonationScenario.AdditionalTime; + Type = type; + Id = id; + } + /// <summary> /// The actual time it takes for the warhead to detonate. /// </summary> From de40f1e43b298a9c39551cb9af6147a7575115c8 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:46:11 +0930 Subject: [PATCH 124/215] firearm --- .../Wrappers/Items/Firearm/FirearmItem.cs | 44 ++++++++++--------- .../Items/Firearm/ParticleDisruptorItem.cs | 44 ++++++++++--------- 2 files changed, 48 insertions(+), 40 deletions(-) diff --git a/LabApi/Features/Wrappers/Items/Firearm/FirearmItem.cs b/LabApi/Features/Wrappers/Items/Firearm/FirearmItem.cs index 14a0480d..4b17f6ac 100644 --- a/LabApi/Features/Wrappers/Items/Firearm/FirearmItem.cs +++ b/LabApi/Features/Wrappers/Items/Firearm/FirearmItem.cs @@ -12,12 +12,28 @@ public class FirearmItem : Item /// <summary> /// Contains all the cached firearm items, accessible through their <see cref="Firearm"/>. /// </summary> - public new static Dictionary<Firearm, FirearmItem> Dictionary { get; } = []; + public static new Dictionary<Firearm, FirearmItem> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="FirearmItem"/>. /// </summary> - public new static IReadOnlyCollection<FirearmItem> List => Dictionary.Values; + public static new IReadOnlyCollection<FirearmItem> List => Dictionary.Values; + + /// <summary> + /// Gets the firearm item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="Firearm"/> was not null. + /// </summary> + /// <param name="firearm">The <see cref="Base"/> of the item.</param> + /// <returns>The requested item or null.</returns> + [return: NotNullIfNotNull(nameof(firearm))] + public static FirearmItem? Get(Firearm? firearm) + { + if (firearm == null) + { + return null; + } + + return Dictionary.TryGetValue(firearm, out FirearmItem item) ? item : (FirearmItem)CreateItemWrapper(firearm); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal FirearmItem(Firearm firearm) Base = firearm; if (CanCache) + { Dictionary.Add(firearm, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -47,16 +56,11 @@ internal override void OnRemove() public new Firearm Base { get; } /// <summary> - /// Gets the firearm item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="Firearm"/> was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="firearm">The <see cref="Base"/> of the item.</param> - /// <returns>The requested item or null.</returns> - [return: NotNullIfNotNull(nameof(firearm))] - public static FirearmItem? Get(Firearm? firearm) + internal override void OnRemove() { - if (firearm == null) - return null; - - return Dictionary.TryGetValue(firearm, out FirearmItem item) ? item : (FirearmItem)CreateItemWrapper(firearm); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/Firearm/ParticleDisruptorItem.cs b/LabApi/Features/Wrappers/Items/Firearm/ParticleDisruptorItem.cs index f62c5933..286e60ec 100644 --- a/LabApi/Features/Wrappers/Items/Firearm/ParticleDisruptorItem.cs +++ b/LabApi/Features/Wrappers/Items/Firearm/ParticleDisruptorItem.cs @@ -12,12 +12,28 @@ public class ParticleDisruptorItem : FirearmItem /// <summary> /// Contains all the cached particle disruptor items, accessible through their <see cref="ParticleDisruptor"/>. /// </summary> - public new static Dictionary<ParticleDisruptor, ParticleDisruptorItem> Dictionary { get; } = []; + public static new Dictionary<ParticleDisruptor, ParticleDisruptorItem> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="ParticleDisruptorItem"/>. /// </summary> - public new static IReadOnlyCollection<ParticleDisruptorItem> List => Dictionary.Values; + public static new IReadOnlyCollection<ParticleDisruptorItem> List => Dictionary.Values; + + /// <summary> + /// Gets the particle disruptor item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="ParticleDisruptor"/> was not null. + /// </summary> + /// <param name="particleDisruptor">The <see cref="Base"/> of the item.</param> + /// <returns>The requested item or null.</returns> + [return: NotNullIfNotNull(nameof(particleDisruptor))] + public static ParticleDisruptorItem? Get(ParticleDisruptor? particleDisruptor) + { + if (particleDisruptor == null) + { + return null; + } + + return Dictionary.TryGetValue(particleDisruptor, out ParticleDisruptorItem item) ? item : (ParticleDisruptorItem)CreateItemWrapper(particleDisruptor); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal ParticleDisruptorItem(ParticleDisruptor particleDisruptor) Base = particleDisruptor; if (CanCache) + { Dictionary.Add(particleDisruptor, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -47,16 +56,11 @@ internal override void OnRemove() public new ParticleDisruptor Base { get; } /// <summary> - /// Gets the particle disruptor item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="ParticleDisruptor"/> was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="particleDisruptor">The <see cref="Base"/> of the item.</param> - /// <returns>The requested item or null.</returns> - [return: NotNullIfNotNull(nameof(particleDisruptor))] - public static ParticleDisruptorItem? Get(ParticleDisruptor? particleDisruptor) + internal override void OnRemove() { - if (particleDisruptor == null) - return null; - - return Dictionary.TryGetValue(particleDisruptor, out ParticleDisruptorItem item) ? item : (ParticleDisruptorItem)CreateItemWrapper(particleDisruptor); + base.OnRemove(); + Dictionary.Remove(Base); } } From 84cde74436ef602fa971699b3155e897367a9a7b Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:46:21 +0930 Subject: [PATCH 125/215] light --- .../Wrappers/Items/Light/FlashlightItem.cs | 44 ++++++++++--------- .../Wrappers/Items/Light/LanternItem.cs | 44 ++++++++++--------- .../Wrappers/Items/Light/LightItem.cs | 44 ++++++++++--------- 3 files changed, 72 insertions(+), 60 deletions(-) diff --git a/LabApi/Features/Wrappers/Items/Light/FlashlightItem.cs b/LabApi/Features/Wrappers/Items/Light/FlashlightItem.cs index 87d660ae..8e3a83af 100644 --- a/LabApi/Features/Wrappers/Items/Light/FlashlightItem.cs +++ b/LabApi/Features/Wrappers/Items/Light/FlashlightItem.cs @@ -12,12 +12,28 @@ public class FlashlightItem : LightItem /// <summary> /// Contains all the cached flashlight items, accessible through their <see cref="BaseFlashlightItem"/>. /// </summary> - public new static Dictionary<BaseFlashlightItem, FlashlightItem> Dictionary { get; } = []; + public static new Dictionary<BaseFlashlightItem, FlashlightItem> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="FlashlightItem"/>. /// </summary> - public new static IReadOnlyCollection<FlashlightItem> List => Dictionary.Values; + public static new IReadOnlyCollection<FlashlightItem> List => Dictionary.Values; + + /// <summary> + /// Gets the flashlight item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseFlashlightItem"/> was not null. + /// </summary> + /// <param name="baseFlashlightItem">The <see cref="Base"/> of the item.</param> + /// <returns>The requested item or null.</returns> + [return: NotNullIfNotNull(nameof(baseFlashlightItem))] + public static FlashlightItem? Get(BaseFlashlightItem? baseFlashlightItem) + { + if (baseFlashlightItem == null) + { + return null; + } + + return Dictionary.TryGetValue(baseFlashlightItem, out FlashlightItem item) ? item : (FlashlightItem)CreateItemWrapper(baseFlashlightItem); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal FlashlightItem(BaseFlashlightItem baseFlashlightItem) Base = baseFlashlightItem; if (CanCache) + { Dictionary.Add(baseFlashlightItem, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -47,16 +56,11 @@ internal override void OnRemove() public new BaseFlashlightItem Base { get; } /// <summary> - /// Gets the flashlight item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseFlashlightItem"/> was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="baseFlashlightItem">The <see cref="Base"/> of the item.</param> - /// <returns>The requested item or null.</returns> - [return: NotNullIfNotNull(nameof(baseFlashlightItem))] - public static FlashlightItem? Get(BaseFlashlightItem? baseFlashlightItem) + internal override void OnRemove() { - if (baseFlashlightItem == null) - return null; - - return Dictionary.TryGetValue(baseFlashlightItem, out FlashlightItem item) ? item : (FlashlightItem)CreateItemWrapper(baseFlashlightItem); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/Light/LanternItem.cs b/LabApi/Features/Wrappers/Items/Light/LanternItem.cs index 81836e53..396ba16d 100644 --- a/LabApi/Features/Wrappers/Items/Light/LanternItem.cs +++ b/LabApi/Features/Wrappers/Items/Light/LanternItem.cs @@ -12,12 +12,28 @@ public class LanternItem : LightItem /// <summary> /// Contains all the cached lantern items, accessible through their <see cref="BaseLanternItem"/>. /// </summary> - public new static Dictionary<BaseLanternItem, LanternItem> Dictionary { get; } = []; + public static new Dictionary<BaseLanternItem, LanternItem> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="LanternItem"/>. /// </summary> - public new static IReadOnlyCollection<LanternItem> List => Dictionary.Values; + public static new IReadOnlyCollection<LanternItem> List => Dictionary.Values; + + /// <summary> + /// Gets the lantern item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseLanternItem"/> was not null. + /// </summary> + /// <param name="baseLanternItem">The <see cref="Base"/> of the item.</param> + /// <returns>The requested item or null.</returns> + [return: NotNullIfNotNull(nameof(baseLanternItem))] + public static LanternItem? Get(BaseLanternItem? baseLanternItem) + { + if (baseLanternItem == null) + { + return null; + } + + return Dictionary.TryGetValue(baseLanternItem, out LanternItem item) ? item : (LanternItem)CreateItemWrapper(baseLanternItem); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal LanternItem(BaseLanternItem baseLanternItem) Base = baseLanternItem; if (CanCache) + { Dictionary.Add(baseLanternItem, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -47,16 +56,11 @@ internal override void OnRemove() public new BaseLanternItem Base { get; } /// <summary> - /// Gets the lantern item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseLanternItem"/> was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="baseLanternItem">The <see cref="Base"/> of the item.</param> - /// <returns>The requested item or null.</returns> - [return: NotNullIfNotNull(nameof(baseLanternItem))] - public static LanternItem? Get(BaseLanternItem? baseLanternItem) + internal override void OnRemove() { - if (baseLanternItem == null) - return null; - - return Dictionary.TryGetValue(baseLanternItem, out LanternItem item) ? item : (LanternItem)CreateItemWrapper(baseLanternItem); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/Light/LightItem.cs b/LabApi/Features/Wrappers/Items/Light/LightItem.cs index b23d768a..13279be2 100644 --- a/LabApi/Features/Wrappers/Items/Light/LightItem.cs +++ b/LabApi/Features/Wrappers/Items/Light/LightItem.cs @@ -13,12 +13,28 @@ public class LightItem : Item /// <summary> /// Contains all the cached light items, accessible through their <see cref="ToggleableLightItemBase"/>. /// </summary> - public new static Dictionary<ToggleableLightItemBase, LightItem> Dictionary { get; } = []; + public static new Dictionary<ToggleableLightItemBase, LightItem> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="LightItem"/>. /// </summary> - public new static IReadOnlyCollection<LightItem> List => Dictionary.Values; + public static new IReadOnlyCollection<LightItem> List => Dictionary.Values; + + /// <summary> + /// Gets the light item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="ToggleableLightItemBase"/> was not null. + /// </summary> + /// <param name="toggleableLight">The <see cref="Base"/> of the item.</param> + /// <returns>The requested item or null.</returns> + [return: NotNullIfNotNull(nameof(toggleableLight))] + public static LightItem? Get(ToggleableLightItemBase? toggleableLight) + { + if (toggleableLight == null) + { + return null; + } + + return Dictionary.TryGetValue(toggleableLight, out LightItem item) ? item : (LightItem)CreateItemWrapper(toggleableLight); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -30,16 +46,9 @@ internal LightItem(ToggleableLightItemBase toggleableLightItemBase) Base = toggleableLightItemBase; if (CanCache) + { Dictionary.Add(toggleableLightItemBase, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -61,16 +70,11 @@ public bool IsEmitting } /// <summary> - /// Gets the light item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="ToggleableLightItemBase"/> was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="toggleableLight">The <see cref="Base"/> of the item.</param> - /// <returns>The requested item or null.</returns> - [return: NotNullIfNotNull(nameof(toggleableLight))] - public static LightItem? Get(ToggleableLightItemBase? toggleableLight) + internal override void OnRemove() { - if (toggleableLight == null) - return null; - - return Dictionary.TryGetValue(toggleableLight, out LightItem item) ? item : (LightItem)CreateItemWrapper(toggleableLight); + base.OnRemove(); + Dictionary.Remove(Base); } } From 613bfcf33c44dd169b5135036aba52656f60dfc9 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:46:27 +0930 Subject: [PATCH 126/215] consumable --- .../Items/Usable/Consumable/AdrenalineItem.cs | 44 ++++++++++--------- .../Items/Usable/Consumable/AntiScp207Item.cs | 44 ++++++++++--------- .../Items/Usable/Consumable/ConsumableItem.cs | 44 ++++++++++--------- .../Items/Usable/Consumable/MedkitItem.cs | 44 ++++++++++--------- .../Usable/Consumable/PainkillersItem.cs | 44 ++++++++++--------- .../Items/Usable/Consumable/Scp1853Item.cs | 44 ++++++++++--------- .../Items/Usable/Consumable/Scp207Item.cs | 44 ++++++++++--------- .../Items/Usable/Consumable/Scp500Item.cs | 44 ++++++++++--------- 8 files changed, 192 insertions(+), 160 deletions(-) diff --git a/LabApi/Features/Wrappers/Items/Usable/Consumable/AdrenalineItem.cs b/LabApi/Features/Wrappers/Items/Usable/Consumable/AdrenalineItem.cs index 93b296fb..1df85413 100644 --- a/LabApi/Features/Wrappers/Items/Usable/Consumable/AdrenalineItem.cs +++ b/LabApi/Features/Wrappers/Items/Usable/Consumable/AdrenalineItem.cs @@ -12,12 +12,28 @@ public class AdrenalineItem : ConsumableItem /// <summary> /// Contains all the cached adrenaline items, accessible through their <see cref="Adrenaline"/>. /// </summary> - public new static Dictionary<Adrenaline, AdrenalineItem> Dictionary { get; } = []; + public static new Dictionary<Adrenaline, AdrenalineItem> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="AdrenalineItem"/>. /// </summary> - public new static IReadOnlyCollection<AdrenalineItem> List => Dictionary.Values; + public static new IReadOnlyCollection<AdrenalineItem> List => Dictionary.Values; + + /// <summary> + /// Gets the adrenaline item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="Adrenaline"/> was not null. + /// </summary> + /// <param name="adrenaline">The <see cref="Base"/> of the item.</param> + /// <returns>The requested item or null.</returns> + [return: NotNullIfNotNull(nameof(adrenaline))] + public static AdrenalineItem? Get(Adrenaline? adrenaline) + { + if (adrenaline == null) + { + return null; + } + + return Dictionary.TryGetValue(adrenaline, out AdrenalineItem item) ? item : (AdrenalineItem)CreateItemWrapper(adrenaline); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal AdrenalineItem(Adrenaline adrenaline) Base = adrenaline; if (CanCache) + { Dictionary.Add(adrenaline, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -47,16 +56,11 @@ internal override void OnRemove() public new Adrenaline Base { get; } /// <summary> - /// Gets the adrenaline item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="Adrenaline"/> was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="adrenaline">The <see cref="Base"/> of the item.</param> - /// <returns>The requested item or null.</returns> - [return: NotNullIfNotNull(nameof(adrenaline))] - public static AdrenalineItem? Get(Adrenaline? adrenaline) + internal override void OnRemove() { - if (adrenaline == null) - return null; - - return Dictionary.TryGetValue(adrenaline, out AdrenalineItem item) ? item : (AdrenalineItem)CreateItemWrapper(adrenaline); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/Usable/Consumable/AntiScp207Item.cs b/LabApi/Features/Wrappers/Items/Usable/Consumable/AntiScp207Item.cs index 435b4500..87b3ff40 100644 --- a/LabApi/Features/Wrappers/Items/Usable/Consumable/AntiScp207Item.cs +++ b/LabApi/Features/Wrappers/Items/Usable/Consumable/AntiScp207Item.cs @@ -12,12 +12,28 @@ public class AntiScp207Item : ConsumableItem /// <summary> /// Contains all the cached anti SCP-207 items, accessible through their <see cref="AntiScp207"/>. /// </summary> - public new static Dictionary<AntiScp207, AntiScp207Item> Dictionary { get; } = []; + public static new Dictionary<AntiScp207, AntiScp207Item> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="AntiScp207Item"/>. /// </summary> - public new static IReadOnlyCollection<AntiScp207Item> List => Dictionary.Values; + public static new IReadOnlyCollection<AntiScp207Item> List => Dictionary.Values; + + /// <summary> + /// Gets the anti SPC-207 item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="AntiScp207"/> was not null. + /// </summary> + /// <param name="antiScp207">The <see cref="Base"/> of the item.</param> + /// <returns>The requested item or null.</returns> + [return: NotNullIfNotNull(nameof(antiScp207))] + public static AntiScp207Item? Get(AntiScp207? antiScp207) + { + if (antiScp207 == null) + { + return null; + } + + return Dictionary.TryGetValue(antiScp207, out AntiScp207Item item) ? item : (AntiScp207Item)CreateItemWrapper(antiScp207); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal AntiScp207Item(AntiScp207 antiScp207) Base = antiScp207; if (CanCache) + { Dictionary.Add(antiScp207, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -47,16 +56,11 @@ internal override void OnRemove() public new AntiScp207 Base { get; } /// <summary> - /// Gets the anti SPC-207 item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="AntiScp207"/> was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="antiScp207">The <see cref="Base"/> of the item.</param> - /// <returns>The requested item or null.</returns> - [return: NotNullIfNotNull(nameof(antiScp207))] - public static AntiScp207Item? Get(AntiScp207? antiScp207) + internal override void OnRemove() { - if (antiScp207 == null) - return null; - - return Dictionary.TryGetValue(antiScp207, out AntiScp207Item item) ? item : (AntiScp207Item)CreateItemWrapper(antiScp207); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/Usable/Consumable/ConsumableItem.cs b/LabApi/Features/Wrappers/Items/Usable/Consumable/ConsumableItem.cs index b1e22781..6d7ac7a4 100644 --- a/LabApi/Features/Wrappers/Items/Usable/Consumable/ConsumableItem.cs +++ b/LabApi/Features/Wrappers/Items/Usable/Consumable/ConsumableItem.cs @@ -12,12 +12,28 @@ public class ConsumableItem : UsableItem /// <summary> /// Contains all the cached consumable items, accessible through their <see cref="Consumable"/>. /// </summary> - public new static Dictionary<Consumable, ConsumableItem> Dictionary { get; } = []; + public static new Dictionary<Consumable, ConsumableItem> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="ConsumableItem"/>. /// </summary> - public new static IReadOnlyCollection<ConsumableItem> List => Dictionary.Values; + public static new IReadOnlyCollection<ConsumableItem> List => Dictionary.Values; + + /// <summary> + /// Gets the consumable item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="Consumable"/> was not null. + /// </summary> + /// <param name="consumable">The <see cref="Base"/> of the item.</param> + /// <returns>The requested item or null.</returns> + [return: NotNullIfNotNull(nameof(consumable))] + public static ConsumableItem? Get(Consumable? consumable) + { + if (consumable == null) + { + return null; + } + + return Dictionary.TryGetValue(consumable, out ConsumableItem item) ? item : (ConsumableItem)CreateItemWrapper(consumable); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal ConsumableItem(Consumable consumable) Base = consumable; if (CanCache) + { Dictionary.Add(consumable, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -47,16 +56,11 @@ internal override void OnRemove() public new Consumable Base { get; } /// <summary> - /// Gets the consumable item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="Consumable"/> was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="consumable">The <see cref="Base"/> of the item.</param> - /// <returns>The requested item or null.</returns> - [return: NotNullIfNotNull(nameof(consumable))] - public static ConsumableItem? Get(Consumable? consumable) + internal override void OnRemove() { - if (consumable == null) - return null; - - return Dictionary.TryGetValue(consumable, out ConsumableItem item) ? item : (ConsumableItem)CreateItemWrapper(consumable); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/Usable/Consumable/MedkitItem.cs b/LabApi/Features/Wrappers/Items/Usable/Consumable/MedkitItem.cs index 01da404b..ae8743de 100644 --- a/LabApi/Features/Wrappers/Items/Usable/Consumable/MedkitItem.cs +++ b/LabApi/Features/Wrappers/Items/Usable/Consumable/MedkitItem.cs @@ -12,12 +12,28 @@ public class MedkitItem : ConsumableItem /// <summary> /// Contains all the cached medkit items, accessible through their <see cref="Medkit"/>. /// </summary> - public new static Dictionary<Medkit, MedkitItem> Dictionary { get; } = []; + public static new Dictionary<Medkit, MedkitItem> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="MedkitItem"/>. /// </summary> - public new static IReadOnlyCollection<MedkitItem> List => Dictionary.Values; + public static new IReadOnlyCollection<MedkitItem> List => Dictionary.Values; + + /// <summary> + /// Gets the medkit item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="Medkit"/> was not null. + /// </summary> + /// <param name="medkit">The <see cref="Base"/> of the item.</param> + /// <returns>The requested item or null.</returns> + [return: NotNullIfNotNull(nameof(medkit))] + public static MedkitItem? Get(Medkit? medkit) + { + if (medkit == null) + { + return null; + } + + return Dictionary.TryGetValue(medkit, out MedkitItem item) ? item : (MedkitItem)CreateItemWrapper(medkit); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal MedkitItem(Medkit medkit) Base = medkit; if (CanCache) + { Dictionary.Add(medkit, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -47,16 +56,11 @@ internal override void OnRemove() public new Medkit Base { get; } /// <summary> - /// Gets the medkit item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="Medkit"/> was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="medkit">The <see cref="Base"/> of the item.</param> - /// <returns>The requested item or null.</returns> - [return: NotNullIfNotNull(nameof(medkit))] - public static MedkitItem? Get(Medkit? medkit) + internal override void OnRemove() { - if (medkit == null) - return null; - - return Dictionary.TryGetValue(medkit, out MedkitItem item) ? item : (MedkitItem)CreateItemWrapper(medkit); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/Usable/Consumable/PainkillersItem.cs b/LabApi/Features/Wrappers/Items/Usable/Consumable/PainkillersItem.cs index c02db914..cb37dcd9 100644 --- a/LabApi/Features/Wrappers/Items/Usable/Consumable/PainkillersItem.cs +++ b/LabApi/Features/Wrappers/Items/Usable/Consumable/PainkillersItem.cs @@ -12,12 +12,28 @@ public class PainkillersItem : ConsumableItem /// <summary> /// Contains all the cached painkiller items, accessible through their <see cref="Painkillers"/>. /// </summary> - public new static Dictionary<Painkillers, PainkillersItem> Dictionary { get; } = []; + public static new Dictionary<Painkillers, PainkillersItem> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="PainkillersItem"/>. /// </summary> - public new static IReadOnlyCollection<PainkillersItem> List => Dictionary.Values; + public static new IReadOnlyCollection<PainkillersItem> List => Dictionary.Values; + + /// <summary> + /// Gets the painkillers item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="Painkillers"/> was not null. + /// </summary> + /// <param name="painkillers">The <see cref="Base"/> of the item.</param> + /// <returns>The requested item or null.</returns> + [return: NotNullIfNotNull(nameof(painkillers))] + public static PainkillersItem? Get(Painkillers? painkillers) + { + if (painkillers == null) + { + return null; + } + + return Dictionary.TryGetValue(painkillers, out PainkillersItem item) ? item : (PainkillersItem)CreateItemWrapper(painkillers); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal PainkillersItem(Painkillers painkillers) Base = painkillers; if (CanCache) + { Dictionary.Add(painkillers, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -47,16 +56,11 @@ internal override void OnRemove() public new Painkillers Base { get; } /// <summary> - /// Gets the painkillers item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="Painkillers"/> was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="painkillers">The <see cref="Base"/> of the item.</param> - /// <returns>The requested item or null.</returns> - [return: NotNullIfNotNull(nameof(painkillers))] - public static PainkillersItem? Get(Painkillers? painkillers) + internal override void OnRemove() { - if (painkillers == null) - return null; - - return Dictionary.TryGetValue(painkillers, out PainkillersItem item) ? item : (PainkillersItem)CreateItemWrapper(painkillers); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/Usable/Consumable/Scp1853Item.cs b/LabApi/Features/Wrappers/Items/Usable/Consumable/Scp1853Item.cs index 05de4a56..bc270187 100644 --- a/LabApi/Features/Wrappers/Items/Usable/Consumable/Scp1853Item.cs +++ b/LabApi/Features/Wrappers/Items/Usable/Consumable/Scp1853Item.cs @@ -12,12 +12,28 @@ public class Scp1853Item : ConsumableItem /// <summary> /// Contains all the cached SCP-1853 items, accessible through their <see cref="BaseScp1853Item"/>. /// </summary> - public new static Dictionary<BaseScp1853Item, Scp1853Item> Dictionary { get; } = []; + public static new Dictionary<BaseScp1853Item, Scp1853Item> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="Scp1853Item"/>. /// </summary> - public new static IReadOnlyCollection<Scp1853Item> List => Dictionary.Values; + public static new IReadOnlyCollection<Scp1853Item> List => Dictionary.Values; + + /// <summary> + /// Gets the SCP-1853 item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseScp1853Item"/> was not null. + /// </summary> + /// <param name="baseScp1853Item">The <see cref="Base"/> of the item.</param> + /// <returns>The requested item or null.</returns> + [return: NotNullIfNotNull(nameof(baseScp1853Item))] + public static Scp1853Item? Get(BaseScp1853Item? baseScp1853Item) + { + if (baseScp1853Item == null) + { + return null; + } + + return Dictionary.TryGetValue(baseScp1853Item, out Scp1853Item item) ? item : (Scp1853Item)CreateItemWrapper(baseScp1853Item); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal Scp1853Item(BaseScp1853Item baseScp1853Item) Base = baseScp1853Item; if (CanCache) + { Dictionary.Add(baseScp1853Item, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -47,16 +56,11 @@ internal override void OnRemove() public new BaseScp1853Item Base { get; } /// <summary> - /// Gets the SCP-1853 item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseScp1853Item"/> was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="baseScp1853Item">The <see cref="Base"/> of the item.</param> - /// <returns>The requested item or null.</returns> - [return: NotNullIfNotNull(nameof(baseScp1853Item))] - public static Scp1853Item? Get(BaseScp1853Item? baseScp1853Item) + internal override void OnRemove() { - if (baseScp1853Item == null) - return null; - - return Dictionary.TryGetValue(baseScp1853Item, out Scp1853Item item) ? item : (Scp1853Item)CreateItemWrapper(baseScp1853Item); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/Usable/Consumable/Scp207Item.cs b/LabApi/Features/Wrappers/Items/Usable/Consumable/Scp207Item.cs index ed5fa481..779cfe2d 100644 --- a/LabApi/Features/Wrappers/Items/Usable/Consumable/Scp207Item.cs +++ b/LabApi/Features/Wrappers/Items/Usable/Consumable/Scp207Item.cs @@ -12,12 +12,28 @@ public class Scp207Item : ConsumableItem /// <summary> /// Contains all the cached SCP-207 items, accessible through their <see cref="Scp207"/>. /// </summary> - public new static Dictionary<Scp207, Scp207Item> Dictionary { get; } = []; + public static new Dictionary<Scp207, Scp207Item> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="Scp207Item"/>. /// </summary> - public new static IReadOnlyCollection<Scp207Item> List => Dictionary.Values; + public static new IReadOnlyCollection<Scp207Item> List => Dictionary.Values; + + /// <summary> + /// Gets the SCP-207 item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="Scp207"/> was not null. + /// </summary> + /// <param name="scp207">The <see cref="Base"/> of the item.</param> + /// <returns>The requested item or null.</returns> + [return: NotNullIfNotNull(nameof(scp207))] + public static Scp207Item? Get(Scp207? scp207) + { + if (scp207 == null) + { + return null; + } + + return Dictionary.TryGetValue(scp207, out Scp207Item item) ? item : (Scp207Item)CreateItemWrapper(scp207); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal Scp207Item(Scp207 scp207) Base = scp207; if (CanCache) + { Dictionary.Add(scp207, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -47,16 +56,11 @@ internal override void OnRemove() public new Scp207 Base { get; } /// <summary> - /// Gets the SCP-207 item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="Scp207"/> was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="scp207">The <see cref="Base"/> of the item.</param> - /// <returns>The requested item or null.</returns> - [return: NotNullIfNotNull(nameof(scp207))] - public static Scp207Item? Get(Scp207? scp207) + internal override void OnRemove() { - if (scp207 == null) - return null; - - return Dictionary.TryGetValue(scp207, out Scp207Item item) ? item : (Scp207Item)CreateItemWrapper(scp207); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/Usable/Consumable/Scp500Item.cs b/LabApi/Features/Wrappers/Items/Usable/Consumable/Scp500Item.cs index 764350c8..be772060 100644 --- a/LabApi/Features/Wrappers/Items/Usable/Consumable/Scp500Item.cs +++ b/LabApi/Features/Wrappers/Items/Usable/Consumable/Scp500Item.cs @@ -12,12 +12,28 @@ public class Scp500Item : ConsumableItem /// <summary> /// Contains all the cached SCP-500 items, accessible through their <see cref="Scp500"/>. /// </summary> - public new static Dictionary<Scp500, Scp500Item> Dictionary { get; } = []; + public static new Dictionary<Scp500, Scp500Item> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="Scp500Item"/>. /// </summary> - public new static IReadOnlyCollection<Scp500Item> List => Dictionary.Values; + public static new IReadOnlyCollection<Scp500Item> List => Dictionary.Values; + + /// <summary> + /// Gets the SCP-500 item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="Scp500"/> was not null. + /// </summary> + /// <param name="scp500">The <see cref="Base"/> of the item.</param> + /// <returns>The requested item or null.</returns> + [return: NotNullIfNotNull(nameof(scp500))] + public static Scp500Item? Get(Scp500? scp500) + { + if (scp500 == null) + { + return null; + } + + return Dictionary.TryGetValue(scp500, out Scp500Item item) ? item : (Scp500Item)CreateItemWrapper(scp500); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal Scp500Item(Scp500 scp500) Base = scp500; if (CanCache) + { Dictionary.Add(scp500, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -47,16 +56,11 @@ internal override void OnRemove() public new Scp500 Base { get; } /// <summary> - /// Gets the SCP-500 item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="Scp500"/> was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="scp500">The <see cref="Base"/> of the item.</param> - /// <returns>The requested item or null.</returns> - [return: NotNullIfNotNull(nameof(scp500))] - public static Scp500Item? Get(Scp500? scp500) + internal override void OnRemove() { - if (scp500 == null) - return null; - - return Dictionary.TryGetValue(scp500, out Scp500Item item) ? item : (Scp500Item)CreateItemWrapper(scp500); + base.OnRemove(); + Dictionary.Remove(Base); } } From 1d99f66e3e21a4808b8231124a9f3b0d2506ccfa Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:46:32 +0930 Subject: [PATCH 127/215] usable --- .../Wrappers/Items/Usable/Scp1344Item.cs | 61 ++++++++++-------- .../Wrappers/Items/Usable/Scp1576Item.cs | 48 +++++++------- .../Wrappers/Items/Usable/Scp244Item.cs | 44 +++++++------ .../Wrappers/Items/Usable/Scp268Item.cs | 44 +++++++------ .../Wrappers/Items/Usable/Scp330Item.cs | 64 ++++++++++++------- .../Wrappers/Items/Usable/UsableItem.cs | 51 +++++++++------ 6 files changed, 178 insertions(+), 134 deletions(-) diff --git a/LabApi/Features/Wrappers/Items/Usable/Scp1344Item.cs b/LabApi/Features/Wrappers/Items/Usable/Scp1344Item.cs index b9289d48..288283df 100644 --- a/LabApi/Features/Wrappers/Items/Usable/Scp1344Item.cs +++ b/LabApi/Features/Wrappers/Items/Usable/Scp1344Item.cs @@ -14,12 +14,43 @@ public class Scp1344Item : UsableItem /// <summary> /// Contains all the cached SCP-1344 items, accessible through their <see cref="BaseScp1344Item"/>. /// </summary> - public new static Dictionary<BaseScp1344Item, Scp1344Item> Dictionary { get; } = []; + public static new Dictionary<BaseScp1344Item, Scp1344Item> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="Scp1344Item"/>. /// </summary> - public new static IReadOnlyCollection<Scp1344Item> List => Dictionary.Values; + public static new IReadOnlyCollection<Scp1344Item> List => Dictionary.Values; + + /// <summary> + /// Gets the SCP-1576 item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseScp1344Item"/> was not null. + /// </summary> + /// <param name="baseItem">The <see cref="Base"/> of the item.</param> + /// <returns>The requested item or null.</returns> + [return: NotNullIfNotNull(nameof(baseItem))] + public static Scp1344Item? Get(BaseScp1344Item? baseItem) + { + if (baseItem == null) + { + return null; + } + + return Dictionary.TryGetValue(baseItem, out Scp1344Item item) ? item : (Scp1344Item)CreateItemWrapper(baseItem); + } + + /// <summary> + /// An internal constructor to prevent external instantiation. + /// </summary> + /// <param name="baseItem">The base <see cref="BaseScp1344Item"/> object.</param> + internal Scp1344Item(BaseScp1344Item baseItem) + : base(baseItem) + { + Base = baseItem; + + if (CanCache) + { + Dictionary.Add(baseItem, this); + } + } /// <summary> /// The base <see cref="BaseScp1344Item"/> object. @@ -58,32 +89,6 @@ public Scp1344Status Status /// </summary> public SeveredEyes SeveredEyesEffect => Base.SeveredEyesEffect; - /// <summary> - /// An internal constructor to prevent external instantiation. - /// </summary> - /// <param name="baseItem">The base <see cref="BaseScp1344Item"/> object.</param> - internal Scp1344Item(BaseScp1344Item baseItem) : base(baseItem) - { - Base = baseItem; - - if (CanCache) - Dictionary.Add(baseItem, this); - } - - /// <summary> - /// Gets the SCP-1576 item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseScp1344Item"/> was not null. - /// </summary> - /// <param name="baseItem">The <see cref="Base"/> of the item.</param> - /// <returns>The requested item or null.</returns> - [return: NotNullIfNotNull(nameof(baseItem))] - public static Scp1344Item? Get(BaseScp1344Item? baseItem) - { - if (baseItem == null) - return null; - - return Dictionary.TryGetValue(baseItem, out Scp1344Item item) ? item : (Scp1344Item)CreateItemWrapper(baseItem); - } - /// <summary> /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> diff --git a/LabApi/Features/Wrappers/Items/Usable/Scp1576Item.cs b/LabApi/Features/Wrappers/Items/Usable/Scp1576Item.cs index 4e3fedc0..e93114a4 100644 --- a/LabApi/Features/Wrappers/Items/Usable/Scp1576Item.cs +++ b/LabApi/Features/Wrappers/Items/Usable/Scp1576Item.cs @@ -1,7 +1,7 @@ -using System.Collections.Generic; +using CustomPlayerEffects; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; -using CustomPlayerEffects; using BaseScp1576Item = InventorySystem.Items.Usables.Scp1576.Scp1576Item; namespace LabApi.Features.Wrappers; @@ -14,12 +14,12 @@ public class Scp1576Item : UsableItem /// <summary> /// Contains all the cached SCP-1576 items, accessible through their <see cref="BaseScp1576Item"/>. /// </summary> - public new static Dictionary<BaseScp1576Item, Scp1576Item> Dictionary { get; } = []; + public static new Dictionary<BaseScp1576Item, Scp1576Item> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="Scp1576Item"/>. /// </summary> - public new static IReadOnlyCollection<Scp1576Item> List => Dictionary.Values; + public static new IReadOnlyCollection<Scp1576Item> List => Dictionary.Values; /// <summary> /// The set of players who are able to transmit their voice to spectators using Scp1576. @@ -32,6 +32,22 @@ public class Scp1576Item : UsableItem /// </summary> public static IEnumerable<Player> ReceiverList => BaseScp1576Item.ValidatedReceivers.Select(x => Player.Get(x)); + /// <summary> + /// Gets the SCP-1576 item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseScp1576Item"/> was not null. + /// </summary> + /// <param name="baseScp1576Item">The <see cref="Base"/> of the item.</param> + /// <returns>The requested item or null.</returns> + [return: NotNullIfNotNull(nameof(baseScp1576Item))] + public static Scp1576Item? Get(BaseScp1576Item? baseScp1576Item) + { + if (baseScp1576Item == null) + { + return null; + } + + return Dictionary.TryGetValue(baseScp1576Item, out Scp1576Item item) ? item : (Scp1576Item)CreateItemWrapper(baseScp1576Item); + } + /// <summary> /// An internal constructor to prevent external instantiation. /// </summary> @@ -42,16 +58,9 @@ internal Scp1576Item(BaseScp1576Item baseScp1576Item) Base = baseScp1576Item; if (CanCache) + { Dictionary.Add(baseScp1576Item, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -60,16 +69,11 @@ internal override void OnRemove() public new BaseScp1576Item Base { get; } /// <summary> - /// Gets the SCP-1576 item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseScp1576Item"/> was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="baseScp1576Item">The <see cref="Base"/> of the item.</param> - /// <returns>The requested item or null.</returns> - [return: NotNullIfNotNull(nameof(baseScp1576Item))] - public static Scp1576Item? Get(BaseScp1576Item? baseScp1576Item) + internal override void OnRemove() { - if (baseScp1576Item == null) - return null; - - return Dictionary.TryGetValue(baseScp1576Item, out Scp1576Item item) ? item : (Scp1576Item)CreateItemWrapper(baseScp1576Item); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/Usable/Scp244Item.cs b/LabApi/Features/Wrappers/Items/Usable/Scp244Item.cs index 104326ad..7aa791dd 100644 --- a/LabApi/Features/Wrappers/Items/Usable/Scp244Item.cs +++ b/LabApi/Features/Wrappers/Items/Usable/Scp244Item.cs @@ -12,12 +12,28 @@ public class Scp244Item : UsableItem /// <summary> /// Contains all the cached SCP-244 items, accessible through their <see cref="BaseScp244Item"/>. /// </summary> - public new static Dictionary<BaseScp244Item, Scp244Item> Dictionary { get; } = []; + public static new Dictionary<BaseScp244Item, Scp244Item> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="Scp244Item"/>. /// </summary> - public new static IReadOnlyCollection<Scp244Item> List => Dictionary.Values; + public static new IReadOnlyCollection<Scp244Item> List => Dictionary.Values; + + /// <summary> + /// Gets the SCP-244 item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseScp244Item"/> was not null. + /// </summary> + /// <param name="baseScp244Item">The <see cref="Base"/> of the item.</param> + /// <returns>The requested item or null.</returns> + [return: NotNullIfNotNull(nameof(baseScp244Item))] + public static Scp244Item? Get(BaseScp244Item? baseScp244Item) + { + if (baseScp244Item == null) + { + return null; + } + + return Dictionary.TryGetValue(baseScp244Item, out Scp244Item item) ? item : (Scp244Item)CreateItemWrapper(baseScp244Item); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal Scp244Item(BaseScp244Item baseScp244Item) Base = baseScp244Item; if (CanCache) + { Dictionary.Add(baseScp244Item, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -47,16 +56,11 @@ internal override void OnRemove() public new BaseScp244Item Base { get; } /// <summary> - /// Gets the SCP-244 item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseScp244Item"/> was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="baseScp244Item">The <see cref="Base"/> of the item.</param> - /// <returns>The requested item or null.</returns> - [return: NotNullIfNotNull(nameof(baseScp244Item))] - public static Scp244Item? Get(BaseScp244Item? baseScp244Item) + internal override void OnRemove() { - if (baseScp244Item == null) - return null; - - return Dictionary.TryGetValue(baseScp244Item, out Scp244Item item) ? item : (Scp244Item)CreateItemWrapper(baseScp244Item); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/Usable/Scp268Item.cs b/LabApi/Features/Wrappers/Items/Usable/Scp268Item.cs index c75ed92b..283d78df 100644 --- a/LabApi/Features/Wrappers/Items/Usable/Scp268Item.cs +++ b/LabApi/Features/Wrappers/Items/Usable/Scp268Item.cs @@ -12,12 +12,28 @@ public class Scp268Item : UsableItem /// <summary> /// Contains all the cached SCP-268 items, accessible through their <see cref="Scp268"/>. /// </summary> - public new static Dictionary<Scp268, Scp268Item> Dictionary { get; } = []; + public static new Dictionary<Scp268, Scp268Item> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="Scp268Item"/>. /// </summary> - public new static IReadOnlyCollection<Scp268Item> List => Dictionary.Values; + public static new IReadOnlyCollection<Scp268Item> List => Dictionary.Values; + + /// <summary> + /// Gets the SCP-268 item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="Scp268"/> was not null. + /// </summary> + /// <param name="scp268">The <see cref="Base"/> of the item.</param> + /// <returns>The requested item or null.</returns> + [return: NotNullIfNotNull(nameof(scp268))] + public static Scp268Item? Get(Scp268? scp268) + { + if (scp268 == null) + { + return null; + } + + return Dictionary.TryGetValue(scp268, out Scp268Item item) ? item : (Scp268Item)CreateItemWrapper(scp268); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal Scp268Item(Scp268 scp268) Base = scp268; if (CanCache) + { Dictionary.Add(scp268, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -59,16 +68,11 @@ public bool IsWorn } /// <summary> - /// Gets the SCP-268 item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="Scp268"/> was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="scp268">The <see cref="Base"/> of the item.</param> - /// <returns>The requested item or null.</returns> - [return: NotNullIfNotNull(nameof(scp268))] - public static Scp268Item? Get(Scp268? scp268) + internal override void OnRemove() { - if (scp268 == null) - return null; - - return Dictionary.TryGetValue(scp268, out Scp268Item item) ? item : (Scp268Item)CreateItemWrapper(scp268); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/Usable/Scp330Item.cs b/LabApi/Features/Wrappers/Items/Usable/Scp330Item.cs index 072f7338..710f76a6 100644 --- a/LabApi/Features/Wrappers/Items/Usable/Scp330Item.cs +++ b/LabApi/Features/Wrappers/Items/Usable/Scp330Item.cs @@ -12,20 +12,36 @@ namespace LabApi.Features.Wrappers; /// </summary> public class Scp330Item : UsableItem { + /// <summary> + /// Maximum number of candies that can be contained in a bag. + /// </summary> + public const int MaxCandies = BaseScp330Item.MaxCandies; + /// <summary> /// Contains all the cached SCP-330 items, accessible through their <see cref="BaseScp330Item"/>. /// </summary> - public new static Dictionary<BaseScp330Item, Scp330Item> Dictionary { get; } = []; + public static new Dictionary<BaseScp330Item, Scp330Item> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="Scp330Item"/>. /// </summary> - public new static IReadOnlyCollection<Scp330Item> List => Dictionary.Values; + public static new IReadOnlyCollection<Scp330Item> List => Dictionary.Values; /// <summary> - /// Maximum number of candies that can be contained in a bag. + /// Gets the SCP-330 item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseScp330Item"/> was not null. /// </summary> - public const int MaxCandies = BaseScp330Item.MaxCandies; + /// <param name="baseScp330Item">The <see cref="Base"/> of the item.</param> + /// <returns>The requested item or null.</returns> + [return: NotNullIfNotNull(nameof(baseScp330Item))] + public static Scp330Item? Get(BaseScp330Item? baseScp330Item) + { + if (baseScp330Item == null) + { + return null; + } + + return Dictionary.TryGetValue(baseScp330Item, out Scp330Item item) ? item : (Scp330Item)CreateItemWrapper(baseScp330Item); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -37,16 +53,9 @@ internal Scp330Item(BaseScp330Item baseScp330Item) Base = baseScp330Item; if (CanCache) + { Dictionary.Add(baseScp330Item, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -76,10 +85,14 @@ public void AddCandies(IEnumerable<CandyKindID> candies, bool sync = true) { IEnumerator<CandyKindID> enumerator = candies.GetEnumerator(); while (enumerator.MoveNext() && Base.Candies.Count < MaxCandies) + { Base.Candies.Add(enumerator.Current); + } if (sync) + { SyncCandies(); + } } /// <summary> @@ -94,10 +107,14 @@ public void RemoveCandies(IEnumerable<CandyKindID> candies, bool sync = true) { IEnumerator<CandyKindID> enumerator = candies.GetEnumerator(); while (enumerator.MoveNext() && !Base.Candies.IsEmpty()) + { Base.Candies.Remove(enumerator.Current); + } if (sync) + { SyncCandies(); + } } /// <summary> @@ -126,15 +143,21 @@ public void SetCandies(IEnumerable<CandyKindID> candies, bool sync = true) public bool TryDrop(CandyKindID kind, [NotNullWhen(true)] out Pickup? dropped) { dropped = null; - if(!Candies.Contains(kind)) + if (!Candies.Contains(kind)) + { return false; + } if (CurrentOwner == null) + { return false; + } dropped = Pickup.Create(Type, CurrentOwner.Position); if (dropped == null) + { return false; + } Scp330Pickup scp330 = (Scp330Pickup)dropped; scp330.ExposedCandy = kind; @@ -144,16 +167,11 @@ public bool TryDrop(CandyKindID kind, [NotNullWhen(true)] out Pickup? dropped) } /// <summary> - /// Gets the SCP-330 item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseScp330Item"/> was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="baseScp330Item">The <see cref="Base"/> of the item.</param> - /// <returns>The requested item or null.</returns> - [return: NotNullIfNotNull(nameof(baseScp330Item))] - public static Scp330Item? Get(BaseScp330Item? baseScp330Item) + internal override void OnRemove() { - if (baseScp330Item == null) - return null; - - return Dictionary.TryGetValue(baseScp330Item, out Scp330Item item) ? item : (Scp330Item)CreateItemWrapper(baseScp330Item); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/Usable/UsableItem.cs b/LabApi/Features/Wrappers/Items/Usable/UsableItem.cs index 02da0172..717d0ab0 100644 --- a/LabApi/Features/Wrappers/Items/Usable/UsableItem.cs +++ b/LabApi/Features/Wrappers/Items/Usable/UsableItem.cs @@ -14,33 +14,42 @@ public class UsableItem : Item /// <summary> /// Contains all the cached usable items, accessible through their <see cref="BaseUsableItem"/>. /// </summary> - public new static Dictionary<BaseUsableItem, UsableItem> Dictionary { get; } = []; + public static new Dictionary<BaseUsableItem, UsableItem> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="UsableItem"/>. /// </summary> - public new static IReadOnlyCollection<UsableItem> List => Dictionary.Values; + public static new IReadOnlyCollection<UsableItem> List => Dictionary.Values; + + /// <summary> + /// Gets the usable item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseUsableItem"/> was not null. + /// </summary> + /// <param name="baseUsableItem">The <see cref="Base"/> of the item.</param> + /// <returns>The requested item or null.</returns> + [return: NotNullIfNotNull(nameof(baseUsableItem))] + public static UsableItem? Get(BaseUsableItem? baseUsableItem) + { + if (baseUsableItem == null) + { + return null; + } + + return Dictionary.TryGetValue(baseUsableItem, out UsableItem item) ? item : (UsableItem)CreateItemWrapper(baseUsableItem); + } /// <summary> /// An internal constructor to prevent external instantiation. /// </summary> /// <param name="baseUsableItem">The base <see cref="BaseUsableItem"/> object.</param> internal UsableItem(BaseUsableItem baseUsableItem) - :base(baseUsableItem) + : base(baseUsableItem) { Base = baseUsableItem; if (CanCache) + { Dictionary.Add(baseUsableItem, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -95,14 +104,19 @@ public float PersonalCooldownDuration get { if (CurrentOwner?.ReferenceHub == null || !UsableItemsController.GetHandler(CurrentOwner.ReferenceHub).PersonalCooldowns.TryGetValue(Type, out float time)) + { return 0; + } return time - Time.timeSinceLevelLoad; } + set { if (CurrentOwner?.ReferenceHub != null) + { UsableItemsController.GetHandler(CurrentOwner.ReferenceHub).PersonalCooldowns[Type] = Time.timeSinceLevelLoad + value; + } } } @@ -130,16 +144,11 @@ public float PersonalCooldownDuration public bool TryGetSoundEmissionRange(out float range) => Base.ServerTryGetSoundEmissionRange(out range); /// <summary> - /// Gets the usable item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseUsableItem"/> was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="baseUsableItem">The <see cref="Base"/> of the item.</param> - /// <returns>The requested item or null.</returns> - [return: NotNullIfNotNull(nameof(baseUsableItem))] - public static UsableItem? Get(BaseUsableItem? baseUsableItem) + internal override void OnRemove() { - if (baseUsableItem == null) - return null; - - return Dictionary.TryGetValue(baseUsableItem, out UsableItem item) ? item : (UsableItem)CreateItemWrapper(baseUsableItem); + base.OnRemove(); + Dictionary.Remove(Base); } } From 83355c2e9eac696185e279c59d3f37b9069004b6 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:46:37 +0930 Subject: [PATCH 128/215] items --- LabApi/Features/Wrappers/Items/AmmoItem.cs | 44 ++- .../Features/Wrappers/Items/BodyArmorItem.cs | 52 +-- LabApi/Features/Wrappers/Items/CoinItem.cs | 44 ++- LabApi/Features/Wrappers/Items/Item.cs | 354 +++++++++--------- .../Features/Wrappers/Items/JailbirdItem.cs | 44 ++- LabApi/Features/Wrappers/Items/KeycardItem.cs | 90 +++-- .../Features/Wrappers/Items/MicroHIDItem.cs | 44 ++- LabApi/Features/Wrappers/Items/RadioItem.cs | 44 ++- .../Features/Wrappers/Items/ThrowableItem.cs | 52 +-- 9 files changed, 409 insertions(+), 359 deletions(-) diff --git a/LabApi/Features/Wrappers/Items/AmmoItem.cs b/LabApi/Features/Wrappers/Items/AmmoItem.cs index 6c7fe2c4..bf1ed142 100644 --- a/LabApi/Features/Wrappers/Items/AmmoItem.cs +++ b/LabApi/Features/Wrappers/Items/AmmoItem.cs @@ -14,12 +14,28 @@ public class AmmoItem : Item /// <summary> /// Contains all the cached ammo items, accessible through their <see cref="BaseAmmoItem"/>. /// </summary> - public new static Dictionary<BaseAmmoItem, AmmoItem> Dictionary { get; } = []; + public static new Dictionary<BaseAmmoItem, AmmoItem> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="AmmoItem"/>. /// </summary> - public new static IReadOnlyCollection<AmmoItem> List => Dictionary.Values; + public static new IReadOnlyCollection<AmmoItem> List => Dictionary.Values; + + /// <summary> + /// Gets the ammo item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseAmmoItem"/> was not null. + /// </summary> + /// <param name="baseAmmoItem">The <see cref="Base"/> of the item.</param> + /// <returns>The requested item or null.</returns> + [return: NotNullIfNotNull(nameof(baseAmmoItem))] + public static AmmoItem? Get(BaseAmmoItem? baseAmmoItem) + { + if (baseAmmoItem == null) + { + return null; + } + + return Dictionary.TryGetValue(baseAmmoItem, out AmmoItem item) ? item : (AmmoItem)CreateItemWrapper(baseAmmoItem); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -31,16 +47,9 @@ internal AmmoItem(BaseAmmoItem baseAmmoItem) Base = baseAmmoItem; if (CanCache) + { Dictionary.Add(baseAmmoItem, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -49,16 +58,11 @@ internal override void OnRemove() public new BaseAmmoItem Base { get; } /// <summary> - /// Gets the ammo item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseAmmoItem"/> was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="baseAmmoItem">The <see cref="Base"/> of the item.</param> - /// <returns>The requested item or null.</returns> - [return: NotNullIfNotNull(nameof(baseAmmoItem))] - public static AmmoItem? Get(BaseAmmoItem? baseAmmoItem) + internal override void OnRemove() { - if (baseAmmoItem == null) - return null; - - return Dictionary.TryGetValue(baseAmmoItem, out AmmoItem item) ? item : (AmmoItem)CreateItemWrapper(baseAmmoItem); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/BodyArmorItem.cs b/LabApi/Features/Wrappers/Items/BodyArmorItem.cs index 07d1bd63..8f106981 100644 --- a/LabApi/Features/Wrappers/Items/BodyArmorItem.cs +++ b/LabApi/Features/Wrappers/Items/BodyArmorItem.cs @@ -1,5 +1,5 @@ -using System; -using InventorySystem.Items.Armor; +using InventorySystem.Items.Armor; +using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; @@ -13,12 +13,28 @@ public class BodyArmorItem : Item /// <summary> /// Contains all the cached body armor items, accessible through their <see cref="BodyArmor"/>. /// </summary> - public new static Dictionary<BodyArmor, BodyArmorItem> Dictionary { get; } = []; + public static new Dictionary<BodyArmor, BodyArmorItem> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="BodyArmorItem"/>. /// </summary> - public new static IReadOnlyCollection<BodyArmorItem> List => Dictionary.Values; + public static new IReadOnlyCollection<BodyArmorItem> List => Dictionary.Values; + + /// <summary> + /// Gets the body armor item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BodyArmor"/> was not null. + /// </summary> + /// <param name="bodyArmor">The <see cref="Base"/> of the item.</param> + /// <returns>The requested item or null.</returns> + [return: NotNullIfNotNull(nameof(bodyArmor))] + public static BodyArmorItem? Get(BodyArmor? bodyArmor) + { + if (bodyArmor == null) + { + return null; + } + + return Dictionary.TryGetValue(bodyArmor, out BodyArmorItem item) ? item : (BodyArmorItem)CreateItemWrapper(bodyArmor); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -30,16 +46,9 @@ internal BodyArmorItem(BodyArmor bodyArmor) Base = bodyArmor; if (CanCache) + { Dictionary.Add(bodyArmor, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -63,7 +72,7 @@ public bool RemoveExcessOnDrop public bool IsMovementModifierActive => Base.MovementModifierActive; /// <summary> - /// Gets the movement speed multiplier after being processed by <see cref="CivilianDownsideMultiplier"/>. + /// Gets the movement speed multiplier after being processed by <see cref="BodyArmor.CivilianClassDownsidesMultiplier"/>. /// </summary> public float ActualMovementSpeedMultiplier => Base.MovementSpeedMultiplier; @@ -73,21 +82,16 @@ public bool RemoveExcessOnDrop public bool IsStaminaModifierActive => Base.StaminaModifierActive; /// <summary> - /// Gets the stamina usage multiplier after being processed by <see cref="CivilianDownsideMultiplier"/>. + /// Gets the stamina usage multiplier after being processed by <see cref="BodyArmor.CivilianClassDownsidesMultiplier"/>. /// </summary> public float ActualStaminaUsageMultiplier => Base.StaminaUsageMultiplier; /// <summary> - /// Gets the body armor item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BodyArmor"/> was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="bodyArmor">The <see cref="Base"/> of the item.</param> - /// <returns>The requested item or null.</returns> - [return: NotNullIfNotNull(nameof(bodyArmor))] - public static BodyArmorItem? Get(BodyArmor? bodyArmor) + internal override void OnRemove() { - if (bodyArmor == null) - return null; - - return Dictionary.TryGetValue(bodyArmor, out BodyArmorItem item) ? item : (BodyArmorItem)CreateItemWrapper(bodyArmor); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/CoinItem.cs b/LabApi/Features/Wrappers/Items/CoinItem.cs index e2fd85e1..75a99d07 100644 --- a/LabApi/Features/Wrappers/Items/CoinItem.cs +++ b/LabApi/Features/Wrappers/Items/CoinItem.cs @@ -17,12 +17,28 @@ public class CoinItem : Item /// <summary> /// Contains all the cached coin items, accessible through their <see cref="Coin"/>. /// </summary> - public new static Dictionary<Coin, CoinItem> Dictionary { get; } = []; + public static new Dictionary<Coin, CoinItem> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="CoinItem"/>. /// </summary> - public new static IReadOnlyCollection<CoinItem> List => Dictionary.Values; + public static new IReadOnlyCollection<CoinItem> List => Dictionary.Values; + + /// <summary> + /// Gets the coin item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="Coin"/> was not null. + /// </summary> + /// <param name="coin">The <see cref="Base"/> of the item.</param> + /// <returns>The requested item or null.</returns> + [return: NotNullIfNotNull(nameof(coin))] + public static CoinItem? Get(Coin? coin) + { + if (coin == null) + { + return null; + } + + return Dictionary.TryGetValue(coin, out CoinItem item) ? item : (CoinItem)CreateItemWrapper(coin); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -34,16 +50,9 @@ internal CoinItem(Coin coin) Base = coin; if (CanCache) + { Dictionary.Add(coin, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -64,16 +73,11 @@ internal override void OnRemove() public double? LastFlipTime => Coin.FlipTimes.TryGetValue(Serial, out double time) ? Math.Abs(time) : null; /// <summary> - /// Gets the coin item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="Coin"/> was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="coin">The <see cref="Base"/> of the item.</param> - /// <returns>The requested item or null.</returns> - [return: NotNullIfNotNull(nameof(coin))] - public static CoinItem? Get(Coin? coin) + internal override void OnRemove() { - if (coin == null) - return null; - - return Dictionary.TryGetValue(coin, out CoinItem item) ? item : (CoinItem)CreateItemWrapper(coin); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/Item.cs b/LabApi/Features/Wrappers/Items/Item.cs index 088c79f6..4cefe4b0 100644 --- a/LabApi/Features/Wrappers/Items/Item.cs +++ b/LabApi/Features/Wrappers/Items/Item.cs @@ -18,10 +18,113 @@ namespace LabApi.Features.Wrappers; /// <summary> /// The wrapper representing <see cref="ItemBase">object</see>. /// -/// <para>Not to be confused with <see cref="Pickup">item pickup.</see></para> +/// <para>Not to be confused with <see cref="Pickup">item pickup</see>.</para> /// </summary> public class Item { + /// <summary> + /// Contains all the handlers for constructing wrappers for the associated base game types. + /// </summary> + private static readonly Dictionary<Type, Func<ItemBase, Item>> TypeWrappers = []; + + /// <summary> + /// Contains all the cached items, accessible through their <see cref="Base"/>. + /// </summary> + public static Dictionary<ItemBase, Item> Dictionary { get; } = []; + + /// <summary> + /// A reference to all instances of <see cref="Item"/>. + /// </summary> + public static IReadOnlyCollection<Item> List => Dictionary.Values; + + /// <summary> + /// Contains all cached items with their <see cref="Item.Serial"/> as a key. + /// </summary> + private static Dictionary<ushort, Item> SerialsCache { get; } = []; + + /// <summary> + /// Gets the item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="ItemBase"/> was not null. + /// </summary> + /// <param name="itemBase">The <see cref="Base"/> of the item.</param> + /// <returns>The requested item or null.</returns> + [return: NotNullIfNotNull(nameof(itemBase))] + public static Item? Get(ItemBase? itemBase) + { + if (itemBase == null) + { + return null; + } + + return Dictionary.TryGetValue(itemBase, out Item item) ? item : CreateItemWrapper(itemBase); + } + + /// <summary> + /// Tries to get the item wrapper from the <see cref="Dictionary"/>. + /// </summary> + /// <param name="itemBase">The <see cref="Base"/> of the item.</param> + /// <param name="item">The requested item.</param> + /// <returns>True if the item exists, otherwise false.</returns> + public static bool TryGet(ItemBase? itemBase, [NotNullWhen(true)] out Item? item) + { + item = Get(itemBase); + return item != null; + } + + /// <summary> + /// Gets the item wrapper or null from <see cref="SerialsCache"/>. + /// </summary> + /// <param name="serial">Serial of the item.</param> + /// <returns>The requested item.</returns> + public static Item? Get(ushort serial) => TryGet(serial, out Item? item) ? item : null; + + /// <summary> + /// Gets the item wrapper or null from the <see cref="Dictionary"/> based on provided serial number. + /// </summary> + /// <param name="serial">The serial number of the item.</param> + /// <param name="item">The requested item.</param> + /// <returns>Whether the was successfully retrieved, otherwise false.</returns> + public static bool TryGet(ushort serial, [NotNullWhen(true)] out Item? item) + { + item = null; + if (SerialsCache.TryGetValue(serial, out item)) + { + return true; + } + + item = List.FirstOrDefault(x => x.Serial == serial); + if (item == null) + { + return false; + } + + SerialsCache[serial] = item; + return true; + } + + /// <summary> + /// Gets a pooled list of items having the same <see cref="ItemType"/>. + /// </summary> + /// <param name="type">Target type.</param> + /// <returns>A List of items.</returns> + public static List<Item> GetAll(ItemType type) + { + List<Item> list = ListPool<Item>.Shared.Rent(); + list.AddRange(List.Where(n => n.Type == type)); + return list; + } + + /// <summary> + /// Gets a pooled list of items having the same <see cref="ItemCategory"/>. + /// </summary> + /// <param name="category">Target category.</param> + /// <returns>A List of items.</returns> + public static List<Item> GetAll(ItemCategory category) + { + List<Item> list = ListPool<Item>.Shared.Rent(); + list.AddRange(List.Where(n => n.Category == category)); + return list; + } + /// <summary> /// Initializes the <see cref="Item"/> class by subscribing to <see cref="ItemBase"/> events and registers derived wrappers. /// </summary> @@ -71,24 +174,90 @@ internal static void Initialize() } /// <summary> - /// Contains all the handlers for constructing wrappers for the associated base game types. + /// Creates a new wrapper from the base item object. /// </summary> - private static readonly Dictionary<Type, Func<ItemBase, Item>> typeWrappers = []; + /// <param name="item">The base object.</param> + /// <returns>The newly created wrapper.</returns> + protected static Item CreateItemWrapper(ItemBase item) + { + Type targetType = item.GetType(); + if (!TypeWrappers.TryGetValue(targetType, out Func<ItemBase, Item> ctorFunc)) + { +#if DEBUG + Logger.Warn($"Unable to find LabApi wrapper for {nameof(Item)} {targetType.Name}, backup up to base constructor!"); +#endif + return new Item(item); + } + + return ctorFunc.Invoke(item); + } /// <summary> - /// Contains all the cached items, accessible through their <see cref="Base"/>. + /// A private method to handle the creation of new items in the server. /// </summary> - public static Dictionary<ItemBase, Item> Dictionary { get; } = []; + /// <param name="item">The created <see cref="ItemBase"/> instance.</param> + private static void AddItem(ItemBase item) + { + try + { + if (!Dictionary.ContainsKey(item)) + { + _ = CreateItemWrapper(item); + } + } + catch (Exception e) + { + Console.Logger.InternalError($"Failed to handle item creation with error: {e}"); + } + } /// <summary> - /// Contains all cached items with their <see cref="Item.Serial"/> as a key. + /// A private method to handle the removal of items from the server. /// </summary> - private static Dictionary<ushort, Item> SerialsCache { get; } = []; + /// <param name="itemBase">The to be destroyed <see cref="ItemBase"/> instance.</param> + private static void RemoveItem(ItemBase itemBase) + { + try + { + SerialsCache.Remove(itemBase.ItemSerial); + if (Dictionary.TryGetValue(itemBase, out Item item)) + { + Dictionary.Remove(itemBase); + item.OnRemove(); + } + } + catch (Exception e) + { + Console.Logger.InternalError($"Failed to handle item destruction with error: {e}"); + } + } /// <summary> - /// A reference to all instances of <see cref="Item"/>. + /// A private method to handle the addition of wrapper handlers. /// </summary> - public static IReadOnlyCollection<Item> List => Dictionary.Values; + /// <typeparam name="T">The derived base game type to handle.</typeparam> + /// <param name="constructor">A handler to construct the wrapper with the base game instance.</param> + private static void Register<T>(Func<T, Item> constructor) + where T : ItemBase + { + TypeWrappers.Add(typeof(T), x => constructor((T)x)); + } + + /// <summary> + /// A private constructor to prevent external instantiation. + /// </summary> + /// <param name="itemBase">The <see cref="Base"/> of the item.</param> + protected Item(ItemBase itemBase) + { + Base = itemBase; + IsPrefab = InventoryItemLoader.TryGetItem(itemBase.ItemTypeId, out ItemBase prefab) && prefab == itemBase; + + if (CanCache) + { + Dictionary.Add(itemBase, this); + SerialsCache[itemBase.ItemSerial] = this; + } + } /// <summary> /// The <see cref="Base"/> of the item. @@ -213,31 +382,9 @@ public ItemThrowSettings ThrowSettings protected bool CanCache => !IsDestroyed && !IsPrefab && Serial != 0 && Base.isActiveAndEnabled; /// <summary> - /// A private constructor to prevent external instantiation. - /// </summary> - /// <param name="itemBase">The <see cref="Base"/> of the item.</param> - protected Item(ItemBase itemBase) - { - Base = itemBase; - IsPrefab = InventoryItemLoader.TryGetItem(itemBase.ItemTypeId, out ItemBase prefab) && prefab == itemBase; - - if (CanCache) - { - Dictionary.Add(itemBase, this); - SerialsCache[itemBase.ItemSerial] = this; - } - } - - /// <summary> - /// An internal virtual method to signal to derived implementations to uncache when the base object is destroyed. - /// </summary> - internal virtual void OnRemove() - { - } - - /// <summary> - /// Drops this item from player's inventory + /// Drops this item from player's inventory. /// </summary> + /// <returns>The dropped item as a <see cref="Pickup"/>.</returns> public Pickup DropItem() => Pickup.Get(Base.ServerDropItem(true)); /// <summary> @@ -253,146 +400,9 @@ public override string ToString() } /// <summary> - /// Gets the item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="ItemBase"/> was not null. - /// </summary> - /// <param name="itemBase">The <see cref="Base"/> of the item.</param> - /// <returns>The requested item or null.</returns> - [return: NotNullIfNotNull(nameof(itemBase))] - public static Item? Get(ItemBase? itemBase) - { - if (itemBase == null) - return null; - - return Dictionary.TryGetValue(itemBase, out Item item) ? item : CreateItemWrapper(itemBase); - } - - /// <summary> - /// Tries to get the item wrapper from the <see cref="Dictionary"/>. - /// </summary> - /// <param name="itemBase">The <see cref="Base"/> of the item.</param> - /// <param name="item">The requested item.</param> - /// <returns>True if the item exists, otherwise false.</returns> - public static bool TryGet(ItemBase? itemBase, [NotNullWhen(true)] out Item? item) - { - item = Get(itemBase); - return item != null; - } - - /// <summary> - /// Gets the item wrapper or null from <see cref="SerialsCache"/>. - /// </summary> - /// <param name="serial">Serial of the item.</param> - /// <returns>The requested item.</returns> - public static Item? Get(ushort serial) => TryGet(serial, out Item? item) ? item : null; - - /// <summary> - /// Gets the item wrapper or null from the <see cref="Dictionary"/> based on provided serial number. - /// </summary> - /// <param name="serial">The serial number of the item.</param> - /// <param name="item">The requested item.</param> - /// <returns>Whether the was successfully retrieved, otherwise false.</returns> - public static bool TryGet(ushort serial, [NotNullWhen(true)] out Item? item) - { - item = null; - if (SerialsCache.TryGetValue(serial, out item)) - return true; - - item = List.FirstOrDefault(x => x.Serial == serial); - if (item == null) - return false; - - SerialsCache[serial] = item; - return true; - } - - /// <summary> - /// Gets a pooled list of items having the same <see cref="ItemType"/>. - /// </summary> - /// <param name="type">Target type.</param> - /// <returns>A List of items.</returns> - public static List<Item> GetAll(ItemType type) - { - List<Item> list = ListPool<Item>.Shared.Rent(); - list.AddRange(List.Where(n => n.Type == type)); - return list; - } - - /// <summary> - /// Gets a pooled list of items having the same <see cref="ItemCategory"/>. - /// </summary> - /// <param name="category">Target category.</param> - /// <returns>A List of items.</returns> - public static List<Item> GetAll(ItemCategory category) - { - List<Item> list = ListPool<Item>.Shared.Rent(); - list.AddRange(List.Where(n => n.Category == category)); - return list; - } - - /// <summary> - /// Creates a new wrapper from the base item object. - /// </summary> - /// <param name="item">The base object.</param> - /// <returns>The newly created wrapper.</returns> - protected static Item CreateItemWrapper(ItemBase item) - { - Type targetType = item.GetType(); - if (!typeWrappers.TryGetValue(targetType, out Func<ItemBase, Item> ctorFunc)) - { -#if DEBUG - Logger.Warn($"Unable to find LabApi wrapper for {nameof(Item)} {targetType.Name}, backup up to base constructor!"); -#endif - return new Item(item); - } - - return ctorFunc.Invoke(item); - } - - /// <summary> - /// A private method to handle the creation of new items in the server. - /// </summary> - /// <param name="item">The created <see cref="ItemBase"/> instance.</param> - private static void AddItem(ItemBase item) - { - try - { - if (!Dictionary.ContainsKey(item)) - _ = CreateItemWrapper(item); - } - catch (Exception e) - { - Console.Logger.InternalError($"Failed to handle item creation with error: {e}"); - } - } - - /// <summary> - /// A private method to handle the removal of items from the server. - /// </summary> - /// <param name="itemBase">The to be destroyed <see cref="ItemBase"/> instance.</param> - private static void RemoveItem(ItemBase itemBase) - { - try - { - SerialsCache.Remove(itemBase.ItemSerial); - if (Dictionary.TryGetValue(itemBase, out Item item)) - { - Dictionary.Remove(itemBase); - item.OnRemove(); - } - } - catch (Exception e) - { - Console.Logger.InternalError($"Failed to handle item destruction with error: {e}"); - } - } - - /// <summary> - /// A private method to handle the addition of wrapper handlers. + /// An internal virtual method to signal to derived implementations to uncache when the base object is destroyed. /// </summary> - /// <typeparam name="T">The derived base game type to handle.</typeparam> - /// <param name="constructor">A handler to construct the wrapper with the base game instance.</param> - private static void Register<T>(Func<T, Item> constructor) where T : ItemBase + internal virtual void OnRemove() { - typeWrappers.Add(typeof(T), x => constructor((T)x)); } } \ No newline at end of file diff --git a/LabApi/Features/Wrappers/Items/JailbirdItem.cs b/LabApi/Features/Wrappers/Items/JailbirdItem.cs index b7e5daf2..a021dd94 100644 --- a/LabApi/Features/Wrappers/Items/JailbirdItem.cs +++ b/LabApi/Features/Wrappers/Items/JailbirdItem.cs @@ -12,12 +12,28 @@ public class JailbirdItem : Item /// <summary> /// Contains all the cached jailbird items, accessible through their <see cref="BaseJailbirdItem"/>. /// </summary> - public new static Dictionary<BaseJailbirdItem, JailbirdItem> Dictionary { get; } = []; + public static new Dictionary<BaseJailbirdItem, JailbirdItem> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="JailbirdItem"/>. /// </summary> - public new static IReadOnlyCollection<JailbirdItem> List => Dictionary.Values; + public static new IReadOnlyCollection<JailbirdItem> List => Dictionary.Values; + + /// <summary> + /// Gets the jailbird item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseJailbirdItem"/> was not null. + /// </summary> + /// <param name="baseJailbirdItem">The <see cref="Base"/> of the item.</param> + /// <returns>The requested item or null.</returns> + [return: NotNullIfNotNull(nameof(baseJailbirdItem))] + public static JailbirdItem? Get(BaseJailbirdItem? baseJailbirdItem) + { + if (baseJailbirdItem == null) + { + return null; + } + + return Dictionary.TryGetValue(baseJailbirdItem, out JailbirdItem item) ? item : (JailbirdItem)CreateItemWrapper(baseJailbirdItem); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal JailbirdItem(BaseJailbirdItem baseJailbirdItem) Base = baseJailbirdItem; if (CanCache) + { Dictionary.Add(baseJailbirdItem, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -57,16 +66,11 @@ internal override void OnRemove() public bool IsCharging => Base.MovementOverrideActive; /// <summary> - /// Gets the jailbird item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseJailbirdItem"/> was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="baseJailbirdItem">The <see cref="Base"/> of the item.</param> - /// <returns>The requested item or null.</returns> - [return: NotNullIfNotNull(nameof(baseJailbirdItem))] - public static JailbirdItem? Get(BaseJailbirdItem? baseJailbirdItem) + internal override void OnRemove() { - if (baseJailbirdItem == null) - return null; - - return Dictionary.TryGetValue(baseJailbirdItem, out JailbirdItem item) ? item : (JailbirdItem)CreateItemWrapper(baseJailbirdItem); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/KeycardItem.cs b/LabApi/Features/Wrappers/Items/KeycardItem.cs index f6ba7f73..3c74fc4b 100644 --- a/LabApi/Features/Wrappers/Items/KeycardItem.cs +++ b/LabApi/Features/Wrappers/Items/KeycardItem.cs @@ -17,49 +17,12 @@ public class KeycardItem : Item /// <summary> /// Contains all the cached keycard items, accessible through their <see cref="BaseKeycardItem"/>. /// </summary> - public new static Dictionary<BaseKeycardItem, KeycardItem> Dictionary { get; } = []; + public static new Dictionary<BaseKeycardItem, KeycardItem> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="KeycardItem"/>. /// </summary> - public new static IReadOnlyCollection<KeycardItem> List => Dictionary.Values; - - /// <summary> - /// An internal constructor to prevent external instantiation. - /// </summary> - /// <param name="baseKeycardItem">The base <see cref="BaseKeycardItem"/> object.</param> - internal KeycardItem(BaseKeycardItem baseKeycardItem) - : base(baseKeycardItem) - { - Base = baseKeycardItem; - - if (CanCache) - Dictionary.Add(baseKeycardItem, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); - } - - /// <summary> - /// The base <see cref="BaseKeycardItem"/> object. - /// </summary> - public new BaseKeycardItem Base { get; } - - /// <summary> - /// Gets the <see cref="DoorPermissionFlags"/> of the keycard. - /// </summary> - public DoorPermissionFlags Permissions => Base.GetPermissions(null); - - /// <summary> - /// Gets the <see cref="KeycardLevels"/> of the keycard which represent the tiers shown on the keycard. - /// </summary> - public KeycardLevels Levels => new KeycardLevels(Permissions); + public static new IReadOnlyCollection<KeycardItem> List => Dictionary.Values; #region Custom Keycards @@ -136,19 +99,27 @@ internal override void OnRemove() public static KeycardItem? CreateCustomCard(ItemType itemType, Player targetPlayer, params object[] args) { if (targetPlayer == null) + { return null; + } if (!itemType.TryGetTemplate(out BaseKeycardItem template)) + { throw new ArgumentException($"Template for {nameof(itemType)} not found"); + } if (!template.Customizable) + { return null; + } int index = 0; foreach (DetailBase detailBase in template.Details) { if (detailBase is not ICustomizableDetail customizableDetail) + { continue; + } customizableDetail.SetArguments(new ArraySegment<object>(args, index, customizableDetail.CustomizablePropertiesAmount)); index += customizableDetail.CustomizablePropertiesAmount; @@ -168,8 +139,49 @@ internal override void OnRemove() public static KeycardItem? Get(BaseKeycardItem? baseKeycardItem) { if (baseKeycardItem == null) + { return null; + } return Dictionary.TryGetValue(baseKeycardItem, out KeycardItem item) ? item : (KeycardItem)CreateItemWrapper(baseKeycardItem); } + + /// <summary> + /// An internal constructor to prevent external instantiation. + /// </summary> + /// <param name="baseKeycardItem">The base <see cref="BaseKeycardItem"/> object.</param> + internal KeycardItem(BaseKeycardItem baseKeycardItem) + : base(baseKeycardItem) + { + Base = baseKeycardItem; + + if (CanCache) + { + Dictionary.Add(baseKeycardItem, this); + } + } + + /// <summary> + /// The base <see cref="BaseKeycardItem"/> object. + /// </summary> + public new BaseKeycardItem Base { get; } + + /// <summary> + /// Gets the <see cref="DoorPermissionFlags"/> of the keycard. + /// </summary> + public DoorPermissionFlags Permissions => Base.GetPermissions(null); + + /// <summary> + /// Gets the <see cref="KeycardLevels"/> of the keycard which represent the tiers shown on the keycard. + /// </summary> + public KeycardLevels Levels => new(Permissions); + + /// <summary> + /// An internal method to remove itself from the cache when the base object is destroyed. + /// </summary> + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); + } } diff --git a/LabApi/Features/Wrappers/Items/MicroHIDItem.cs b/LabApi/Features/Wrappers/Items/MicroHIDItem.cs index 862a5210..840fe279 100644 --- a/LabApi/Features/Wrappers/Items/MicroHIDItem.cs +++ b/LabApi/Features/Wrappers/Items/MicroHIDItem.cs @@ -13,12 +13,28 @@ public class MicroHIDItem : Item /// <summary> /// Contains all the cached micro hid items, accessible through their <see cref="BaseMicroHIDItem"/>. /// </summary> - public new static Dictionary<BaseMicroHIDItem, MicroHIDItem> Dictionary { get; } = []; + public static new Dictionary<BaseMicroHIDItem, MicroHIDItem> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="MicroHIDItem"/>. /// </summary> - public new static IReadOnlyCollection<MicroHIDItem> List => Dictionary.Values; + public static new IReadOnlyCollection<MicroHIDItem> List => Dictionary.Values; + + /// <summary> + /// Gets the micro hid item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseMicroHIDItem"/> was not null. + /// </summary> + /// <param name="baseMicroHIDItem">The <see cref="Base"/> of the item.</param> + /// <returns>The requested item or null.</returns> + [return: NotNullIfNotNull(nameof(baseMicroHIDItem))] + public static MicroHIDItem? Get(BaseMicroHIDItem? baseMicroHIDItem) + { + if (baseMicroHIDItem == null) + { + return null; + } + + return Dictionary.TryGetValue(baseMicroHIDItem, out MicroHIDItem item) ? item : (MicroHIDItem)CreateItemWrapper(baseMicroHIDItem); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -30,16 +46,9 @@ internal MicroHIDItem(BaseMicroHIDItem baseMicroHIDItem) Base = baseMicroHIDItem; if (CanCache) + { Dictionary.Add(baseMicroHIDItem, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -133,16 +142,11 @@ public MicroHidFiringMode FiringMode public bool TryGetSoundEmissionRange(out float range) => Base.ServerTryGetSoundEmissionRange(out range); /// <summary> - /// Gets the micro hid item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseMicroHIDItem"/> was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="baseMicroHIDItem">The <see cref="Base"/> of the item.</param> - /// <returns>The requested item or null.</returns> - [return: NotNullIfNotNull(nameof(baseMicroHIDItem))] - public static MicroHIDItem? Get(BaseMicroHIDItem? baseMicroHIDItem) + internal override void OnRemove() { - if (baseMicroHIDItem == null) - return null; - - return Dictionary.TryGetValue(baseMicroHIDItem, out MicroHIDItem item) ? item : (MicroHIDItem)CreateItemWrapper(baseMicroHIDItem); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/RadioItem.cs b/LabApi/Features/Wrappers/Items/RadioItem.cs index 26b852bb..607de207 100644 --- a/LabApi/Features/Wrappers/Items/RadioItem.cs +++ b/LabApi/Features/Wrappers/Items/RadioItem.cs @@ -14,12 +14,28 @@ public class RadioItem : Item /// <summary> /// Contains all the cached radio items, accessible through their <see cref="BaseRadioItem"/>. /// </summary> - public new static Dictionary<BaseRadioItem, RadioItem> Dictionary { get; } = []; + public static new Dictionary<BaseRadioItem, RadioItem> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="RadioItem"/>. /// </summary> - public new static IReadOnlyCollection<RadioItem> List => Dictionary.Values; + public static new IReadOnlyCollection<RadioItem> List => Dictionary.Values; + + /// <summary> + /// Gets the radio item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseRadioItem"/> was not null. + /// </summary> + /// <param name="baseRadioItem">The <see cref="Base"/> of the item.</param> + /// <returns>The requested item or null.</returns> + [return: NotNullIfNotNull(nameof(baseRadioItem))] + public static RadioItem? Get(BaseRadioItem? baseRadioItem) + { + if (baseRadioItem == null) + { + return null; + } + + return Dictionary.TryGetValue(baseRadioItem, out RadioItem item) ? item : (RadioItem)CreateItemWrapper(baseRadioItem); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -31,16 +47,9 @@ internal RadioItem(BaseRadioItem baseRadioItem) Base = baseRadioItem; if (CanCache) + { Dictionary.Add(baseRadioItem, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -73,16 +82,11 @@ public byte BatteryPercent public RadioMessages.RadioRangeLevel RangeLevel => Base.RangeLevel; /// <summary> - /// Gets the radio item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseRadioItem"/> was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="baseRadioItem">The <see cref="Base"/> of the item.</param> - /// <returns>The requested item or null.</returns> - [return: NotNullIfNotNull(nameof(baseRadioItem))] - public static RadioItem? Get(BaseRadioItem? baseRadioItem) + internal override void OnRemove() { - if (baseRadioItem == null) - return null; - - return Dictionary.TryGetValue(baseRadioItem, out RadioItem item) ? item : (RadioItem)CreateItemWrapper(baseRadioItem); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/ThrowableItem.cs b/LabApi/Features/Wrappers/Items/ThrowableItem.cs index 9d2a8f6f..c29a49fc 100644 --- a/LabApi/Features/Wrappers/Items/ThrowableItem.cs +++ b/LabApi/Features/Wrappers/Items/ThrowableItem.cs @@ -13,12 +13,28 @@ public class ThrowableItem : Item /// <summary> /// Contains all the cached throwable items, accessible through their <see cref="BaseThrowableItem"/>. /// </summary> - public new static Dictionary<BaseThrowableItem, ThrowableItem> Dictionary { get; } = []; + public static new Dictionary<BaseThrowableItem, ThrowableItem> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="ThrowableItem"/>. /// </summary> - public new static IReadOnlyCollection<ThrowableItem> List => Dictionary.Values; + public static new IReadOnlyCollection<ThrowableItem> List => Dictionary.Values; + + /// <summary> + /// Gets the throwable item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseThrowableItem"/> was not null. + /// </summary> + /// <param name="baseThrowableItem">The <see cref="Base"/> of the item.</param> + /// <returns>The requested item or null.</returns> + [return: NotNullIfNotNull(nameof(baseThrowableItem))] + public static ThrowableItem? Get(BaseThrowableItem? baseThrowableItem) + { + if (baseThrowableItem == null) + { + return null; + } + + return Dictionary.TryGetValue(baseThrowableItem, out ThrowableItem item) ? item : (ThrowableItem)CreateItemWrapper(baseThrowableItem); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -30,16 +46,9 @@ internal ThrowableItem(BaseThrowableItem baseThrowableItem) Base = baseThrowableItem; if (CanCache) + { Dictionary.Add(baseThrowableItem, this); - } - - /// <summary> - /// An internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -47,12 +56,12 @@ internal override void OnRemove() /// </summary> public new BaseThrowableItem Base { get; } - /// <summary> - /// The projectile prefab instance, changes to this will be reflect across all new spawned projectiles. - /// </summary> + ///// <summary> + ///// The projectile prefab instance, changes to this will be reflect across all new spawned projectiles. + ///// </summary> // TODO: use projectile wrapper. // FIX: prefab caching. - //Pickup ProjectilePrefab => Pickup.Get(Base.Projectile); + // Pickup ProjectilePrefab => Pickup.Get(Base.Projectile); /// <summary> /// Gets or set the velocity added in the forward direction on a weak throw. @@ -127,16 +136,11 @@ public Vector3 FullThrowRelativePosition } /// <summary> - /// Gets the throwable item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseThrowableItem"/> was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="baseThrowableItem">The <see cref="Base"/> of the item.</param> - /// <returns>The requested item or null.</returns> - [return: NotNullIfNotNull(nameof(baseThrowableItem))] - public static ThrowableItem? Get(BaseThrowableItem? baseThrowableItem) + internal override void OnRemove() { - if (baseThrowableItem == null) - return null; - - return Dictionary.TryGetValue(baseThrowableItem, out ThrowableItem item) ? item : (ThrowableItem)CreateItemWrapper(baseThrowableItem); + base.OnRemove(); + Dictionary.Remove(Base); } } From 4fef805340c8ada0744816b544fa4867862369a3 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:46:43 +0930 Subject: [PATCH 129/215] grenades --- .../Grenades/ExplosiveGrenadeProjectile.cs | 36 ++++++++------- .../Grenades/FlashbangProjectile.cs | 38 +++++++++------- .../Projectiles/Grenades/Scp018Projectile.cs | 45 ++++++++++--------- .../Projectiles/Grenades/Scp2176Projectile.cs | 39 ++++++++-------- .../Grenades/TimedGrenadeProjectile.cs | 42 ++++++++++------- 5 files changed, 111 insertions(+), 89 deletions(-) diff --git a/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/ExplosiveGrenadeProjectile.cs b/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/ExplosiveGrenadeProjectile.cs index 57462b09..543f3fe4 100644 --- a/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/ExplosiveGrenadeProjectile.cs +++ b/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/ExplosiveGrenadeProjectile.cs @@ -20,16 +20,35 @@ public class ExplosiveGrenadeProjectile : TimedGrenadeProjectile /// </summary> public static new IReadOnlyCollection<ExplosiveGrenadeProjectile> List => Dictionary.Values; + /// <summary> + /// Gets the explosion grenade from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="ExplosionGrenade"/> was not <see langword="null"/>. + /// </summary> + /// <param name="projectile">The <see cref="Base"/> of the projectile.</param> + /// <returns>The requested projectile or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(projectile))] + public static ExplosiveGrenadeProjectile? Get(ExplosionGrenade? projectile) + { + if (projectile == null) + { + return null; + } + + return Dictionary.TryGetValue(projectile, out ExplosiveGrenadeProjectile wrapper) ? wrapper : (ExplosiveGrenadeProjectile)CreateItemWrapper(projectile); + } + /// <summary> /// A protected constructor to prevent external instantiation. /// </summary> /// <param name="projectilePickup">The <see cref="ExplosionGrenade"/> of the pickup.</param> - internal ExplosiveGrenadeProjectile(ExplosionGrenade projectilePickup) : base(projectilePickup) + internal ExplosiveGrenadeProjectile(ExplosionGrenade projectilePickup) + : base(projectilePickup) { Base = projectilePickup; if (CanCache) + { Dictionary.Add(projectilePickup, this); + } } /// <summary> @@ -71,19 +90,4 @@ internal override void OnRemove() Dictionary.Remove(Base); } - - /// <summary> - /// Gets the explosion grenade from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="ExplosionGrenade"/> was not <see langword="null"/>. - /// </summary> - /// <param name="projectile">The <see cref="Base"/> of the projectile.</param> - /// <returns>The requested projectile or <see langword="null"/>.</returns> - [return: NotNullIfNotNull(nameof(projectile))] - public static ExplosiveGrenadeProjectile? Get(ExplosionGrenade? projectile) - { - if (projectile == null) - return null; - - return Dictionary.TryGetValue(projectile, out ExplosiveGrenadeProjectile wrapper) ? wrapper : (ExplosiveGrenadeProjectile)CreateItemWrapper(projectile); - } } - diff --git a/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/FlashbangProjectile.cs b/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/FlashbangProjectile.cs index fac43753..0ad15571 100644 --- a/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/FlashbangProjectile.cs +++ b/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/FlashbangProjectile.cs @@ -20,16 +20,35 @@ public class FlashbangProjectile : TimedGrenadeProjectile /// </summary> public static new IReadOnlyCollection<FlashbangProjectile> List => Dictionary.Values; + /// <summary> + /// Gets the flashbang from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="FlashbangGrenade"/> was not <see langword="null"/>. + /// </summary> + /// <param name="projectile">The <see cref="Base"/> of the projectile.</param> + /// <returns>The requested projectile or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(projectile))] + public static FlashbangProjectile? Get(FlashbangGrenade? projectile) + { + if (projectile == null) + { + return null; + } + + return Dictionary.TryGetValue(projectile, out FlashbangProjectile wrapper) ? wrapper : (FlashbangProjectile)CreateItemWrapper(projectile); + } + /// <summary> /// A protected constructor to prevent external instantiation. /// </summary> /// <param name="projectilePickup">The <see cref="FlashbangGrenade"/> of the pickup.</param> - internal FlashbangProjectile(FlashbangGrenade projectilePickup) : base(projectilePickup) + internal FlashbangProjectile(FlashbangGrenade projectilePickup) + : base(projectilePickup) { Base = projectilePickup; if (CanCache) + { Dictionary.Add(projectilePickup, this); + } } /// <summary> @@ -48,7 +67,7 @@ public LayerMask BlockingMask /// <summary> /// Gets or sets the base blind time to affect people with. - /// <para>Note that this value is affected by distance from the grenade aswell as whether the player is looking at it and if it is on surface.</para> + /// <para>Note that this value is affected by distance from the grenade as well as whether the player is looking at it and if it is on surface.</para> /// </summary> public float BaseBlindTime { @@ -63,19 +82,4 @@ internal override void OnRemove() Dictionary.Remove(Base); } - - /// <summary> - /// Gets the flashbang from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="FlashbangGrenade"/> was not <see langword="null"/>. - /// </summary> - /// <param name="projectile">The <see cref="Base"/> of the projectile.</param> - /// <returns>The requested projectile or <see langword="null"/>.</returns> - [return: NotNullIfNotNull(nameof(projectile))] - public static FlashbangProjectile? Get(FlashbangGrenade? projectile) - { - if (projectile == null) - return null; - - return Dictionary.TryGetValue(projectile, out FlashbangProjectile wrapper) ? wrapper : (FlashbangProjectile)CreateItemWrapper(projectile); - } } - diff --git a/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/Scp018Projectile.cs b/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/Scp018Projectile.cs index d699577e..226ca4a1 100644 --- a/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/Scp018Projectile.cs +++ b/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/Scp018Projectile.cs @@ -1,5 +1,4 @@ using InventorySystem.Items.Pickups; -using InventorySystem.Items.ThrowableProjectiles; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using UnityEngine; @@ -21,16 +20,35 @@ public class Scp018Projectile : TimedGrenadeProjectile /// </summary> public static new IReadOnlyCollection<Scp018Projectile> List => Dictionary.Values; + /// <summary> + /// Gets the Scp-018 from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="InventorySystem.Items.ThrowableProjectiles.Scp018Projectile"/> was not <see langword="null"/>. + /// </summary> + /// <param name="projectile">The <see cref="Base"/> of the projectile.</param> + /// <returns>The requested projectile or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(projectile))] + public static Scp018Projectile? Get(InventorySystem.Items.ThrowableProjectiles.Scp018Projectile? projectile) + { + if (projectile == null) + { + return null; + } + + return Dictionary.TryGetValue(projectile, out Scp018Projectile wrapper) ? wrapper : (Scp018Projectile)CreateItemWrapper(projectile); + } + /// <summary> /// A protected constructor to prevent external instantiation. /// </summary> /// <param name="projectilePickup">The <see cref="InventorySystem.Items.ThrowableProjectiles.Scp018Projectile"/> of the pickup.</param> - internal Scp018Projectile(InventorySystem.Items.ThrowableProjectiles.Scp018Projectile projectilePickup) : base(projectilePickup) + internal Scp018Projectile(InventorySystem.Items.ThrowableProjectiles.Scp018Projectile projectilePickup) + : base(projectilePickup) { Base = projectilePickup; if (CanCache) + { Dictionary.Add(projectilePickup, this); + } } /// <summary> @@ -49,12 +67,12 @@ internal Scp018Projectile(InventorySystem.Items.ThrowableProjectiles.Scp018Proje public float CurrentDamage => Base.CurrentDamage; /// <summary> - /// Gets or sets the + /// Gets or sets the velocity of SCP-018. /// </summary> public Vector3 Velocity { - get => PhysicsModule.Rb.velocity; - set => PhysicsModule.Rb.velocity = value; + get => PhysicsModule.Rb.linearVelocity; + set => PhysicsModule.Rb.linearVelocity = value; } /// <summary> @@ -63,7 +81,7 @@ public Vector3 Velocity /// Intensities:<br/> /// 4-150 Low<br/> /// 150-400 Medium<br/> - /// 400+ High + /// 400+ High. /// </para> /// </summary> /// <param name="velSqrt">Velocity to play the sound for.</param> @@ -76,19 +94,4 @@ internal override void OnRemove() Dictionary.Remove(Base); } - - /// <summary> - /// Gets the Scp-018 from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="InventorySystem.Items.ThrowableProjectiles.Scp018Projectile"/> was not <see langword="null"/>. - /// </summary> - /// <param name="projectile">The <see cref="Base"/> of the projectile.</param> - /// <returns>The requested projectile or <see langword="null"/>.</returns> - [return: NotNullIfNotNull(nameof(projectile))] - public static Scp018Projectile? Get(InventorySystem.Items.ThrowableProjectiles.Scp018Projectile? projectile) - { - if (projectile == null) - return null; - - return Dictionary.TryGetValue(projectile, out Scp018Projectile wrapper) ? wrapper : (Scp018Projectile)CreateItemWrapper(projectile); - } } - diff --git a/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/Scp2176Projectile.cs b/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/Scp2176Projectile.cs index bc32659a..71602304 100644 --- a/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/Scp2176Projectile.cs +++ b/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/Scp2176Projectile.cs @@ -1,5 +1,4 @@ -using InventorySystem.Items.ThrowableProjectiles; -using System.Collections.Generic; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; namespace LabApi.Features.Wrappers; @@ -19,16 +18,35 @@ public class Scp2176Projectile : TimedGrenadeProjectile /// </summary> public static new IReadOnlyCollection<Scp2176Projectile> List => Dictionary.Values; + /// <summary> + /// Gets the Scp-2176 from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="InventorySystem.Items.ThrowableProjectiles.Scp2176Projectile"/> was not <see langword="null"/>. + /// </summary> + /// <param name="projectile">The <see cref="Base"/> of the projectile.</param> + /// <returns>The requested projectile or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(projectile))] + public static Scp2176Projectile? Get(InventorySystem.Items.ThrowableProjectiles.Scp2176Projectile? projectile) + { + if (projectile == null) + { + return null; + } + + return Dictionary.TryGetValue(projectile, out Scp2176Projectile wrapper) ? wrapper : (Scp2176Projectile)CreateItemWrapper(projectile); + } + /// <summary> /// A protected constructor to prevent external instantiation. /// </summary> /// <param name="projectilePickup">The <see cref="InventorySystem.Items.ThrowableProjectiles.Scp2176Projectile"/> of the pickup.</param> - internal Scp2176Projectile(InventorySystem.Items.ThrowableProjectiles.Scp2176Projectile projectilePickup) : base(projectilePickup) + internal Scp2176Projectile(InventorySystem.Items.ThrowableProjectiles.Scp2176Projectile projectilePickup) + : base(projectilePickup) { Base = projectilePickup; if (CanCache) + { Dictionary.Add(projectilePickup, this); + } } /// <summary> @@ -60,19 +78,4 @@ internal override void OnRemove() Dictionary.Remove(Base); } - - /// <summary> - /// Gets the Scp-2176 from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="InventorySystem.Items.ThrowableProjectiles.Scp2176Projectile"/> was not <see langword="null"/>. - /// </summary> - /// <param name="projectile">The <see cref="Base"/> of the projectile.</param> - /// <returns>The requested projectile or <see langword="null"/>.</returns> - [return: NotNullIfNotNull(nameof(projectile))] - public static Scp2176Projectile? Get(InventorySystem.Items.ThrowableProjectiles.Scp2176Projectile? projectile) - { - if (projectile == null) - return null; - - return Dictionary.TryGetValue(projectile, out Scp2176Projectile wrapper) ? wrapper : (Scp2176Projectile)CreateItemWrapper(projectile); - } } - diff --git a/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/TimedGrenadeProjectile.cs b/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/TimedGrenadeProjectile.cs index 344d3d98..3594b358 100644 --- a/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/TimedGrenadeProjectile.cs +++ b/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/TimedGrenadeProjectile.cs @@ -27,6 +27,22 @@ public class TimedGrenadeProjectile : Projectile /// </summary> public static new IReadOnlyCollection<TimedGrenadeProjectile> List => Dictionary.Values; + /// <summary> + /// Gets the timed grenade from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="TimeGrenade"/> was not <see langword="null"/>. + /// </summary> + /// <param name="projectile">The <see cref="Base"/> of the projectile.</param> + /// <returns>The requested projectile or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(projectile))] + public static TimedGrenadeProjectile? Get(TimeGrenade? projectile) + { + if (projectile == null) + { + return null; + } + + return Dictionary.TryGetValue(projectile, out TimedGrenadeProjectile wrapper) ? wrapper : (TimedGrenadeProjectile)CreateItemWrapper(projectile); + } + /// <summary> /// Spawns a explosion particles and effect on specified location.<br/> /// Valid for <see cref="ItemType.GrenadeHE"/>, <see cref="ItemType.GrenadeFlash"/> and <see cref="ItemType.SCP2176"/>. Doesn't do anything for any other input. @@ -46,14 +62,18 @@ public class TimedGrenadeProjectile : Projectile public static TimedGrenadeProjectile? SpawnActive(Vector3 pos, ItemType type, Player? owner = null, double timeOverride = -1d) { if (!InventoryItemLoader.TryGetItem(type, out InventorySystem.Items.ThrowableProjectiles.ThrowableItem throwable)) + { return null; + } if (throwable.Projectile is not TimeGrenade grenade) + { return null; + } TimeGrenade newPickup = GameObject.Instantiate(grenade, pos, Quaternion.identity); - PickupSyncInfo psi = new PickupSyncInfo(throwable.ItemTypeId, throwable.Weight, locked: true); + PickupSyncInfo psi = new(throwable.ItemTypeId, throwable.Weight, locked: true); newPickup.Info = psi; newPickup.PreviousOwner = new Footprint(owner?.ReferenceHub); @@ -70,12 +90,15 @@ public class TimedGrenadeProjectile : Projectile /// A protected constructor to prevent external instantiation. /// </summary> /// <param name="projectilePickup">The <see cref="TimeGrenade"/> of the pickup.</param> - internal TimedGrenadeProjectile(TimeGrenade projectilePickup) : base(projectilePickup) + internal TimedGrenadeProjectile(TimeGrenade projectilePickup) + : base(projectilePickup) { Base = projectilePickup; if (CanCache) + { Dictionary.Add(projectilePickup, this); + } } /// <summary> @@ -104,19 +127,4 @@ internal override void OnRemove() Dictionary.Remove(Base); } - - /// <summary> - /// Gets the timed grenade from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="TimeGrenade"/> was not <see langword="null"/>. - /// </summary> - /// <param name="projectile">The <see cref="Base"/> of the projectile.</param> - /// <returns>The requested projectile or <see langword="null"/>.</returns> - [return: NotNullIfNotNull(nameof(projectile))] - public static TimedGrenadeProjectile? Get(TimeGrenade? projectile) - { - if (projectile == null) - return null; - - return Dictionary.TryGetValue(projectile, out TimedGrenadeProjectile wrapper) ? wrapper : (TimedGrenadeProjectile)CreateItemWrapper(projectile); - } } - From 549b664c033388b43d44b15af0f965d60b1c0c2d Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:46:52 +0930 Subject: [PATCH 130/215] projectiles --- .../Pickups/Projectiles/Projectile.cs | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/LabApi/Features/Wrappers/Pickups/Projectiles/Projectile.cs b/LabApi/Features/Wrappers/Pickups/Projectiles/Projectile.cs index 6e9d65dd..df02aad8 100644 --- a/LabApi/Features/Wrappers/Pickups/Projectiles/Projectile.cs +++ b/LabApi/Features/Wrappers/Pickups/Projectiles/Projectile.cs @@ -21,16 +21,35 @@ public class Projectile : Pickup /// </summary> public static new IReadOnlyCollection<Projectile> List => Dictionary.Values; + /// <summary> + /// Gets the projectile wrapper from the <see cref="Dictionary"/> or creates a new if it doesn't exist and the provided <see cref="ThrownProjectile"/> was not <see langword="null"/>. + /// </summary> + /// <param name="projectile">The <see cref="Base"/> if the projectile.</param> + /// <returns>The requested wrapper or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(projectile))] + public static Projectile? Get(ThrownProjectile? projectile) + { + if (projectile == null) + { + return null; + } + + return Dictionary.TryGetValue(projectile, out Projectile wrapper) ? wrapper : (Projectile)CreateItemWrapper(projectile); + } + /// <summary> /// A protected constructor to prevent external instantiation. /// </summary> /// <param name="projectilePickup">The <see cref="ThrownProjectile"/> of the pickup.</param> - protected Projectile(ThrownProjectile projectilePickup) : base(projectilePickup) + protected Projectile(ThrownProjectile projectilePickup) + : base(projectilePickup) { Base = projectilePickup; if (CanCache) + { Dictionary.Add(projectilePickup, this); + } } /// <summary> @@ -38,24 +57,11 @@ protected Projectile(ThrownProjectile projectilePickup) : base(projectilePickup) /// </summary> public new ThrownProjectile Base { get; } + /// <inheritdoc /> internal override void OnRemove() { base.OnRemove(); Dictionary.Remove(Base); } - - /// <summary> - /// Gets the projectile wrapper from the <see cref="Dictionary"/> or creates a new if it doesn't exist and the provided <see cref="ThrownProjectile"/> was not <see langword="null"/>. - /// </summary> - /// <param name="projectile">The <see cref="Base"/> if the projectile.</param> - /// <returns>The requested wrapper or <see langword="null"/>.</returns> - [return: NotNullIfNotNull(nameof(projectile))] - public static Projectile? Get(ThrownProjectile? projectile) - { - if (projectile == null) - return null; - - return Dictionary.TryGetValue(projectile, out Projectile wrapper) ? wrapper : (Projectile)CreateItemWrapper(projectile); - } } From 5eedc73d478d6dd6833dedaefdefa2e470b44d97 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:47:06 +0930 Subject: [PATCH 131/215] derived pickups --- .../Features/Wrappers/Pickups/AmmoPickup.cs | 44 ++++++++-------- .../Wrappers/Pickups/BodyArmorPickup.cs | 44 ++++++++-------- .../Wrappers/Pickups/FirearmPickup.cs | 44 ++++++++-------- .../Wrappers/Pickups/JailbirdPickup.cs | 44 ++++++++-------- .../Wrappers/Pickups/KeycardPickup.cs | 44 ++++++++-------- .../Wrappers/Pickups/MicroHIDPickup.cs | 44 ++++++++-------- .../Features/Wrappers/Pickups/RadioPickup.cs | 48 +++++++++-------- .../Wrappers/Pickups/Scp1576Pickup.cs | 51 +++++++++---------- .../Features/Wrappers/Pickups/Scp244Pickup.cs | 46 +++++++++-------- .../Features/Wrappers/Pickups/Scp330Pickup.cs | 47 +++++++++-------- .../Wrappers/Pickups/TimedGrenadePickup.cs | 44 ++++++++-------- 11 files changed, 271 insertions(+), 229 deletions(-) diff --git a/LabApi/Features/Wrappers/Pickups/AmmoPickup.cs b/LabApi/Features/Wrappers/Pickups/AmmoPickup.cs index 6be7fefd..681332cb 100644 --- a/LabApi/Features/Wrappers/Pickups/AmmoPickup.cs +++ b/LabApi/Features/Wrappers/Pickups/AmmoPickup.cs @@ -12,12 +12,28 @@ public class AmmoPickup : Pickup /// <summary> /// Contains all the cached ammo pickups, accessible through their <see cref="BaseAmmoPickup"/>. /// </summary> - public new static Dictionary<BaseAmmoPickup, AmmoPickup> Dictionary { get; } = []; + public static new Dictionary<BaseAmmoPickup, AmmoPickup> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="AmmoPickup"/>. /// </summary> - public new static IReadOnlyCollection<AmmoPickup> List => Dictionary.Values; + public static new IReadOnlyCollection<AmmoPickup> List => Dictionary.Values; + + /// <summary> + /// Gets the ammo pickup from the <see cref="Dictionary"/> or creates a new if it doesn't exist and the provided <see cref="BaseAmmoPickup"/> was not <see langword="null"/>. + /// </summary> + /// <param name="pickup">The <see cref="Base"/> if the pickup.</param> + /// <returns>The requested pickup or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(pickup))] + public static AmmoPickup? Get(BaseAmmoPickup? pickup) + { + if (pickup == null) + { + return null; + } + + return Dictionary.TryGetValue(pickup, out AmmoPickup wrapper) ? wrapper : (AmmoPickup)CreateItemWrapper(pickup); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal AmmoPickup(BaseAmmoPickup baseAmmoPickup) Base = baseAmmoPickup; if (CanCache) + { Dictionary.Add(baseAmmoPickup, this); - } - - /// <summary> - /// A internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -56,16 +65,11 @@ public ushort Ammo } /// <summary> - /// Gets the ammo pickup from the <see cref="Dictionary"/> or creates a new if it doesn't exist and the provided <see cref="BaseAmmoPickup"/> was not <see langword="null"/>. + /// A internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="pickup">The <see cref="Base"/> if the pickup.</param> - /// <returns>The requested pickup or <see langword="null"/>.</returns> - [return: NotNullIfNotNull(nameof(pickup))] - public static AmmoPickup? Get(BaseAmmoPickup? pickup) + internal override void OnRemove() { - if (pickup == null) - return null; - - return Dictionary.TryGetValue(pickup, out AmmoPickup wrapper) ? wrapper : (AmmoPickup)CreateItemWrapper(pickup); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Pickups/BodyArmorPickup.cs b/LabApi/Features/Wrappers/Pickups/BodyArmorPickup.cs index 643a268b..bc23c687 100644 --- a/LabApi/Features/Wrappers/Pickups/BodyArmorPickup.cs +++ b/LabApi/Features/Wrappers/Pickups/BodyArmorPickup.cs @@ -12,12 +12,28 @@ public class BodyArmorPickup : Pickup /// <summary> /// Contains all the cached body armor pickups, accessible through their <see cref="BaseBodyArmorPickup"/>. /// </summary> - public new static Dictionary<BaseBodyArmorPickup, BodyArmorPickup> Dictionary { get; } = []; + public static new Dictionary<BaseBodyArmorPickup, BodyArmorPickup> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="BodyArmorPickup"/>. /// </summary> - public new static IReadOnlyCollection<BodyArmorPickup> List => Dictionary.Values; + public static new IReadOnlyCollection<BodyArmorPickup> List => Dictionary.Values; + + /// <summary> + /// Gets the body armor pickup from the <see cref="Dictionary"/> or creates a new if it doesn't exist and the provided <see cref="BaseBodyArmorPickup"/> was not <see langword="null"/>. + /// </summary> + /// <param name="pickup">The <see cref="Base"/> if the pickup.</param> + /// <returns>The requested pickup or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(pickup))] + public static BodyArmorPickup? Get(BaseBodyArmorPickup? pickup) + { + if (pickup == null) + { + return null; + } + + return Dictionary.TryGetValue(pickup, out BodyArmorPickup wrapper) ? wrapper : (BodyArmorPickup)CreateItemWrapper(pickup); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal BodyArmorPickup(BaseBodyArmorPickup baseBodyArmorPickup) Base = baseBodyArmorPickup; if (CanCache) + { Dictionary.Add(baseBodyArmorPickup, this); - } - - /// <summary> - /// A internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -47,16 +56,11 @@ internal override void OnRemove() public new BaseBodyArmorPickup Base { get; } /// <summary> - /// Gets the body armor pickup from the <see cref="Dictionary"/> or creates a new if it doesn't exist and the provided <see cref="BaseBodyArmorPickup"/> was not <see langword="null"/>. + /// A internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="pickup">The <see cref="Base"/> if the pickup.</param> - /// <returns>The requested pickup or <see langword="null"/>.</returns> - [return: NotNullIfNotNull(nameof(pickup))] - public static BodyArmorPickup? Get(BaseBodyArmorPickup? pickup) + internal override void OnRemove() { - if (pickup == null) - return null; - - return Dictionary.TryGetValue(pickup, out BodyArmorPickup wrapper) ? wrapper : (BodyArmorPickup)CreateItemWrapper(pickup); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Pickups/FirearmPickup.cs b/LabApi/Features/Wrappers/Pickups/FirearmPickup.cs index 401abff3..d197c9ba 100644 --- a/LabApi/Features/Wrappers/Pickups/FirearmPickup.cs +++ b/LabApi/Features/Wrappers/Pickups/FirearmPickup.cs @@ -14,12 +14,28 @@ public class FirearmPickup : Pickup /// <summary> /// Contains all the cached firearm pickups, accessible through their <see cref="BaseFirearmPickup"/>. /// </summary> - public new static Dictionary<BaseFirearmPickup, FirearmPickup> Dictionary { get; } = []; + public static new Dictionary<BaseFirearmPickup, FirearmPickup> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="FirearmPickup"/>. /// </summary> - public new static IReadOnlyCollection<FirearmPickup> List => Dictionary.Values; + public static new IReadOnlyCollection<FirearmPickup> List => Dictionary.Values; + + /// <summary> + /// Gets the firearm pickup from the <see cref="Dictionary"/> or creates a new if it doesn't exist and the provided <see cref="BaseFirearmPickup"/> was not <see langword="null"/>. + /// </summary> + /// <param name="pickup">The <see cref="Base"/> if the pickup.</param> + /// <returns>The requested pickup or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(pickup))] + public static FirearmPickup? Get(BaseFirearmPickup? pickup) + { + if (pickup == null) + { + return null; + } + + return Dictionary.TryGetValue(pickup, out FirearmPickup wrapper) ? wrapper : (FirearmPickup)CreateItemWrapper(pickup); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -31,16 +47,9 @@ internal FirearmPickup(BaseFirearmPickup baseFirearmPickup) Base = baseFirearmPickup; if (CanCache) + { Dictionary.Add(baseFirearmPickup, this); - } - - /// <summary> - /// A internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -63,16 +72,11 @@ public uint AttachmentCode } /// <summary> - /// Gets the firearm pickup from the <see cref="Dictionary"/> or creates a new if it doesn't exist and the provided <see cref="BaseFirearmPickup"/> was not <see langword="null"/>. + /// A internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="pickup">The <see cref="Base"/> if the pickup.</param> - /// <returns>The requested pickup or <see langword="null"/>.</returns> - [return: NotNullIfNotNull(nameof(pickup))] - public static FirearmPickup? Get(BaseFirearmPickup? pickup) + internal override void OnRemove() { - if (pickup == null) - return null; - - return Dictionary.TryGetValue(pickup, out FirearmPickup wrapper) ? wrapper : (FirearmPickup)CreateItemWrapper(pickup); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Pickups/JailbirdPickup.cs b/LabApi/Features/Wrappers/Pickups/JailbirdPickup.cs index f0ea39cf..6561da44 100644 --- a/LabApi/Features/Wrappers/Pickups/JailbirdPickup.cs +++ b/LabApi/Features/Wrappers/Pickups/JailbirdPickup.cs @@ -13,12 +13,28 @@ public class JailbirdPickup : Pickup /// <summary> /// Contains all the cached ammo pickups, accessible through their <see cref="BaseJailbirdPickup"/>. /// </summary> - public new static Dictionary<BaseJailbirdPickup, JailbirdPickup> Dictionary { get; } = []; + public static new Dictionary<BaseJailbirdPickup, JailbirdPickup> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="JailbirdPickup"/>. /// </summary> - public new static IReadOnlyCollection<JailbirdPickup> List => Dictionary.Values; + public static new IReadOnlyCollection<JailbirdPickup> List => Dictionary.Values; + + /// <summary> + /// Gets the jailbird pickup from the <see cref="Dictionary"/> or creates a new if it doesn't exist and the provided <see cref="BaseJailbirdPickup"/> was not <see langword="null"/>. + /// </summary> + /// <param name="pickup">The <see cref="Base"/> if the pickup.</param> + /// <returns>The requested pickup or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(pickup))] + public static JailbirdPickup? Get(BaseJailbirdPickup? pickup) + { + if (pickup == null) + { + return null; + } + + return Dictionary.TryGetValue(pickup, out JailbirdPickup wrapper) ? wrapper : (JailbirdPickup)CreateItemWrapper(pickup); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -30,16 +46,9 @@ internal JailbirdPickup(BaseJailbirdPickup baseJailbirdPickup) Base = baseJailbirdPickup; if (CanCache) + { Dictionary.Add(baseJailbirdPickup, this); - } - - /// <summary> - /// A internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -75,16 +84,11 @@ public JailbirdWearState WearState } /// <summary> - /// Gets the jailbird pickup from the <see cref="Dictionary"/> or creates a new if it doesn't exist and the provided <see cref="BaseJailbirdPickup"/> was not <see langword="null"/>. + /// A internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="pickup">The <see cref="Base"/> if the pickup.</param> - /// <returns>The requested pickup or <see langword="null"/>.</returns> - [return: NotNullIfNotNull(nameof(pickup))] - public static JailbirdPickup? Get(BaseJailbirdPickup? pickup) + internal override void OnRemove() { - if (pickup == null) - return null; - - return Dictionary.TryGetValue(pickup, out JailbirdPickup wrapper) ? wrapper : (JailbirdPickup)CreateItemWrapper(pickup); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Pickups/KeycardPickup.cs b/LabApi/Features/Wrappers/Pickups/KeycardPickup.cs index f0741a9e..71a58ea6 100644 --- a/LabApi/Features/Wrappers/Pickups/KeycardPickup.cs +++ b/LabApi/Features/Wrappers/Pickups/KeycardPickup.cs @@ -12,12 +12,28 @@ public class KeycardPickup : Pickup /// <summary> /// Contains all the cached keycard pickups, accessible through their <see cref="BaseKeycardPickup"/>. /// </summary> - public new static Dictionary<BaseKeycardPickup, KeycardPickup> Dictionary { get; } = []; + public static new Dictionary<BaseKeycardPickup, KeycardPickup> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="KeycardPickup"/>. /// </summary> - public new static IReadOnlyCollection<KeycardPickup> List => Dictionary.Values; + public static new IReadOnlyCollection<KeycardPickup> List => Dictionary.Values; + + /// <summary> + /// Gets the keycard pickup from the <see cref="Dictionary"/> or creates a new if it doesn't exist and the provided <see cref="BaseKeycardPickup"/> was not <see langword="null"/>. + /// </summary> + /// <param name="pickup">The <see cref="Base"/> if the pickup.</param> + /// <returns>The requested pickup or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(pickup))] + public static KeycardPickup? Get(BaseKeycardPickup? pickup) + { + if (pickup == null) + { + return null; + } + + return Dictionary.TryGetValue(pickup, out KeycardPickup wrapper) ? wrapper : (KeycardPickup)CreateItemWrapper(pickup); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal KeycardPickup(BaseKeycardPickup baseKeycardPickup) Base = baseKeycardPickup; if (CanCache) + { Dictionary.Add(baseKeycardPickup, this); - } - - /// <summary> - /// A internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -47,16 +56,11 @@ internal override void OnRemove() public new BaseKeycardPickup Base { get; } /// <summary> - /// Gets the keycard pickup from the <see cref="Dictionary"/> or creates a new if it doesn't exist and the provided <see cref="BaseKeycardPickup"/> was not <see langword="null"/>. + /// A internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="pickup">The <see cref="Base"/> if the pickup.</param> - /// <returns>The requested pickup or <see langword="null"/>.</returns> - [return: NotNullIfNotNull(nameof(pickup))] - public static KeycardPickup? Get(BaseKeycardPickup? pickup) + internal override void OnRemove() { - if (pickup == null) - return null; - - return Dictionary.TryGetValue(pickup, out KeycardPickup wrapper) ? wrapper : (KeycardPickup)CreateItemWrapper(pickup); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Pickups/MicroHIDPickup.cs b/LabApi/Features/Wrappers/Pickups/MicroHIDPickup.cs index 6d30c11d..a62dcdd3 100644 --- a/LabApi/Features/Wrappers/Pickups/MicroHIDPickup.cs +++ b/LabApi/Features/Wrappers/Pickups/MicroHIDPickup.cs @@ -13,12 +13,28 @@ public class MicroHIDPickup : Pickup /// <summary> /// Contains all the cached micro hid pickups, accessible through their <see cref="BaseMicroHIDPickup"/>. /// </summary> - public new static Dictionary<BaseMicroHIDPickup, MicroHIDPickup> Dictionary { get; } = []; + public static new Dictionary<BaseMicroHIDPickup, MicroHIDPickup> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="MicroHIDPickup"/>. /// </summary> - public new static IReadOnlyCollection<MicroHIDPickup> List => Dictionary.Values; + public static new IReadOnlyCollection<MicroHIDPickup> List => Dictionary.Values; + + /// <summary> + /// Gets the micro hid pickup from the <see cref="Dictionary"/> or creates a new if it doesn't exist and the provided <see cref="BaseMicroHIDPickup"/> was not <see langword="null"/>. + /// </summary> + /// <param name="pickup">The <see cref="Base"/> if the pickup.</param> + /// <returns>The requested pickup or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(pickup))] + public static MicroHIDPickup? Get(BaseMicroHIDPickup? pickup) + { + if (pickup == null) + { + return null; + } + + return Dictionary.TryGetValue(pickup, out MicroHIDPickup wrapper) ? wrapper : (MicroHIDPickup)CreateItemWrapper(pickup); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -31,16 +47,9 @@ internal MicroHIDPickup(BaseMicroHIDPickup baseMicroHIDPickup) BaseCycleController = CycleSyncModule.GetCycleController(Serial); if (CanCache) + { Dictionary.Add(baseMicroHIDPickup, this); - } - - /// <summary> - /// A internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -83,16 +92,11 @@ public MicroHidFiringMode FiringMode public float PhaseElapsed => BaseCycleController.CurrentPhaseElapsed; /// <summary> - /// Gets the micro hid pickup from the <see cref="Dictionary"/> or creates a new if it doesn't exist and the provided <see cref="BaseMicroHIDPickup"/> was not <see langword="null"/>. + /// A internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="pickup">The <see cref="Base"/> if the pickup.</param> - /// <returns>The requested pickup or <see langword="null"/>.</returns> - [return: NotNullIfNotNull(nameof(pickup))] - public static MicroHIDPickup? Get(BaseMicroHIDPickup? pickup) + internal override void OnRemove() { - if (pickup == null) - return null; - - return Dictionary.TryGetValue(pickup, out MicroHIDPickup wrapper) ? wrapper : (MicroHIDPickup)CreateItemWrapper(pickup); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Pickups/RadioPickup.cs b/LabApi/Features/Wrappers/Pickups/RadioPickup.cs index 38e35ab6..a1082b67 100644 --- a/LabApi/Features/Wrappers/Pickups/RadioPickup.cs +++ b/LabApi/Features/Wrappers/Pickups/RadioPickup.cs @@ -13,12 +13,28 @@ public class RadioPickup : Pickup /// <summary> /// Contains all the cached radio pickups, accessible through their <see cref="BaseRadioPickup"/>. /// </summary> - public new static Dictionary<BaseRadioPickup, RadioPickup> Dictionary { get; } = []; + public static new Dictionary<BaseRadioPickup, RadioPickup> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="RadioPickup"/>. /// </summary> - public new static IReadOnlyCollection<RadioPickup> List => Dictionary.Values; + public static new IReadOnlyCollection<RadioPickup> List => Dictionary.Values; + + /// <summary> + /// Gets the radio pickup from the <see cref="Dictionary"/> or creates a new if it doesn't exist and the provided <see cref="BaseRadioPickup"/> was not <see langword="null"/>. + /// </summary> + /// <param name="pickup">The <see cref="Base"/> if the pickup.</param> + /// <returns>The requested pickup or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(pickup))] + public static RadioPickup? Get(BaseRadioPickup? pickup) + { + if (pickup == null) + { + return null; + } + + return Dictionary.TryGetValue(pickup, out RadioPickup wrapper) ? wrapper : (RadioPickup)CreateItemWrapper(pickup); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -30,16 +46,9 @@ internal RadioPickup(BaseRadioPickup baseRadioPickup) Base = baseRadioPickup; if (CanCache) + { Dictionary.Add(baseRadioPickup, this); - } - - /// <summary> - /// A internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -65,9 +74,13 @@ public RadioMessages.RadioRangeLevel RangeLevel set { if (value == RadioMessages.RadioRangeLevel.RadioDisabled) + { IsEnabled = false; + } else + { Base.NetworkSavedRange = (byte)value; + } } } @@ -81,16 +94,11 @@ public float Battery } /// <summary> - /// Gets the radio pickup from the <see cref="Dictionary"/> or creates a new if it doesn't exist and the provided <see cref="BaseRadioPickup"/> was not <see langword="null"/>. + /// A internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="pickup">The <see cref="Base"/> if the pickup.</param> - /// <returns>The requested pickup or <see langword="null"/>.</returns> - [return: NotNullIfNotNull(nameof(pickup))] - public static RadioPickup? Get(BaseRadioPickup? pickup) + internal override void OnRemove() { - if (pickup == null) - return null; - - return Dictionary.TryGetValue(pickup, out RadioPickup wrapper) ? wrapper : (RadioPickup)CreateItemWrapper(pickup); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Pickups/Scp1576Pickup.cs b/LabApi/Features/Wrappers/Pickups/Scp1576Pickup.cs index e8b81b91..2cab477d 100644 --- a/LabApi/Features/Wrappers/Pickups/Scp1576Pickup.cs +++ b/LabApi/Features/Wrappers/Pickups/Scp1576Pickup.cs @@ -1,9 +1,5 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using BaseScp1576Pickup = InventorySystem.Items.Usables.Scp1576.Scp1576Pickup; namespace LabApi.Features.Wrappers; @@ -16,12 +12,28 @@ public class Scp1576Pickup : Pickup /// <summary> /// Contains all the cached SCP-1576 pickups, accessible through their <see cref="BaseScp1576Pickup"/>. /// </summary> - public new static Dictionary<BaseScp1576Pickup, Scp1576Pickup> Dictionary { get; } = []; + public static new Dictionary<BaseScp1576Pickup, Scp1576Pickup> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="Scp1576Pickup"/>. /// </summary> - public new static IReadOnlyCollection<Scp1576Pickup> List => Dictionary.Values; + public static new IReadOnlyCollection<Scp1576Pickup> List => Dictionary.Values; + + /// <summary> + /// Gets the SCP-1576 pickup from the <see cref="Dictionary"/> or creates a new if it doesn't exist and the provided <see cref="BaseScp1576Pickup"/> was not <see langword="null"/>. + /// </summary> + /// <param name="pickup">The <see cref="Base"/> if the pickup.</param> + /// <returns>The requested pickup or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(pickup))] + public static Scp1576Pickup? Get(BaseScp1576Pickup? pickup) + { + if (pickup == null) + { + return null; + } + + return Dictionary.TryGetValue(pickup, out Scp1576Pickup wrapper) ? wrapper : (Scp1576Pickup)CreateItemWrapper(pickup); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -33,16 +45,9 @@ internal Scp1576Pickup(BaseScp1576Pickup baseScp1576Pickup) Base = baseScp1576Pickup; if (CanCache) + { Dictionary.Add(baseScp1576Pickup, this); - } - - /// <summary> - /// A internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -60,17 +65,11 @@ public float HornPosition } /// <summary> - /// Gets the SCP-1576 pickup from the <see cref="Dictionary"/> or creates a new if it doesn't exist and the provided <see cref="BaseScp1576Pickup"/> was not <see langword="null"/>. + /// A internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="pickup">The <see cref="Base"/> if the pickup.</param> - /// <returns>The requested pickup or <see langword="null"/>.</returns> - [return: NotNullIfNotNull(nameof(pickup))] - public static Scp1576Pickup? Get(BaseScp1576Pickup? pickup) + internal override void OnRemove() { - if (pickup == null) - return null; - - return Dictionary.TryGetValue(pickup, out Scp1576Pickup wrapper) ? wrapper : (Scp1576Pickup)CreateItemWrapper(pickup); + base.OnRemove(); + Dictionary.Remove(Base); } - } diff --git a/LabApi/Features/Wrappers/Pickups/Scp244Pickup.cs b/LabApi/Features/Wrappers/Pickups/Scp244Pickup.cs index 76b3306d..79e18475 100644 --- a/LabApi/Features/Wrappers/Pickups/Scp244Pickup.cs +++ b/LabApi/Features/Wrappers/Pickups/Scp244Pickup.cs @@ -5,19 +5,35 @@ namespace LabApi.Features.Wrappers; /// <summary> -/// Wrapper for the <see cref="Scp244DeployablePickup"/> +/// Wrapper for the <see cref="Scp244DeployablePickup"/>. /// </summary> public class Scp244Pickup : Pickup { /// <summary> /// Contains all the cached SCP-244 pickups, accessible through their <see cref="Scp244DeployablePickup"/>. /// </summary> - public new static Dictionary<Scp244DeployablePickup, Scp244Pickup> Dictionary { get; } = []; + public static new Dictionary<Scp244DeployablePickup, Scp244Pickup> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="Scp244Pickup"/>. /// </summary> - public new static IReadOnlyCollection<Scp244Pickup> List => Dictionary.Values; + public static new IReadOnlyCollection<Scp244Pickup> List => Dictionary.Values; + + /// <summary> + /// Gets the SCP-244 pickup from the <see cref="Dictionary"/> or creates a new if it doesn't exist and the provided <see cref="Scp244DeployablePickup"/> was not <see langword="null"/>. + /// </summary> + /// <param name="pickup">The <see cref="Base"/> if the pickup.</param> + /// <returns>The requested pickup or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(pickup))] + public static Scp244Pickup? Get(Scp244DeployablePickup? pickup) + { + if (pickup == null) + { + return null; + } + + return Dictionary.TryGetValue(pickup, out Scp244Pickup wrapper) ? wrapper : (Scp244Pickup)CreateItemWrapper(pickup); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal Scp244Pickup(Scp244DeployablePickup scp244DeployablePickup) Base = scp244DeployablePickup; if (CanCache) + { Dictionary.Add(scp244DeployablePickup, this); - } - - /// <summary> - /// A internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -61,16 +70,11 @@ public Scp244State State public float SizePercent => Base.CurrentSizePercent; /// <summary> - /// Gets the SCP-244 pickup from the <see cref="Dictionary"/> or creates a new if it doesn't exist and the provided <see cref="Scp244DeployablePickup"/> was not <see langword="null"/>. + /// A internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="pickup">The <see cref="Base"/> if the pickup.</param> - /// <returns>The requested pickup or <see langword="null"/>.</returns> - [return: NotNullIfNotNull(nameof(pickup))] - public static Scp244Pickup? Get(Scp244DeployablePickup? pickup) + internal override void OnRemove() { - if (pickup == null) - return null; - - return Dictionary.TryGetValue(pickup, out Scp244Pickup wrapper) ? wrapper : (Scp244Pickup)CreateItemWrapper(pickup); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Pickups/Scp330Pickup.cs b/LabApi/Features/Wrappers/Pickups/Scp330Pickup.cs index 5d133ed1..c3572e58 100644 --- a/LabApi/Features/Wrappers/Pickups/Scp330Pickup.cs +++ b/LabApi/Features/Wrappers/Pickups/Scp330Pickup.cs @@ -6,19 +6,35 @@ namespace LabApi.Features.Wrappers; /// <summary> -/// Wrapper for the +/// Wrapper for the <see cref="BaseScp330Pickup"/>. /// </summary> public class Scp330Pickup : Pickup { /// <summary> /// Contains all the cached SCP-330 pickups, accessible through their <see cref="BaseScp330Pickup"/>. /// </summary> - public new static Dictionary<BaseScp330Pickup, Scp330Pickup> Dictionary { get; } = []; + public static new Dictionary<BaseScp330Pickup, Scp330Pickup> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="Scp330Pickup"/>. /// </summary> - public new static IReadOnlyCollection<Scp330Pickup> List => Dictionary.Values; + public static new IReadOnlyCollection<Scp330Pickup> List => Dictionary.Values; + + /// <summary> + /// Gets the SCP-330 pickup from the <see cref="Dictionary"/> or creates a new if it doesn't exist and the provided <see cref="BaseScp330Pickup"/> was not <see langword="null"/>. + /// </summary> + /// <param name="pickup">The <see cref="Base"/> if the pickup.</param> + /// <returns>The requested pickup or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(pickup))] + public static Scp330Pickup? Get(BaseScp330Pickup? pickup) + { + if (pickup == null) + { + return null; + } + + return Dictionary.TryGetValue(pickup, out Scp330Pickup wrapper) ? wrapper : (Scp330Pickup)CreateItemWrapper(pickup); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -30,16 +46,9 @@ internal Scp330Pickup(BaseScp330Pickup baseScp330Pickup) Base = baseScp330Pickup; if (CanCache) + { Dictionary.Add(baseScp330Pickup, this); - } - - /// <summary> - /// A internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -63,17 +72,11 @@ public CandyKindID ExposedCandy } /// <summary> - /// Gets the SCP-330 pickup from the <see cref="Dictionary"/> or creates a new if it doesn't exist and the provided <see cref="BaseScp330Pickup"/> was not <see langword="null"/>. + /// A internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="pickup">The <see cref="Base"/> if the pickup.</param> - /// <returns>The requested pickup or <see langword="null"/>.</returns> - [return: NotNullIfNotNull(nameof(pickup))] - public static Scp330Pickup? Get(BaseScp330Pickup? pickup) + internal override void OnRemove() { - if (pickup == null) - return null; - - return Dictionary.TryGetValue(pickup, out Scp330Pickup wrapper) ? wrapper : (Scp330Pickup)CreateItemWrapper(pickup); + base.OnRemove(); + Dictionary.Remove(Base); } - } diff --git a/LabApi/Features/Wrappers/Pickups/TimedGrenadePickup.cs b/LabApi/Features/Wrappers/Pickups/TimedGrenadePickup.cs index 9d290f7f..c4f62cea 100644 --- a/LabApi/Features/Wrappers/Pickups/TimedGrenadePickup.cs +++ b/LabApi/Features/Wrappers/Pickups/TimedGrenadePickup.cs @@ -12,12 +12,28 @@ public class TimedGrenadePickup : Pickup /// <summary> /// Contains all the cached timed grenade pickups, accessible through their <see cref="BaseTimedGrenadePickup"/>. /// </summary> - public new static Dictionary<BaseTimedGrenadePickup, TimedGrenadePickup> Dictionary { get; } = []; + public static new Dictionary<BaseTimedGrenadePickup, TimedGrenadePickup> Dictionary { get; } = []; /// <summary> /// A reference to all instances of <see cref="TimedGrenadePickup"/>. /// </summary> - public new static IReadOnlyCollection<TimedGrenadePickup> List => Dictionary.Values; + public static new IReadOnlyCollection<TimedGrenadePickup> List => Dictionary.Values; + + /// <summary> + /// Gets the timed grenade pickup from the <see cref="Dictionary"/> or creates a new if it doesn't exist and the provided <see cref="BaseTimedGrenadePickup"/> was not <see langword="null"/>. + /// </summary> + /// <param name="pickup">The <see cref="Base"/> if the pickup.</param> + /// <returns>The requested pickup or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(pickup))] + public static TimedGrenadePickup? Get(BaseTimedGrenadePickup? pickup) + { + if (pickup == null) + { + return null; + } + + return Dictionary.TryGetValue(pickup, out TimedGrenadePickup wrapper) ? wrapper : (TimedGrenadePickup)CreateItemWrapper(pickup); + } /// <summary> /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal TimedGrenadePickup(BaseTimedGrenadePickup baseTimedGrenadePickup) Base = baseTimedGrenadePickup; if (CanCache) + { Dictionary.Add(baseTimedGrenadePickup, this); - } - - /// <summary> - /// A internal method to remove itself from the cache when the base object is destroyed. - /// </summary> - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// <summary> @@ -47,16 +56,11 @@ internal override void OnRemove() public new BaseTimedGrenadePickup Base { get; } /// <summary> - /// Gets the timed grenade pickup from the <see cref="Dictionary"/> or creates a new if it doesn't exist and the provided <see cref="BaseTimedGrenadePickup"/> was not <see langword="null"/>. + /// A internal method to remove itself from the cache when the base object is destroyed. /// </summary> - /// <param name="pickup">The <see cref="Base"/> if the pickup.</param> - /// <returns>The requested pickup or <see langword="null"/>.</returns> - [return: NotNullIfNotNull(nameof(pickup))] - public static TimedGrenadePickup? Get(BaseTimedGrenadePickup? pickup) + internal override void OnRemove() { - if (pickup == null) - return null; - - return Dictionary.TryGetValue(pickup, out TimedGrenadePickup wrapper) ? wrapper : (TimedGrenadePickup)CreateItemWrapper(pickup); + base.OnRemove(); + Dictionary.Remove(Base); } } From a23ee3305b83c284779c924734ca6c3df3e01c5b Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:47:14 +0930 Subject: [PATCH 132/215] pickups --- LabApi/Features/Wrappers/Pickups/Pickup.cs | 365 +++++++++++---------- 1 file changed, 190 insertions(+), 175 deletions(-) diff --git a/LabApi/Features/Wrappers/Pickups/Pickup.cs b/LabApi/Features/Wrappers/Pickups/Pickup.cs index 7836090a..814b1435 100644 --- a/LabApi/Features/Wrappers/Pickups/Pickup.cs +++ b/LabApi/Features/Wrappers/Pickups/Pickup.cs @@ -3,11 +3,10 @@ using InventorySystem.Items; using InventorySystem.Items.Pickups; using InventorySystem.Items.ThrowableProjectiles; +using LabApi.Events.Arguments.ServerEvents; +using LabApi.Events.Handlers; using Mirror; using System; -using InventorySystem.Items.ThrowableProjectiles; -using LabApi.Events.Handlers; -using LabApi.Events.Arguments.ServerEvents; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using UnityEngine; @@ -21,6 +20,106 @@ namespace LabApi.Features.Wrappers; /// </summary> public class Pickup { + /// <summary> + /// Contains all the handlers for constructing wrappers for the associated base game types. + /// </summary> + private static readonly Dictionary<Type, Func<ItemPickupBase, Pickup>> TypeWrappers = []; + + /// <summary> + /// Contains all the cached items that have a none zero serial, accessible through their serial. + /// </summary> + /// <remarks> + /// Item pickups spawned by the map do not have a serial until they are unlocked so may not be cached here. + /// Use <see cref="Dictionary"/> or <see cref="List"/> instead if you need all item pickups. + /// </remarks> + public static Dictionary<ushort, Pickup> SerialCache { get; } = []; + + /// <summary> + /// Contains all the cached item pickups, accessible through their <see cref="ItemPickupBase"/>. + /// </summary> + public static Dictionary<ItemPickupBase, Pickup> Dictionary { get; } = []; + + /// <summary> + /// A reference to all instances of <see cref="Pickup"/>. + /// </summary> + public static IReadOnlyCollection<Pickup> List => Dictionary.Values; + + /// <summary> + /// Gets the pickup wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist. + /// </summary> + /// <param name="itemPickupBase">The <see cref="ItemPickupBase"/> of the pickup.</param> + /// <returns>The requested item <see cref="Pickup"/>.</returns> + [return: NotNullIfNotNull(nameof(itemPickupBase))] + public static Pickup? Get(ItemPickupBase? itemPickupBase) + { + if (itemPickupBase == null) + { + return null; + } + + if (Dictionary.TryGetValue(itemPickupBase, out Pickup pickup)) + { + return pickup; + } + + return CreateItemWrapper(itemPickupBase); + } + + /// <summary> + /// Gets the pickup wrapper from the <see cref="SerialCache"/>. + /// </summary> + /// <param name="itemSerial">The serial of the pickup.</param> + /// <returns>The requested item <see cref="Pickup"/> or null if it doesn't exist.</returns> + public static Pickup? Get(ushort itemSerial) => SerialCache.GetValueOrDefault(itemSerial); + + /// <summary> + /// Tries to get the pickup wrapper from the <see cref="SerialCache"/>. + /// </summary> + /// <param name="itemSerial">The serial of the pickup.</param> + /// <param name="pickup">The requested item <see cref="Pickup"/> or null if it doesn't exist.</param> + /// <returns>True of the pickup exists, otherwise false.</returns> + public static bool TryGet(ushort itemSerial, [NotNullWhen(true)] out Pickup? pickup) => SerialCache.TryGetValue(itemSerial, out pickup); + + /// <summary> + /// Creates a new <see cref="Pickup"/>. + /// </summary> + /// <param name="type">The <see cref="ItemType"/>.</param> + /// <param name="position">The initial position.</param> + /// <returns>The instantiated <see cref="Pickup"/>.</returns> + /// <remarks>The pickup is only spawned on the server, to spawn the pickup for clients use <see cref="Spawn"/>.</remarks> + public static Pickup? Create(ItemType type, Vector3 position) => Create(type, position, Quaternion.identity, Vector3.one); + + /// <summary> + /// Creates a new <see cref="Pickup"/>. + /// </summary> + /// <param name="type">The <see cref="ItemType"/>.</param> + /// <param name="position">The initial position.</param> + /// <param name="rotation">The initial rotation.</param> + /// <returns>The instantiated <see cref="Pickup"/>.</returns> + /// <remarks>The pickup is only spawned on the server, to spawn the pickup for clients use <see cref="Spawn"/>.</remarks> + public static Pickup? Create(ItemType type, Vector3 position, Quaternion rotation) => Create(type, position, rotation, Vector3.one); + + /// <summary> + /// Creates a new <see cref="Pickup"/>. + /// </summary> + /// <param name="type">The <see cref="ItemType"/>.</param> + /// <param name="position">The initial position.</param> + /// <param name="rotation">The initial rotation.</param> + /// <param name="scale">The initial scale.</param> + /// <returns>The instantiated <see cref="Pickup"/>.</returns> + /// <remarks>The pickup is only spawned on the server, to spawn the pickup for clients use <see cref="Spawn"/>.</remarks> + public static Pickup? Create(ItemType type, Vector3 position, Quaternion rotation, Vector3 scale) + { + if (type == ItemType.None || !InventoryItemLoader.AvailableItems.TryGetValue(type, out ItemBase itemBase)) + { + return null; + } + + ItemPickupBase newPickupBase = InventoryExtensions.ServerCreatePickup(itemBase, new PickupSyncInfo(type, itemBase.Weight), position, rotation, false); + newPickupBase.transform.localScale = scale; + return Get(newPickupBase); + } + /// <summary> /// Initializes the <see cref="Pickup"/> class. /// </summary> @@ -50,28 +149,94 @@ internal static void Initialize() } /// <summary> - /// Contains all the handlers for constructing wrappers for the associated base game types. + /// Creates a new wrapper from the base pickup object. /// </summary> - private static readonly Dictionary<Type, Func<ItemPickupBase, Pickup>> typeWrappers = []; + /// <param name="pickupBase">The base object.</param> + /// <returns>The newly created wrapper.</returns> + protected static Pickup CreateItemWrapper(ItemPickupBase pickupBase) + { + if (TypeWrappers.TryGetValue(pickupBase.GetType(), out Func<ItemPickupBase, Pickup> ctorFunc)) + { + return ctorFunc(pickupBase); + } + + Console.Logger.Warn($"Failed to find pickup wrapper for type {pickupBase.GetType()}"); + return new Pickup(pickupBase); + } /// <summary> - /// Contains all the cached items that have a none zero serial, accessible through their serial. + /// A private method to handle the creation of new pickups in the server. /// </summary> - /// <remarks> - /// Item pickups spawned by the map do not have a serial until they are unlocked so may not be cached here. - /// Use <see cref="Dictionary"/> or <see cref="List"/> instead if you need all item pickups. - /// </remarks> - public static Dictionary<ushort, Pickup> SerialCache { get; } = []; + /// <param name="pickup">The created <see cref="ItemPickupBase"/> instance.</param> + private static void AddPickup(ItemPickupBase pickup) + { + try + { + if (!Dictionary.ContainsKey(pickup)) + { + Pickup wrapper = CreateItemWrapper(pickup); + ServerEvents.OnPickupCreated(new PickupCreatedEventArgs(wrapper)); + } + } + catch (Exception e) + { + Console.Logger.Error($"Failed to handle pickup creation with error: {e}"); + } + } /// <summary> - /// Contains all the cached item pickups, accessible through their <see cref="ItemPickupBase"/>. + /// A private method to handle the removal of pickups from the server. /// </summary> - public static Dictionary<ItemPickupBase, Pickup> Dictionary { get; } = []; + /// <param name="pickup">The to be destroyed <see cref="ItemPickupBase"/> instance.</param> + private static void RemovePickup(ItemPickupBase pickup) + { + try + { + if (Dictionary.TryGetValue(pickup, out Pickup item)) + { + item.OnRemove(); + } + + ServerEvents.OnPickupDestroyed(new PickupDestroyedEventArgs(item)); + } + catch (Exception e) + { + Console.Logger.Error($"Failed to handle pickup destruction with error: {e}"); + } + } /// <summary> - /// A reference to all instances of <see cref="Pickup"/>. + /// A private method to handle the addition of wrapper handlers. /// </summary> - public static IReadOnlyCollection<Pickup> List => Dictionary.Values; + /// <typeparam name="T">The derived base game type to handle.</typeparam> + /// <param name="constructor">A handler to construct the wrapper with the base game instance.</param> + private static void Register<T>(Func<T, Pickup> constructor) + where T : ItemPickupBase + { + TypeWrappers.Add(typeof(T), x => constructor((T)x)); + } + + /// <summary> + /// A protected constructor to prevent external instantiation. + /// </summary> + /// <param name="itemPickupBase">The <see cref="ItemPickupBase"/> of the pickup.</param> + protected Pickup(ItemPickupBase itemPickupBase) + { + Base = itemPickupBase; + GameObject = itemPickupBase.gameObject; + Transform = itemPickupBase.transform; + IsPrefab = InventoryItemLoader.TryGetItem(itemPickupBase.ItemId.TypeId, out ItemBase prefab) && prefab.PickupDropModel == itemPickupBase; + + if (CanCache) + { + Dictionary.Add(itemPickupBase, this); + + if (itemPickupBase.Info.Serial != 0) + { + SerialCache[itemPickupBase.Info.Serial] = this; + } + } + } /// <summary> /// The <see cref="ItemPickupBase"/> of the pickup. @@ -83,6 +248,9 @@ internal static void Initialize() /// </summary> public NetworkIdentity NetworkIdentity => Base.netIdentity; + /// <summary> + /// THe <see cref="PickupStandardPhysics"/> of the pickup. + /// </summary> /// <remarks> /// Will be null if the <see cref="PickupPhysicsModule"/> is not a <see cref="InventorySystem.Items.Pickups.PickupStandardPhysics"/> e.g. when SCP018 it is in its "Activated" state and uses an alternate physics module. /// Use <see cref="PhysicsModule"/> instead for those cases. @@ -153,7 +321,7 @@ public float Weight get => Base.Info.WeightKg; set => Base.NetworkInfo = Base.Info with { - WeightKg = value + WeightKg = value, }; } @@ -165,7 +333,7 @@ public bool IsLocked get => Base.Info.Locked; set => Base.NetworkInfo = Base.Info with { - Locked = value + Locked = value, }; } @@ -177,7 +345,7 @@ public bool IsInUse get => Base.Info.InUse; set => Base.NetworkInfo = Base.Info with { - InUse = value + InUse = value, }; } @@ -219,35 +387,6 @@ public Quaternion Rotation /// </summary> protected bool CanCache => !IsDestroyed && !IsPrefab && Base.isActiveAndEnabled; - /// <summary> - /// A protected constructor to prevent external instantiation. - /// </summary> - /// <param name="itemPickupBase">The <see cref="ItemPickupBase"/> of the pickup.</param> - protected Pickup(ItemPickupBase itemPickupBase) - { - Base = itemPickupBase; - GameObject = itemPickupBase.gameObject; - Transform = itemPickupBase.transform; - IsPrefab = InventoryItemLoader.TryGetItem(itemPickupBase.ItemId.TypeId, out ItemBase prefab) && prefab.PickupDropModel == itemPickupBase; - - if (CanCache) - { - Dictionary.Add(itemPickupBase, this); - - if (itemPickupBase.Info.Serial != 0) - SerialCache[itemPickupBase.Info.Serial] = this; - } - } - - /// <summary> - /// An internal virtual method to signal to derived implementations to uncache when the base object is destroyed. - /// </summary> - internal virtual void OnRemove() - { - Dictionary.Remove(Base); - SerialCache.Remove(Serial); - } - /// <summary> /// Spawns the pickup. /// </summary> @@ -271,135 +410,11 @@ public override string ToString() } /// <summary> - /// Gets the pickup wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist. - /// </summary> - /// <param name="itemPickupBase">The <see cref="ItemPickupBase"/> of the pickup.</param> - /// <returns>The requested item <see cref="Pickup"/>.</returns> - [return: NotNullIfNotNull(nameof(itemPickupBase))] - public static Pickup? Get(ItemPickupBase? itemPickupBase) - { - if (itemPickupBase == null) - return null; - - if (Dictionary.TryGetValue(itemPickupBase, out Pickup pickup)) - return pickup; - - return CreateItemWrapper(itemPickupBase); - } - - /// <summary> - /// Gets the pickup wrapper from the <see cref="SerialCache"/>. - /// </summary> - /// <param name="itemSerial">The serial of the pickup.</param> - /// <returns>The requested item <see cref="Pickup"/> or null if it doesn't exist.</returns> - public static Pickup? Get(ushort itemSerial) => SerialCache.GetValueOrDefault(itemSerial); - - /// <summary> - /// Tries to get the pickup wrapper from the <see cref="SerialCache"/>. - /// </summary> - /// <param name="itemSerial">The serial of the pickup.</param> - /// <param name="pickup">The requested item <see cref="Pickup"/> or null if it doesn't exist.</param> - /// <returns>True of the pickup exists, otherwise false.</returns> - public static bool TryGet(ushort itemSerial, [NotNullWhen(true)] out Pickup? pickup) => SerialCache.TryGetValue(itemSerial, out pickup); - - /// <summary> - /// Creates a new <see cref="Pickup"/>. - /// </summary> - /// <param name="type">The <see cref="ItemType"/>.</param> - /// <param name="position">The initial position.</param> - /// <returns>The instantiated <see cref="Pickup"/></returns> - /// <remarks>The pickup is only spawned on the server, to spawn the pickup for clients use <see cref="Spawn"/>.</remarks> - public static Pickup? Create(ItemType type, Vector3 position) => Create(type, position, Quaternion.identity, Vector3.one); - - /// <summary> - /// Creates a new <see cref="Pickup"/>. - /// </summary> - /// <param name="type">The <see cref="ItemType"/>.</param> - /// <param name="position">The initial position.</param> - /// <param name="rotation">The initial rotation.</param> - /// <returns>The instantiated <see cref="Pickup"/></returns> - /// <remarks>The pickup is only spawned on the server, to spawn the pickup for clients use <see cref="Spawn"/>.</remarks> - public static Pickup? Create(ItemType type, Vector3 position, Quaternion rotation) => Create(type, position, rotation, Vector3.one); - - /// <summary> - /// Creates a new <see cref="Pickup"/>. - /// </summary> - /// <param name="type">The <see cref="ItemType"/>.</param> - /// <param name="position">The initial position.</param> - /// <param name="rotation">The initial rotation.</param> - /// <param name="scale">The initial scale.</param> - /// <returns>The instantiated <see cref="Pickup"/></returns> - /// <remarks>The pickup is only spawned on the server, to spawn the pickup for clients use <see cref="Spawn"/>.</remarks> - public static Pickup? Create(ItemType type, Vector3 position, Quaternion rotation, Vector3 scale) - { - if (type == ItemType.None || !InventoryItemLoader.AvailableItems.TryGetValue(type, out ItemBase itemBase)) - return null; - - ItemPickupBase newPickupBase = InventoryExtensions.ServerCreatePickup(itemBase, new PickupSyncInfo(type, itemBase.Weight), position, rotation, false); - newPickupBase.transform.localScale = scale; - return Get(newPickupBase); - } - - /// <summary> - /// A private method to handle the creation of new pickups in the server. - /// </summary> - /// <param name="pickup">The created <see cref="ItemPickupBase"/> instance.</param> - private static void AddPickup(ItemPickupBase pickup) - { - try - { - if (!Dictionary.ContainsKey(pickup)) - { - Pickup wrapper = CreateItemWrapper(pickup); - ServerEvents.OnPickupCreated(new PickupCreatedEventArgs(wrapper)); - } - } - catch(Exception e) - { - Console.Logger.Error($"Failed to handle pickup creation with error: {e}"); - } - } - - /// <summary> - /// A private method to handle the removal of pickups from the server. - /// </summary> - /// <param name="pickup">The to be destroyed <see cref="ItemPickupBase"/> instance.</param> - private static void RemovePickup(ItemPickupBase pickup) - { - try - { - if (Dictionary.TryGetValue(pickup, out Pickup item)) - item.OnRemove(); - - ServerEvents.OnPickupDestroyed(new PickupDestroyedEventArgs(item)); - } - catch(Exception e) - { - Console.Logger.Error($"Failed to handle pickup destruction with error: {e}"); - } - } - - /// <summary> - /// A private method to handle the addition of wrapper handlers. - /// </summary> - /// <typeparam name="T">The derived base game type to handle.</typeparam> - /// <param name="constructor">A handler to construct the wrapper with the base game instance.</param> - private static void Register<T>(Func<T, Pickup> constructor) where T : ItemPickupBase - { - typeWrappers.Add(typeof(T), x => constructor((T)x)); - } - - /// <summary> - /// Creates a new wrapper from the base pickup object. + /// An internal virtual method to signal to derived implementations to uncache when the base object is destroyed. /// </summary> - /// <param name="pickupBase">The base object.</param> - /// <returns>The newly created wrapper.</returns> - protected static Pickup CreateItemWrapper(ItemPickupBase pickupBase) + internal virtual void OnRemove() { - if (typeWrappers.TryGetValue(pickupBase.GetType(), out Func<ItemPickupBase, Pickup> ctorFunc)) - return ctorFunc(pickupBase); - - Console.Logger.Warn($"Failed to find pickup wrapper for type {pickupBase.GetType()}"); - return new Pickup(pickupBase); + Dictionary.Remove(Base); + SerialCache.Remove(Serial); } } From ea995f3301c769e348190f49cd88738d74eb66b9 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:47:18 +0930 Subject: [PATCH 133/215] player --- LabApi/Features/Wrappers/Players/Player.cs | 1561 +++++++++++--------- 1 file changed, 839 insertions(+), 722 deletions(-) diff --git a/LabApi/Features/Wrappers/Players/Player.cs b/LabApi/Features/Wrappers/Players/Player.cs index 74030993..06c01a0e 100644 --- a/LabApi/Features/Wrappers/Players/Player.cs +++ b/LabApi/Features/Wrappers/Players/Player.cs @@ -39,15 +39,15 @@ namespace LabApi.Features.Wrappers; /// </summary> public class Player { - /// <summary> - /// Contains all the cached players in the game, accessible through their <see cref="ReferenceHub"/>. + /// <summary> + /// A cache of players by their User ID. Does not necessarily contain all players. /// </summary> - public static Dictionary<ReferenceHub, Player> Dictionary { get; } = []; + private static readonly Dictionary<string, Player> UserIdCache = new(CustomNetworkManager.slots, StringComparer.OrdinalIgnoreCase); /// <summary> - /// A cache of players by their User ID. Does not necessarily contain all players. + /// Contains all the cached players in the game, accessible through their <see cref="ReferenceHub"/>. /// </summary> - private static readonly Dictionary<string, Player> UserIdCache = new(CustomNetworkManager.slots, StringComparer.OrdinalIgnoreCase); + public static Dictionary<ReferenceHub, Player> Dictionary { get; } = []; /// <summary> /// A reference to all <see cref="Player"/> instances currently in the game. @@ -100,7 +100,7 @@ public class Player public static int Count => ReadyList.Count(); /// <summary> - /// Gets the amount of non-verified players + /// Gets the amount of non-verified players. /// </summary> public static int NonVerifiedCount => UnauthenticatedList.Count(); @@ -110,1037 +110,1176 @@ public class Player public static int ConnectionsCount => LiteNetLib4MirrorCore.Host.ConnectedPeersCount; /// <summary> - /// Initializes the <see cref="Player"/> class to subscribe to <see cref="ReferenceHub"/> events and handle the player cache. + /// Validates the custom info text and returns result whether it is valid or invalid.<br/> + /// Current validation requirements are the following: + /// <br/> + /// <list type="bullet"> + /// <item>Match the <see cref="Misc.PlayerCustomInfoRegex"/> regex.</item> + /// <item>Use only color,i,b and size rich text tags.</item> + /// <item>Colors used have to be from <see cref="Misc.AcceptedColours"/></item> + /// </list> + /// <br/> /// </summary> - [InitializeWrapper] - internal static void Initialize() + /// <param name="text">The text to check on.</param> + /// <param name="rejectionReason">Out parameter containing rejection reason.</param> + /// <returns>Whether is the info parameter valid.</returns> + public static bool ValidateCustomInfo(string text, out string rejectionReason) => NicknameSync.ValidateCustomInfo(text, out rejectionReason); + + /// <summary> + /// Gets a all players matching the criteria specified by the <see cref="PlayerSearchFlags"/>. + /// </summary> + /// <param name="flags">The <see cref="PlayerSearchFlags"/> of the players to include.</param> + /// <returns>The set of players that match the criteria.</returns> + /// <remarks> + /// By default this returns the same set of players as <see cref="ReadyList"/>. + /// </remarks> + public static IEnumerable<Player> GetAll(PlayerSearchFlags flags = PlayerSearchFlags.AuthenticatedAndDummy) { - Dictionary.Clear(); - UserIdCache.Clear(); + bool authenticated = (flags & PlayerSearchFlags.AuthenticatedPlayers) > 0; + bool unauthenticated = (flags & PlayerSearchFlags.UnauthenticatedPlayers) > 0; + bool dummyNpcs = (flags & PlayerSearchFlags.DummyNpcs) > 0; + bool regularNpcs = (flags & PlayerSearchFlags.RegularNpcs) > 0; + bool host = (flags & PlayerSearchFlags.Host) > 0; - ReferenceHub.OnPlayerAdded += AddPlayer; - ReferenceHub.OnPlayerRemoved += RemovePlayer; + bool includePlayers = authenticated || unauthenticated; + bool allPlayers = authenticated && unauthenticated; + bool includeNpcs = dummyNpcs || regularNpcs; + bool allNpcs = dummyNpcs && regularNpcs; + + foreach (Player player in List) + { + if ((includePlayers && player.IsPlayer && (allPlayers || player.IsReady == authenticated)) || + ((includeNpcs && player.IsNpc) && (allNpcs || player.IsDummy == dummyNpcs)) || + (host && player.IsHost)) + { + yield return player; + } + } } + #region Player Getters + /// <summary> - /// An internal constructor to prevent external instantiation. + /// Gets the player wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist. /// </summary> /// <param name="referenceHub">The reference hub of the player.</param> - internal Player(ReferenceHub referenceHub) + /// <returns>The requested player or null if the reference hub is null.</returns> + [return: NotNullIfNotNull(nameof(referenceHub))] + public static Player? Get(ReferenceHub? referenceHub) { - Dictionary.Add(referenceHub, this); + if (referenceHub == null) + { + return null; + } - ReferenceHub = referenceHub; - CustomDataStoreManager.AddPlayer(this); + return Dictionary.TryGetValue(referenceHub, out Player player) ? player : CreatePlayerWrapper(referenceHub); } /// <summary> - /// The <see cref="ReferenceHub">Reference Hub</see> of the player. + /// Gets a list of players from a list of reference hubs. /// </summary> - public ReferenceHub ReferenceHub { get; } + /// <param name="referenceHubs">The reference hubs of the players.</param> + /// <returns>A list of players.</returns> + public static List<Player> Get(IEnumerable<ReferenceHub> referenceHubs) + { + // We rent a list from the pool to avoid unnecessary allocations. + // We don't care if the developer forgets to return the list to the pool + // as at least it will be more efficient than always allocating a new list. + List<Player> list = ListPool<Player>.Shared.Rent(); + return GetNonAlloc(referenceHubs, list); + } /// <summary> - /// Gets the player's <see cref="GameObject"/>. + /// Gets a list of players from a list of reference hubs without allocating a new list. /// </summary> - public GameObject GameObject => ReferenceHub.gameObject; + /// <param name="referenceHubs">The reference hubs of the players.</param> + /// <param name="list">A reference to the list to add the players to.</param> + /// <returns>The <paramref name="list"/> passed in.</returns> + public static List<Player> GetNonAlloc(IEnumerable<ReferenceHub> referenceHubs, List<Player> list) + { + // We clear the list to avoid any previous data. + list.Clear(); - /// <summary> - /// Gets whether the player is the host or server. - /// </summary> - public bool IsHost => ReferenceHub.isLocalPlayer; + // And then we add all the players to the list. + list.AddRange(referenceHubs.Select(Get)!); - /// <summary> - /// Gets whether the player is the dedicated server. - /// </summary> - [Obsolete($"Use {nameof(IsHost)} instead")] - public bool IsServer => ReferenceHub.isLocalPlayer; + // We finally return the list. + return list; + } - /// <summary> - /// Gets whether this <see cref="Player"/> instance is not controlled by a real human being. - /// </summary> - /// <remarks> - /// This list includes dummy players. - /// </remarks> - public bool IsNpc => !IsHost && ReferenceHub.connectionToClient.GetType() != typeof(NetworkConnectionToClient); + #region Get Player from a GameObject /// <summary> - /// Gets whether the player is a real player and not the host or an Npc. + /// Gets the <see cref="Player"/> associated with the <see cref="GameObject"/>. /// </summary> - public bool IsPlayer => Connection.GetType() == typeof(NetworkConnectionToClient); + /// <param name="gameObject">The <see cref="UnityEngine.GameObject"/> to get the player from.</param> + /// <returns>The <see cref="Player"/> associated with the <see cref="GameObject"/> or null if it doesn't exist.</returns> + public static Player? Get(GameObject? gameObject) => TryGet(gameObject, out Player? player) ? player : null; /// <summary> - /// Gets whether the player is a dummy instance. + /// Tries to get the <see cref="Player"/> associated with the <see cref="GameObject"/>. /// </summary> - public bool IsDummy => ReferenceHub.authManager.InstanceMode == ClientInstanceMode.Dummy; + /// <param name="gameObject">The <see cref="UnityEngine.GameObject"/> to get the player from.</param> + /// <param name="player">The <see cref="Player"/> associated with the <see cref="UnityEngine.GameObject"/> or null if it doesn't exist.</param> + /// <returns>Whether the player was successfully retrieved.</returns> + public static bool TryGet(GameObject? gameObject, [NotNullWhen(true)] out Player? player) + { + player = null; + if (gameObject == null) + { + return false; + } - /// <summary> - /// Gets the Player's User ID. - /// </summary> - public string UserId => ReferenceHub.authManager.UserId; + if (!ReferenceHub.TryGetHub(gameObject, out ReferenceHub? hub)) + { + return false; + } - /// <summary> - /// Gets the player's Network ID. - /// </summary> - public uint NetworkId => ReferenceHub.characterClassManager.netId; + player = Get(hub); + return true; + } - /// <summary> - /// Gets the player's <see cref="NetworkConnection"/>. - /// </summary> - public NetworkConnection Connection => IsHost ? ReferenceHub.networkIdentity.connectionToServer : ReferenceHub.networkIdentity.connectionToClient; + #endregion - /// <summary> - /// Gets the player's <see cref="NetworkConnectionToClient"/>. - /// </summary> - public NetworkConnectionToClient ConnectionToClient => ReferenceHub.networkIdentity.connectionToClient; + #region Get Player from a NetworkIdentity /// <summary> - /// Gets the player's <see cref="RecyclablePlayerId"/> value. + /// Gets the <see cref="Player"/> associated with the <see cref="NetworkIdentity"/>. /// </summary> - public int PlayerId => ReferenceHub.PlayerId; + /// <param name="identity">The <see cref="NetworkIdentity"/> to get the player from.</param> + /// <returns>The <see cref="Player"/> associated with the <see cref="NetworkIdentity"/> or null if it doesn't exist.</returns> + public static Player? Get(NetworkIdentity? identity) => TryGet(identity, out Player? player) ? player : null; /// <summary> - /// Gets if the player is currently offline. + /// Tries to get the <see cref="Player"/> associated with the <see cref="NetworkIdentity"/>. /// </summary> - [Obsolete("Use IsDestroyed instead.")] - public bool IsOffline => GameObject == null; + /// <param name="identity">The <see cref="NetworkIdentity"/> to get the player from.</param> + /// <param name="player">The <see cref="Player"/> associated with the <see cref="NetworkIdentity"/> or null if it doesn't exist.</param> + /// <returns>Whether the player was successfully retrieved.</returns> + public static bool TryGet(NetworkIdentity? identity, [NotNullWhen(true)] out Player? player) + { + player = null; + if (identity == null) + { + return false; + } - /// <summary> - /// Gets if the player is currently online. - /// </summary> - [Obsolete("Use !IsDestroyed instead.")] - public bool IsOnline => !IsOffline; + if (!TryGet(identity.netId, out player)) + { + return false; + } - /// <summary> - /// Gets if the player is properly connected and authenticated. - /// </summary> - public bool IsReady => ReferenceHub.authManager.InstanceMode != ClientInstanceMode.Unverified && ReferenceHub.nicknameSync.NickSet; + return true; + } + + #endregion + + #region Get Player from a NetworkIdentity.netId (uint) /// <summary> - /// Gets the player's IP address. + /// Gets the <see cref="Player"/> associated with the <see cref="NetworkIdentity.netId"/>. /// </summary> - public string IpAddress => ReferenceHub.characterClassManager.connectionToClient.address; + /// <param name="netId">The <see cref="NetworkIdentity.netId"/> to get the player from.</param> + /// <returns>The <see cref="Player"/> associated with the <see cref="NetworkIdentity.netId"/> or null if it doesn't exist.</returns> + public static Player? Get(uint netId) => TryGet(netId, out Player? player) ? player : null; /// <summary> - /// Gets or sets the player's current role. + /// Tries to get the <see cref="Player"/> associated with the <see cref="NetworkIdentity.netId"/>. /// </summary> - public RoleTypeId Role + /// <param name="netId">The <see cref="NetworkIdentity.netId"/> to get the player from.</param> + /// <param name="player">The <see cref="Player"/> associated with the <see cref="NetworkIdentity.netId"/> or null if it doesn't exist.</param> + /// <returns>Whether the player was successfully retrieved.</returns> + public static bool TryGet(uint netId, [NotNullWhen(true)] out Player? player) { - get => ReferenceHub.GetRoleId(); - set => ReferenceHub.roleManager.ServerSetRole(value, RoleChangeReason.RemoteAdmin); + player = null; + if (!ReferenceHub.TryGetHubNetID(netId, out ReferenceHub hub)) + { + return false; + } + + player = Get(hub); + return true; } - /// <summary> - /// Gets the player's current <see cref="PlayerRoleBase"/>. - /// </summary> - public PlayerRoleBase RoleBase => ReferenceHub.roleManager.CurrentRole; + #endregion - /// <summary> - /// Get's the player's current role unique identifier. - /// </summary> - public int LifeId => RoleBase.UniqueLifeIdentifier; + #region Get Player from a ICommandSender /// <summary> - /// Gets the Player's Nickname. + /// Gets the <see cref="Player"/> associated with the <see cref="ICommandSender"/>. /// </summary> - public string Nickname => ReferenceHub.nicknameSync.MyNick; + /// <param name="sender">The <see cref="ICommandSender"/> to get the player from.</param> + /// <returns>The <see cref="Player"/> associated with the <see cref="ICommandSender"/> or null if it doesn't exist.</returns> + public static Player? Get(ICommandSender? sender) => TryGet(sender, out Player? player) ? player : null; /// <summary> - /// Gets or sets the Player's Display Name. + /// Tries to get the <see cref="Player"/> associated with the <see cref="ICommandSender"/>. /// </summary> - public string DisplayName + /// <param name="sender">The <see cref="ICommandSender"/> to get the player from.</param> + /// <param name="player">The <see cref="Player"/> associated with the <see cref="ICommandSender"/> or null if it doesn't exist.</param> + /// <returns>Whether the player was successfully retrieved.</returns> + public static bool TryGet(ICommandSender? sender, [NotNullWhen(true)] out Player? player) { - get => ReferenceHub.nicknameSync.DisplayName; - set => ReferenceHub.nicknameSync.DisplayName = value; - } + player = null; - /// <summary> - /// Gets the log name needed for command senders. - /// </summary> - public string LogName => IsHost ? "SERVER CONSOLE" : $"{Nickname} ({UserId})"; + if (sender is not CommandSender commandSender) + { + return false; + } - /// <summary> - /// Gets or sets the player's custom info.<br/> - /// Do note that custom info is restriced by several things listed in <see cref="ValidateCustomInfo"/>. - /// Please use this method to validate your string as it is validated on the client by the same method. - /// </summary> - public string CustomInfo - { - get => ReferenceHub.nicknameSync.CustomPlayerInfo; - set => ReferenceHub.nicknameSync.CustomPlayerInfo = value; + return TryGet(commandSender.SenderId, out player); } + #endregion + + #region Get Player from a UserId + /// <summary> - /// Gets or sets the player's info area flags. - /// Flags determine what info is displayed to other players when they hover their crosshair over. + /// Gets the <see cref="Player"/> associated with the <paramref name="userId"/>. /// </summary> - public PlayerInfoArea InfoArea - { - get => ReferenceHub.nicknameSync.Network_playerInfoToShow; - set => ReferenceHub.nicknameSync.Network_playerInfoToShow = value; - } + /// <param name="userId">The User ID of the player.</param> + /// <returns>The <see cref="Player"/> associated with the <paramref name="userId"/> or null if it doesn't exist.</returns> + public static Player? Get(string? userId) => TryGet(userId, out Player? player) ? player : null; /// <summary> - /// Gets or sets the player's current health. + /// Tries to get the <see cref="Player"/> associated with the <paramref name="userId"/>. /// </summary> - public float Health + /// <param name="userId">The user ID of the player.</param> + /// <param name="player">The <see cref="Player"/> associated with the <paramref name="userId"/> or null if it doesn't exist.</param> + /// <returns>Whether the player was successfully retrieved.</returns> + public static bool TryGet(string? userId, [NotNullWhen(true)] out Player? player) { - get => ReferenceHub.playerStats.GetModule<HealthStat>().CurValue; - set => ReferenceHub.playerStats.GetModule<HealthStat>().CurValue = value; + player = null; + if (string.IsNullOrEmpty(userId)) + { + return false; + } + + if (UserIdCache.TryGetValue(userId!, out player) && player.IsOnline) + { + return true; + } + + player = List.FirstOrDefault(x => x.UserId == userId); + if (player == null) + { + return false; + } + + UserIdCache[userId!] = player; + return true; } + #endregion + + #region Get Player from a Player Id + /// <summary> - /// Gets or sets the player's current maximum health. + /// Gets the <see cref="Player" /> associated with the <paramref name="playerId" />. /// </summary> - public float MaxHealth + /// <param name="playerId">The player ID of the player.</param> + /// <returns>The <see cref="Player" /> associated with the <paramref name="playerId" /> or null if it doesn't exist.</returns> + public static Player? Get(int playerId) => TryGet(playerId, out Player? player) ? player : null; + + /// <summary> + /// Tries to get the <see cref="Player" /> associated with the <paramref name="playerId" />. + /// </summary> + /// <param name="playerId">The player ID of the player.</param> + /// <param name="player">The <see cref="Player" /> associated with the <paramref name="playerId" /> or null if it doesn't exist.</param> + /// <returns>Whether the player was successfully retrieved.</returns> + public static bool TryGet(int playerId, [NotNullWhen(true)] out Player? player) { - get => ReferenceHub.playerStats.GetModule<HealthStat>().MaxValue; - set => ReferenceHub.playerStats.GetModule<HealthStat>().MaxValue = value; + player = List.FirstOrDefault(n => n.PlayerId == playerId); + return player != null; } + #endregion + + #region Get Player from a Name + /// <summary> - /// Gets or sets the player's current artificial health.<br/> - /// Setting the value will clear all the current "processes" (each process is responsible for decaying AHP value separately. Eg 2 processes blue candy AHP, which doesn't decay and adrenaline proccess, where AHP does decay).<br/> - /// Note: This value cannot be greater than <see cref="MaxArtificialHealth"/>. Set it to your desired value first if its over <see cref="AhpStat.DefaultMax"/> and then set this one. + /// Get closest player by lexicographical order. + /// Players are compared by their <see cref="DisplayName"/>. /// </summary> - public float ArtificialHealth - { - get => ReferenceHub.playerStats.GetModule<AhpStat>().CurValue; - set - { - AhpStat ahp = ReferenceHub.playerStats.GetModule<AhpStat>(); - ahp.ServerKillAllProcesses(); + /// <param name="input">The input to search the player by.</param> + /// <param name="requireFullMatch">Whether the full match is required.</param> + /// <returns>Player or <see langword="null"/> if no close player found.</returns> + public static Player? GetByDisplayName(string input, bool requireFullMatch = false) => GetByName(input, requireFullMatch, static p => p.DisplayName); - if (value > 0) - ReferenceHub.playerStats.GetModule<AhpStat>().ServerAddProcess(value, MaxArtificialHealth, 0f, 1f, 0f, false); - } - } + /// <summary> + /// Gets the closest player by lexicographical order. + /// Players are compared by their <see cref="Nickname"/>. + /// </summary> + /// <param name="input">The input to search the player by.</param> + /// <param name="requireFullMatch">Whether the full match is required.</param> + /// <returns>Player or <see langword="null"/> if no close player found.</returns> + public static Player? GetByNickname(string input, bool requireFullMatch = false) => GetByName(input, requireFullMatch, static p => p.Nickname); /// <summary> - /// Gets or sets the player's current maximum artificial health or hume shield.<br/> - /// Note: The value resets to <see cref="AhpStat.DefaultMax"/> when the player's AHP reaches 0. + /// Gets the closest player by lexicographical order. + /// Base function to allow to select by <see langword="string"/> player property. /// </summary> - public float MaxArtificialHealth + /// <param name="input">The input to search the player by.</param> + /// <param name="requireFullMatch">Whether the full match is required.</param> + /// <param name="propertySelector">Function to select player property.</param> + /// <returns>Player or <see langword="null"/> if no close player found.</returns> + public static Player? GetByName(string input, bool requireFullMatch, Func<Player, string> propertySelector) { - get => ReferenceHub.playerStats.GetModule<AhpStat>().MaxValue; - set => ReferenceHub.playerStats.GetModule<AhpStat>().MaxValue = value; + IOrderedEnumerable<Player> sortedPlayers = List.OrderBy(propertySelector); + + foreach (Player player in sortedPlayers) + { + string toCheck = propertySelector(player); + if (requireFullMatch) + { + if (toCheck.Equals(input, StringComparison.OrdinalIgnoreCase)) + { + return player; + } + } + else if (toCheck.StartsWith(input, StringComparison.OrdinalIgnoreCase)) + { + return player; + } + } + + return null; } /// <summary> - /// Gets or sets the player's hume shield current value. + /// Tries to get players by name by seeing if their name starts with the input. /// </summary> - public float HumeShield + /// <param name="input">The input to search for.</param> + /// <param name="players">The output players if found.</param> + /// <returns>True if the players are found, false otherwise.</returns> + public static bool TryGetPlayersByName(string input, out List<Player> players) { - get => ReferenceHub.playerStats.GetModule<HumeShieldStat>().CurValue; - set => ReferenceHub.playerStats.GetModule<HumeShieldStat>().CurValue = value; + players = GetNonAlloc( + ReferenceHub.AllHubs.Where(x => x.nicknameSync.Network_myNickSync.StartsWith(input, StringComparison.OrdinalIgnoreCase)), + ListPool<Player>.Shared.Rent()); + + return players.Count > 0; } + #endregion + + #endregion + /// <summary> - /// Gets or sets the player's maximum hume shield value. - /// Note: This value may change if the player passes a new humeshield treshold for SCPs. + /// Initializes the <see cref="Player"/> class to subscribe to <see cref="ReferenceHub"/> events and handle the player cache. /// </summary> - public float MaxHumeShield + [InitializeWrapper] + internal static void Initialize() { - get => ReferenceHub.playerStats.GetModule<HumeShieldStat>().MaxValue; - set => ReferenceHub.playerStats.GetModule<HumeShieldStat>().MaxValue = value; + Dictionary.Clear(); + UserIdCache.Clear(); + + ReferenceHub.OnPlayerAdded += AddPlayer; + ReferenceHub.OnPlayerRemoved += RemovePlayer; } /// <summary> - /// Gets or sets the current regeneration rate of the hume shield per second. - /// Returns -1 if the player's role doesn't have hume shield controller. + /// Creates a new wrapper for the player using the player's <see cref="global::ReferenceHub"/>. /// </summary> - public float HumeShieldRegenRate + /// <param name="referenceHub">The <see cref="global::ReferenceHub"/> of the player.</param> + /// <returns>The created player wrapper.</returns> + private static Player CreatePlayerWrapper(ReferenceHub referenceHub) { - get - { - if (ReferenceHub.roleManager.CurrentRole is not IHumeShieldedRole role) - return -1; + Player player = new(referenceHub); - return role.HumeShieldModule.HsRegeneration; - } - set + if (referenceHub.isLocalPlayer) { - if (ReferenceHub.roleManager.CurrentRole is not IHumeShieldedRole role) - return; - - (role.HumeShieldModule as DynamicHumeShieldController).RegenerationRate = value; + Server.Host = player; } + + return player; } /// <summary> - /// Gets or sets the time that must pass after taking damage for hume shield to regenerate again. - /// Returns -1 if the player's role doesn't have hume shield controller. + /// Handles the creation of a player in the server. /// </summary> - public float HumeShieldRegenCooldown + /// <param name="referenceHub">The reference hub of the player.</param> + private static void AddPlayer(ReferenceHub referenceHub) { - get + try { - if (ReferenceHub.roleManager.CurrentRole is not IHumeShieldedRole role) - return -1; + if (Dictionary.ContainsKey(referenceHub)) + { + return; + } - return (role.HumeShieldModule as DynamicHumeShieldController).RegenerationCooldown; + CreatePlayerWrapper(referenceHub); } - set + catch (Exception ex) { - if (ReferenceHub.roleManager.CurrentRole is not IHumeShieldedRole role) - return; - - (role.HumeShieldModule as DynamicHumeShieldController).RegenerationCooldown = value; + Console.Logger.InternalError($"Failed to handle player addition with exception: {ex}"); } } /// <summary> - /// Gets or sets the player's current gravity. Default value is <see cref="FpcGravityController.DefaultGravity"/>.<br/> - /// If the player's current role is not first person controlled (inherit from <see cref="IFpcRole"/> then <see cref="Vector3.zero"/> is returned.<br/> - /// Y-axis is up and down. Negative values makes the player go down. Positive upwards. Player must not be grounded in order for gravity to take effect. + /// Handles the removal of a player from the server. /// </summary> - public Vector3 Gravity + /// <param name="referenceHub">The reference hub of the player.</param> + private static void RemovePlayer(ReferenceHub referenceHub) { - get + try { - if (ReferenceHub.roleManager.CurrentRole is IFpcRole role) - return role.FpcModule.Motor.GravityController.Gravity; + if (referenceHub.authManager.UserId != null) + { + UserIdCache.Remove(referenceHub.authManager.UserId); + } - return Vector3.zero; + if (TryGet(referenceHub.gameObject, out Player? player)) + { + CustomDataStoreManager.RemovePlayer(player); + } + + if (referenceHub.isLocalPlayer) + { + Server.Host = null; + } + + Dictionary.Remove(referenceHub); } - set + catch (Exception ex) { - if (ReferenceHub.roleManager.CurrentRole is IFpcRole role) - role.FpcModule.Motor.GravityController.Gravity = value; + Console.Logger.InternalError($"Failed to handle player removal with exception: {ex}"); } } /// <summary> - /// Gets a value indicating whether the player has remote admin access. + /// An internal constructor to prevent external instantiation. /// </summary> - public bool RemoteAdminAccess => ReferenceHub.serverRoles.RemoteAdmin; + /// <param name="referenceHub">The reference hub of the player.</param> + internal Player(ReferenceHub referenceHub) + { + Dictionary.Add(referenceHub, this); + + ReferenceHub = referenceHub; + CustomDataStoreManager.AddPlayer(this); + } /// <summary> - /// Gets a value indicating whether the player has Do-Not-Track enabled. + /// The <see cref="ReferenceHub">Reference Hub</see> of the player. /// </summary> - public bool DoNotTrack => ReferenceHub.authManager.DoNotTrack; + public ReferenceHub ReferenceHub { get; } /// <summary> - /// Gets or sets a value indicating whether the player is in overwatch mode. + /// Gets the player's <see cref="GameObject"/>. /// </summary> - public bool IsOverwatchEnabled - { - get => ReferenceHub.serverRoles.IsInOverwatch; - set => ReferenceHub.serverRoles.IsInOverwatch = value; - } + public GameObject GameObject => ReferenceHub.gameObject; /// <summary> - /// Gets the player this player is currently spectating.<br/> - /// Returns null if current player is not spectator or the spectated player is not valid. - /// </summary> - public Player? CurrentlySpectating - { - get - { - if (RoleBase is not SpectatorRole sr) - return null; - - if (!ReferenceHub.TryGetHubNetID(sr.SyncedSpectatedNetId, out ReferenceHub hub)) - return null; - - return Get(hub); - } - } - - /// <summary> - /// Gets a pooled list of players who are currently spectating this player. + /// Gets whether the player is the host or server. /// </summary> - public List<Player> CurrentSpectators - { - get - { - List<Player> list = ListPool<Player>.Shared.Rent(); - foreach (Player player in List) - { - if (ReferenceHub.IsSpectatedBy(player.ReferenceHub)) - list.Add(player); - } - - return list; - } - } + public bool IsHost => ReferenceHub.isLocalPlayer; /// <summary> - /// Gets or sets the player's current <see cref="Item">item</see>. + /// Gets whether the player is the dedicated server. /// </summary> - public Item? CurrentItem - { - get => Item.Get(Inventory.CurInstance); - set - { - if (value == null || value.Type == ItemType.None) - Inventory.ServerSelectItem(0); - else - Inventory.ServerSelectItem(value.Serial); - } - } + [Obsolete($"Use {nameof(IsHost)} instead")] + public bool IsServer => ReferenceHub.isLocalPlayer; /// <summary> - /// Gets the player's currently active <see cref="StatusEffectBase">status effects</see>. + /// Gets whether this <see cref="Player"/> instance is not controlled by a real human being. /// </summary> - public IEnumerable<StatusEffectBase> ActiveEffects => ReferenceHub.playerEffectsController.AllEffects.Where(x => x.Intensity > 0); + /// <remarks> + /// This list includes dummy players. + /// </remarks> + public bool IsNpc => !IsHost && ReferenceHub.connectionToClient.GetType() != typeof(NetworkConnectionToClient); /// <summary> - /// Gets the <see cref="LabApi.Features.Wrappers.Room"/> at the player's current position. - /// May be <see langword="null"/> if the player is in the void. - /// <para> - /// Player inside of the elevator is consider to be in the said room until the elevator teleports to the next door. - /// </para> + /// Gets whether the player is a real player and not the host or an Npc. /// </summary> - public Room? Room => Room.TryGetRoomAtPosition(Position, out Room room) ? room : null; + public bool IsPlayer => Connection.GetType() == typeof(NetworkConnectionToClient); /// <summary> - /// Gets the cached room of the player. Cached room is revalidated once every frame or when player teleports.<br/> - /// It is not guarantee that the <see cref="Position"/> will match the exact same room it should be in due to the caching.<br/> - /// May be <see langword="null"/> if the player is in the void. + /// Gets whether the player is a dummy instance. /// </summary> - public Room? CachedRoom => ReferenceHub.TryGetCurrentRoom(out RoomIdentifier rid) ? Room.Get(rid) : null; + public bool IsDummy => ReferenceHub.authManager.InstanceMode == ClientInstanceMode.Dummy; /// <summary> - /// Gets the <see cref="FacilityZone"/> for the player's current room. Returns <see cref="FacilityZone.None"/> if the room is null. + /// Gets the Player's User ID. /// </summary> - public FacilityZone Zone => Room?.Zone ?? FacilityZone.None; + public string UserId => ReferenceHub.authManager.UserId; /// <summary> - /// Gets the <see cref="Item">items</see> in the player's inventory. + /// Gets the player's Network ID. /// </summary> - public IEnumerable<Item> Items => Inventory.UserInventory.Items.Values.Select(Item.Get)!; + public uint NetworkId => ReferenceHub.characterClassManager.netId; /// <summary> - /// Gets the player's Reserve Ammo. + /// Gets the player's <see cref="NetworkConnection"/>. /// </summary> - public Dictionary<ItemType, ushort> Ammo => Inventory.UserInventory.ReserveAmmo; + public NetworkConnection Connection => IsHost ? ReferenceHub.networkIdentity.connectionToServer : ReferenceHub.networkIdentity.connectionToClient; /// <summary> - /// Gets or sets the player's group color. + /// Gets the player's <see cref="NetworkConnectionToClient"/>. /// </summary> - public string GroupColor - { - get => ReferenceHub.serverRoles.Network_myColor; - set => ReferenceHub.serverRoles.SetColor(value); - } + public NetworkConnectionToClient ConnectionToClient => ReferenceHub.networkIdentity.connectionToClient; /// <summary> - /// Gets or sets what is displayed for the player's group. + /// Gets the player's <see cref="RecyclablePlayerId"/> value. /// </summary> - public string GroupName - { - get => ReferenceHub.serverRoles.Network_myText; - set => ReferenceHub.serverRoles.SetText(value); - } + public int PlayerId => ReferenceHub.PlayerId; /// <summary> - /// Gets or sets the player's <see cref="UserGroup"/>. + /// Gets if the player is currently offline. /// </summary> - public UserGroup? UserGroup - { - get => ReferenceHub.serverRoles.Group; - set => ReferenceHub.serverRoles.SetGroup(value); - } + [Obsolete("Use IsDestroyed instead.")] + public bool IsOffline => GameObject == null; /// <summary> - /// Gets the player's default permission group name. Or null if the player is not in a group. - /// </summary> - public string? PermissionsGroupName => ServerStatic.PermissionsHandler.Members.GetValueOrDefault(UserId); - - /// <summary>s - /// Gets the player's unit ID, or -1 if the role is not a <see cref="HumanRole"/>. + /// Gets if the player is currently online. /// </summary> - public int UnitId => RoleBase is HumanRole humanRole ? humanRole.UnitNameId : -1; + [Obsolete("Use !IsDestroyed instead.")] + public bool IsOnline => !IsOffline; /// <summary> - /// Gets a value indicating whether the player has a reserved slot. + /// Gets if the player is properly connected and authenticated. /// </summary> - public bool HasReservedSlot => ReservedSlot.HasReservedSlot(UserId); + public bool IsReady => ReferenceHub.authManager.InstanceMode != ClientInstanceMode.Unverified && ReferenceHub.nicknameSync.NickSet; /// <summary> - /// Gets the player's velocity. + /// Gets the player's IP address. /// </summary> - public Vector3 Velocity => ReferenceHub.GetVelocity(); + public string IpAddress => ReferenceHub.characterClassManager.connectionToClient.address; /// <summary> - /// Gets the player's <see cref="Inventory"/>. + /// Gets or sets the player's current role. /// </summary> - public Inventory Inventory => ReferenceHub.inventory; + public RoleTypeId Role + { + get => ReferenceHub.GetRoleId(); + set => ReferenceHub.roleManager.ServerSetRole(value, RoleChangeReason.RemoteAdmin); + } /// <summary> - /// Gets the <see cref="VoiceModuleBase"/> for the player, or null if the player does not have a voice module. + /// Gets the player's current <see cref="PlayerRoleBase"/>. /// </summary> - public VoiceModuleBase? VoiceModule => RoleBase is IVoiceRole voiceRole ? voiceRole.VoiceModule : null; + public PlayerRoleBase RoleBase => ReferenceHub.roleManager.CurrentRole; /// <summary> - /// Gets the current <see cref="VoiceChatChannel"/> for the player, or <see cref="VoiceChatChannel.None"/> if the player is not using a voice module. + /// Get's the player's current role unique identifier. /// </summary> - public VoiceChatChannel VoiceChannel => VoiceModule?.CurrentChannel ?? VoiceChatChannel.None; + public int LifeId => RoleBase.UniqueLifeIdentifier; /// <summary> - /// Gets a value indicating whether the player has no items in their inventory. + /// Gets the Player's Nickname. /// </summary> - public bool IsWithoutItems => Inventory.UserInventory.Items.Count == 0; + public string Nickname => ReferenceHub.nicknameSync.MyNick; /// <summary> - /// Gets a value indicating whether the player's inventory is full. + /// Gets or sets the Player's Display Name. /// </summary> - public bool IsInventoryFull => Inventory.UserInventory.Items.Count >= Inventory.MaxSlots; + public string DisplayName + { + get => ReferenceHub.nicknameSync.DisplayName; + set => ReferenceHub.nicknameSync.DisplayName = value; + } /// <summary> - /// Gets a value indicating whether the player is out of ammunition. + /// Gets the log name needed for command senders. /// </summary> - public bool IsOutOfAmmo => Inventory.UserInventory.ReserveAmmo.All(ammo => ammo.Value == 0); + public string LogName => IsHost ? "SERVER CONSOLE" : $"{Nickname} ({UserId})"; /// <summary> - /// Gets or sets a value indicating whether the player is disarmed. + /// Gets or sets the player's custom info.<br/> + /// Do note that custom info is restricted by several things listed in <see cref="ValidateCustomInfo"/>. + /// Please use this method to validate your string as it is validated on the client by the same method. /// </summary> - public bool IsDisarmed + public string CustomInfo { - get => Inventory.IsDisarmed(); - set - { - if (value) - { - Inventory.SetDisarmedStatus(null); - DisarmedPlayers.Entries.Add(new DisarmedPlayers.DisarmedEntry(ReferenceHub.networkIdentity.netId, 0U)); - new DisarmedPlayersListMessage(DisarmedPlayers.Entries).SendToAuthenticated(); - return; - } - - Inventory.SetDisarmedStatus(null); - new DisarmedPlayersListMessage(DisarmedPlayers.Entries).SendToAuthenticated(); - } + get => ReferenceHub.nicknameSync.CustomPlayerInfo; + set => ReferenceHub.nicknameSync.CustomPlayerInfo = value; } /// <summary> - /// Gets a value indicating whether the player is muted. - /// </summary> - public bool IsMuted => VoiceChatMutes.QueryLocalMute(UserId); - - /// <summary> - /// Gets a value indicating whether the player is muted from the intercom. + /// Gets or sets the player's info area flags. + /// Flags determine what info is displayed to other players when they hover their cross-hair over. /// </summary> - public bool IsIntercomMuted => VoiceChatMutes.QueryLocalMute(UserId, true); + public PlayerInfoArea InfoArea + { + get => ReferenceHub.nicknameSync.Network_playerInfoToShow; + set => ReferenceHub.nicknameSync.Network_playerInfoToShow = value; + } /// <summary> - /// Gets a value indicating whether the player is talking through a radio. + /// Gets or sets the player's current health. /// </summary> - public bool IsUsingRadio => PersonalRadioPlayback.IsTransmitting(ReferenceHub); + public float Health + { + get => ReferenceHub.playerStats.GetModule<HealthStat>().CurValue; + set => ReferenceHub.playerStats.GetModule<HealthStat>().CurValue = value; + } /// <summary> - /// Gets a value indicating whether the player is speaking. + /// Gets or sets the player's current maximum health. /// </summary> - public bool IsSpeaking => VoiceModule != null && VoiceModule.IsSpeaking; + public float MaxHealth + { + get => ReferenceHub.playerStats.GetModule<HealthStat>().MaxValue; + set => ReferenceHub.playerStats.GetModule<HealthStat>().MaxValue = value; + } /// <summary> - /// Gets a value indicating whether the player is a Global Moderator. + /// Gets or sets the player's current artificial health.<br/> + /// Setting the value will clear all the current "processes" (each process is responsible for decaying AHP value separately. E.g 2 processes blue candy AHP, which doesn't decay and adrenaline process, where AHP does decay).<br/> + /// Note: This value cannot be greater than <see cref="MaxArtificialHealth"/>. Set it to your desired value first if its over <see cref="AhpStat.DefaultMax"/> and then set this one. /// </summary> - public bool IsGlobalModerator => ReferenceHub.authManager.RemoteAdminGlobalAccess; + public float ArtificialHealth + { + get => ReferenceHub.playerStats.GetModule<AhpStat>().CurValue; + set + { + AhpStat ahp = ReferenceHub.playerStats.GetModule<AhpStat>(); + ahp.ServerKillAllProcesses(); - /// <summary> - /// Gets a value indicating whether the player is a Northwood Staff member. - /// </summary> - public bool IsNorthwoodStaff => ReferenceHub.authManager.NorthwoodStaff; + if (value > 0) + { + ReferenceHub.playerStats.GetModule<AhpStat>().ServerAddProcess(value, MaxArtificialHealth, 0f, 1f, 0f, false); + } + } + } /// <summary> - /// Gets or sets a value indicating whether bypass mode is enabled for the player, allowing them to open doors/gates without keycards. + /// Gets or sets the player's current maximum artificial health or hume shield.<br/> + /// Note: The value resets to <see cref="AhpStat.DefaultMax"/> when the player's AHP reaches 0. /// </summary> - public bool IsBypassEnabled + public float MaxArtificialHealth { - get => ReferenceHub.serverRoles.BypassMode; - set => ReferenceHub.serverRoles.BypassMode = value; + get => ReferenceHub.playerStats.GetModule<AhpStat>().MaxValue; + set => ReferenceHub.playerStats.GetModule<AhpStat>().MaxValue = value; } /// <summary> - /// Gets or sets a value indicating whether god mode is enabled for the player. + /// Gets or sets the player's hume shield current value. /// </summary> - public bool IsGodModeEnabled + public float HumeShield { - get => ReferenceHub.characterClassManager.GodMode; - set => ReferenceHub.characterClassManager.GodMode = value; + get => ReferenceHub.playerStats.GetModule<HumeShieldStat>().CurValue; + set => ReferenceHub.playerStats.GetModule<HumeShieldStat>().CurValue = value; } /// <summary> - /// Gets or sets a value indicating whether noclip mode is enabled for the player. + /// Gets or sets the player's maximum hume shield value. + /// Note: This value may change if the player passes a new hume shield threshold for SCPs. /// </summary> - public bool IsNoclipEnabled + public float MaxHumeShield { - get => ReferenceHub.playerStats.GetModule<AdminFlagsStat>().HasFlag(AdminFlags.Noclip); - set => ReferenceHub.playerStats.GetModule<AdminFlagsStat>().SetFlag(AdminFlags.Noclip, value); + get => ReferenceHub.playerStats.GetModule<HumeShieldStat>().MaxValue; + set => ReferenceHub.playerStats.GetModule<HumeShieldStat>().MaxValue = value; } /// <summary> - /// Gets or sets the player who disarmed this player. + /// Gets or sets the current regeneration rate of the hume shield per second. + /// Returns -1 if the player's role doesn't have hume shield controller. /// </summary> - public Player? DisarmedBy + public float HumeShieldRegenRate { get { - if (!IsDisarmed) return null; - - DisarmedPlayers.DisarmedEntry entry = DisarmedPlayers.Entries.Find(x => x.DisarmedPlayer == NetworkId); + if (ReferenceHub.roleManager.CurrentRole is not IHumeShieldedRole role) + { + return -1; + } - return Get(entry.Disarmer); + return role.HumeShieldModule.HsRegeneration; } + set { - Inventory.SetDisarmedStatus(null); - - if (value == null) + if (ReferenceHub.roleManager.CurrentRole is not IHumeShieldedRole role) + { return; + } - DisarmedPlayers.Entries.Add(new DisarmedPlayers.DisarmedEntry(NetworkId, value.NetworkId)); - new DisarmedPlayersListMessage(DisarmedPlayers.Entries).SendToAuthenticated(); + ((DynamicHumeShieldController)role.HumeShieldModule).RegenerationRate = value; } } /// <summary> - /// Gets the player's current <see cref="Team"/>. + /// Gets or sets the time that must pass after taking damage for hume shield to regenerate again. + /// Returns -1 if the player's role doesn't have hume shield controller. /// </summary> - public Team Team => RoleBase.Team; + public float HumeShieldRegenCooldown + { + get + { + if (ReferenceHub.roleManager.CurrentRole is not IHumeShieldedRole role) + { + return -1; + } - /// <summary> - /// Gets the player's current <see cref="Faction"/>. - /// </summary> - public Faction Faction => Team.GetFaction(); + return ((DynamicHumeShieldController)role.HumeShieldModule).RegenerationCooldown; + } - /// <summary> - /// Gets whether the player is currently Alive. - /// </summary> - public bool IsAlive => Team != Team.Dead; + set + { + if (ReferenceHub.roleManager.CurrentRole is not IHumeShieldedRole role) + { + return; + } - /// <summary> - /// Gets if the player is an SCP. - /// </summary> - public bool IsSCP => Team == Team.SCPs; + ((DynamicHumeShieldController)role.HumeShieldModule).RegenerationCooldown = value; + } + } /// <summary> - /// Gets if the player is a human. + /// Gets or sets the player's current gravity. Default value is <see cref="FpcGravityController.DefaultGravity"/>.<br/> + /// If the player's current role is not first person controlled (inherit from <see cref="IFpcRole"/> then <see cref="Vector3.zero"/> is returned.<br/> + /// Y-axis is up and down. Negative values makes the player go down. Positive upwards. Player must not be grounded in order for gravity to take effect. /// </summary> - public bool IsHuman => IsAlive && !IsSCP; + public Vector3 Gravity + { + get + { + if (ReferenceHub.roleManager.CurrentRole is IFpcRole role) + { + return role.FpcModule.Motor.GravityController.Gravity; + } - /// <summary> - /// Gets if the player is part of the NTF. - /// </summary> - public bool IsNTF => Team == Team.FoundationForces; + return Vector3.zero; + } + + set + { + if (ReferenceHub.roleManager.CurrentRole is IFpcRole role) + { + role.FpcModule.Motor.GravityController.Gravity = value; + } + } + } /// <summary> - /// Gets if the player is part of the Chaos Insurgency. + /// Gets a value indicating whether the player has remote admin access. /// </summary> - public bool IsChaos => Team == Team.ChaosInsurgency; + public bool RemoteAdminAccess => ReferenceHub.serverRoles.RemoteAdmin; /// <summary> - /// Gets if the player is a tutorial. + /// Gets a value indicating whether the player has Do-Not-Track enabled. /// </summary> - public bool IsTutorial => Role == RoleTypeId.Tutorial; + public bool DoNotTrack => ReferenceHub.authManager.DoNotTrack; /// <summary> - /// Gets the player's Camera <see cref="Transform"/>. + /// Gets or sets a value indicating whether the player is in overwatch mode. /// </summary> - public Transform Camera => ReferenceHub.PlayerCameraReference; + public bool IsOverwatchEnabled + { + get => ReferenceHub.serverRoles.IsInOverwatch; + set => ReferenceHub.serverRoles.IsInOverwatch = value; + } /// <summary> - /// Gets or sets the player's position.<br/> - /// Returns <see cref="Vector3.zero"/> if the player's role is not currently derived from <see cref="IFpcRole"/>. + /// Gets the player this player is currently spectating.<br/> + /// Returns null if current player is not spectator or the spectated player is not valid. /// </summary> - public Vector3 Position + public Player? CurrentlySpectating { get { - if (RoleBase is not IFpcRole fpcRole) - return Vector3.zero; + if (RoleBase is not SpectatorRole sr) + { + return null; + } - return fpcRole.FpcModule.Position; - } - set => ReferenceHub.TryOverridePosition(value); - } + if (!ReferenceHub.TryGetHubNetID(sr.SyncedSpectatedNetId, out ReferenceHub hub)) + { + return null; + } - /// <summary> - /// Gets or sets the player's rotation. - /// </summary> - public Quaternion Rotation - { - get => GameObject.transform.rotation; - set => ReferenceHub.TryOverrideRotation(value.eulerAngles); + return Get(hub); + } } /// <summary> - /// Gets or sets the player's look rotation. X is vertical axis while Y is horizontal. Vertical axis is clamped by the base game logic.<br/> - /// Returns <see cref="Vector2.zero"/> if the player's role is not currently derived from <see cref="IFpcRole"/>. + /// Gets a pooled list of players who are currently spectating this player. /// </summary> - public Vector2 LookRotation + public List<Player> CurrentSpectators { get { - if (ReferenceHub.roleManager.CurrentRole is not IFpcRole fpcRole) - return Vector2.zero; + List<Player> list = ListPool<Player>.Shared.Rent(); + foreach (Player player in List) + { + if (ReferenceHub.IsSpectatedBy(player.ReferenceHub)) + { + list.Add(player); + } + } - FpcMouseLook mouseLook = fpcRole.FpcModule.MouseLook; - return new Vector2(mouseLook.CurrentVertical, mouseLook.CurrentHorizontal); + return list; } - set => ReferenceHub.TryOverrideRotation(value); } /// <summary> - /// Gets or sets player's scale. Player's role must be <see cref="IFpcRole"/> for it to take effect.<br/> - /// Vertical scale is not linear as the model's origin and scaling is done from player's feet. + /// Gets or sets the player's current <see cref="Item">item</see>. /// </summary> - public Vector3 Scale + public Item? CurrentItem { - get - { - if (ReferenceHub.roleManager.CurrentRole is not IFpcRole fpcRole) - return Vector3.zero; - - return fpcRole.FpcModule.Motor.ScaleController.Scale; - } + get => Item.Get(Inventory.CurInstance); set { - if (ReferenceHub.roleManager.CurrentRole is not IFpcRole fpcRole) - return; - - fpcRole.FpcModule.Motor.ScaleController.Scale = value; + if (value == null || value.Type == ItemType.None) + { + Inventory.ServerSelectItem(0); + } + else + { + Inventory.ServerSelectItem(value.Serial); + } } } /// <summary> - /// Gets or sets player's remaining stamina (min = 0, max = 1). + /// Gets the player's currently active <see cref="StatusEffectBase">status effects</see>. /// </summary> - public float StaminaRemaining - { - get => ReferenceHub.playerStats.GetModule<StaminaStat>().CurValue; - set => ReferenceHub.playerStats.GetModule<StaminaStat>().CurValue = value; - } + public IEnumerable<StatusEffectBase> ActiveEffects => ReferenceHub.playerEffectsController.AllEffects.Where(x => x.Intensity > 0); /// <summary> - /// Validates the custom info text and returns result whether it is valid or invalid.<br/> - /// Current validation requirements are the following: - /// - /// <list type="bullet"> - /// <item>Match the <see cref="Misc.PlayerCustomInfoRegex"/> regex.</item> - /// <item>Use only color,i,b and size rich text tags.</item> - /// <item>Colors used have to be from <see cref="Misc.AcceptedColours"/></item> - /// </list> - /// + /// Gets the <see cref="LabApi.Features.Wrappers.Room"/> at the player's current position. + /// May be <see langword="null"/> if the player is in the void. + /// <para> + /// Player inside of the elevator is consider to be in the said room until the elevator teleports to the next door. + /// </para> /// </summary> - /// <param name="text">The text to check on.</param> - /// <param name="rejectionReason">Out parameter containing rejection reason.</param> - /// <returns>Whether is the info parameter valid.</returns> - public static bool ValidateCustomInfo(string text, out string rejectionReason) => NicknameSync.ValidateCustomInfo(text, out rejectionReason); + public Room? Room => Room.TryGetRoomAtPosition(Position, out Room? room) ? room : null; /// <summary> - /// Gets a all players matching the criteria specified by the <see cref="PlayerSearchFlags"/>. + /// Gets the cached room of the player. Cached room is revalidated once every frame or when player teleports.<br/> + /// It is not guarantee that the <see cref="Position"/> will match the exact same room it should be in due to the caching.<br/> + /// May be <see langword="null"/> if the player is in the void. /// </summary> - /// <param name="flags">The <see cref="PlayerSearchFlags"/> of the players to include.</param> - /// <returns>The set of players that match the criteria.</returns> - /// <remarks> - /// By default this returns the same set of players as <see cref="ReadyList"/>. - /// </remarks> - public static IEnumerable<Player> GetAll(PlayerSearchFlags flags = PlayerSearchFlags.AuthenticatedAndDummy) - { - bool authenticated = (flags & PlayerSearchFlags.AuthenticatedPlayers) > 0; - bool unauthenticated = (flags & PlayerSearchFlags.UnauthenticatedPlayers) > 0; - bool dummyNpcs = (flags & PlayerSearchFlags.DummyNpcs) > 0; - bool regularNpcs = (flags & PlayerSearchFlags.RegularNpcs) > 0; - bool host = (flags & PlayerSearchFlags.Host) > 0; + public Room? CachedRoom => ReferenceHub.TryGetCurrentRoom(out RoomIdentifier rid) ? Room.Get(rid) : null; - bool includePlayers = authenticated || unauthenticated; - bool allPlayers = authenticated && unauthenticated; - bool includeNpcs = dummyNpcs || regularNpcs; - bool allNpcs = dummyNpcs && regularNpcs; + /// <summary> + /// Gets the <see cref="FacilityZone"/> for the player's current room. Returns <see cref="FacilityZone.None"/> if the room is null. + /// </summary> + public FacilityZone Zone => Room?.Zone ?? FacilityZone.None; - foreach (Player player in List) - { - if ((includePlayers && player.IsPlayer && (allPlayers || player.IsReady == authenticated)) || - (includeNpcs && player.IsNpc) && (allNpcs || player.IsDummy == dummyNpcs) || - (host && player.IsHost)) - yield return player; - } - } + /// <summary> + /// Gets the <see cref="Item">items</see> in the player's inventory. + /// </summary> + public IEnumerable<Item> Items => Inventory.UserInventory.Items.Values.Select(Item.Get)!; - #region Player Getters + /// <summary> + /// Gets the player's Reserve Ammo. + /// </summary> + public Dictionary<ItemType, ushort> Ammo => Inventory.UserInventory.ReserveAmmo; /// <summary> - /// Gets the player wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist. + /// Gets or sets the player's group color. /// </summary> - /// <param name="referenceHub">The reference hub of the player.</param> - /// <returns>The requested player or null if the reference hub is null.</returns> - [return: NotNullIfNotNull(nameof(referenceHub))] - public static Player? Get(ReferenceHub? referenceHub) + public string GroupColor { - if (referenceHub == null) - return null; - - return Dictionary.TryGetValue(referenceHub, out Player player) ? player : CreatePlayerWrapper(referenceHub); + get => ReferenceHub.serverRoles.Network_myColor; + set => ReferenceHub.serverRoles.SetColor(value); } /// <summary> - /// Gets a list of players from a list of reference hubs. + /// Gets or sets what is displayed for the player's group. /// </summary> - /// <param name="referenceHubs">The reference hubs of the players.</param> - /// <returns>A list of players.</returns> - public static List<Player> Get(IEnumerable<ReferenceHub> referenceHubs) + public string GroupName { - // We rent a list from the pool to avoid unnecessary allocations. - // We don't care if the developer forgets to return the list to the pool - // as at least it will be more efficient than always allocating a new list. - List<Player> list = ListPool<Player>.Shared.Rent(); - return GetNonAlloc(referenceHubs, list); + get => ReferenceHub.serverRoles.Network_myText; + set => ReferenceHub.serverRoles.SetText(value); } /// <summary> - /// Gets a list of players from a list of reference hubs without allocating a new list. + /// Gets or sets the player's <see cref="UserGroup"/>. /// </summary> - /// <param name="referenceHubs">The reference hubs of the players.</param> - /// <param name="list">A reference to the list to add the players to.</param> - public static List<Player> GetNonAlloc(IEnumerable<ReferenceHub> referenceHubs, List<Player> list) + public UserGroup? UserGroup { - // We clear the list to avoid any previous data. - list.Clear(); - // And then we add all the players to the list. - list.AddRange(referenceHubs.Select(Get)); - // We finally return the list. - return list; + get => ReferenceHub.serverRoles.Group; + set => ReferenceHub.serverRoles.SetGroup(value); } - #region Get Player from a GameObject + /// <summary> + /// Gets the player's default permission group name. Or null if the player is not in a group. + /// </summary> + public string? PermissionsGroupName => ServerStatic.PermissionsHandler.Members.GetValueOrDefault(UserId); + + /// <summary>s + /// Gets the player's unit ID, or -1 if the role is not a <see cref="HumanRole"/>. + /// </summary> + public int UnitId => RoleBase is HumanRole humanRole ? humanRole.UnitNameId : -1; /// <summary> - /// Gets the <see cref="Player"/> associated with the <see cref="GameObject"/>. + /// Gets a value indicating whether the player has a reserved slot. /// </summary> - /// <param name="gameObject">The <see cref="UnityEngine.GameObject"/> to get the player from.</param> - /// <returns>The <see cref="Player"/> associated with the <see cref="GameObject"/> or null if it doesn't exist.</returns> - public static Player? Get(GameObject? gameObject) => TryGet(gameObject, out Player? player) ? player : null; + public bool HasReservedSlot => ReservedSlot.HasReservedSlot(UserId); /// <summary> - /// Tries to get the <see cref="Player"/> associated with the <see cref="GameObject"/>. + /// Gets the player's velocity. /// </summary> - /// <param name="gameObject">The <see cref="UnityEngine.GameObject"/> to get the player from.</param> - /// <param name="player">The <see cref="Player"/> associated with the <see cref="UnityEngine.GameObject"/> or null if it doesn't exist.</param> - /// <returns>Whether the player was successfully retrieved.</returns> - public static bool TryGet(GameObject? gameObject, [NotNullWhen(true)] out Player? player) - { - player = null; - if (gameObject == null) - return false; + public Vector3 Velocity => ReferenceHub.GetVelocity(); - if (!ReferenceHub.TryGetHub(gameObject, out ReferenceHub? hub)) - return false; + /// <summary> + /// Gets the player's <see cref="Inventory"/>. + /// </summary> + public Inventory Inventory => ReferenceHub.inventory; - player = Get(hub); - return true; - } + /// <summary> + /// Gets the <see cref="VoiceModuleBase"/> for the player, or null if the player does not have a voice module. + /// </summary> + public VoiceModuleBase? VoiceModule => RoleBase is IVoiceRole voiceRole ? voiceRole.VoiceModule : null; - #endregion + /// <summary> + /// Gets the current <see cref="VoiceChatChannel"/> for the player, or <see cref="VoiceChatChannel.None"/> if the player is not using a voice module. + /// </summary> + public VoiceChatChannel VoiceChannel => VoiceModule?.CurrentChannel ?? VoiceChatChannel.None; - #region Get Player from a NetworkIdentity + /// <summary> + /// Gets a value indicating whether the player has no items in their inventory. + /// </summary> + public bool IsWithoutItems => Inventory.UserInventory.Items.Count == 0; /// <summary> - /// Gets the <see cref="Player"/> associated with the <see cref="NetworkIdentity"/>. + /// Gets a value indicating whether the player's inventory is full. /// </summary> - /// <param name="identity">The <see cref="NetworkIdentity"/> to get the player from.</param> - /// <returns>The <see cref="Player"/> associated with the <see cref="NetworkIdentity"/> or null if it doesn't exist.</returns> - public static Player? Get(NetworkIdentity? identity) => TryGet(identity, out Player? player) ? player : null; + public bool IsInventoryFull => Inventory.UserInventory.Items.Count >= Inventory.MaxSlots; /// <summary> - /// Tries to get the <see cref="Player"/> associated with the <see cref="NetworkIdentity"/>. + /// Gets a value indicating whether the player is out of ammunition. /// </summary> - /// <param name="identity">The <see cref="NetworkIdentity"/> to get the player from.</param> - /// <param name="player">The <see cref="Player"/> associated with the <see cref="NetworkIdentity"/> or null if it doesn't exist.</param> - /// <returns>Whether the player was successfully retrieved.</returns> - public static bool TryGet(NetworkIdentity? identity, [NotNullWhen(true)] out Player? player) - { - player = null; - if (identity == null) - return false; + public bool IsOutOfAmmo => Inventory.UserInventory.ReserveAmmo.All(ammo => ammo.Value == 0); - if (!TryGet(identity.netId, out player)) - return false; + /// <summary> + /// Gets or sets a value indicating whether the player is disarmed. + /// </summary> + public bool IsDisarmed + { + get => Inventory.IsDisarmed(); + set + { + if (value) + { + Inventory.SetDisarmedStatus(null); + DisarmedPlayers.Entries.Add(new DisarmedPlayers.DisarmedEntry(ReferenceHub.networkIdentity.netId, 0U)); + new DisarmedPlayersListMessage(DisarmedPlayers.Entries).SendToAuthenticated(); + return; + } - return true; + Inventory.SetDisarmedStatus(null); + new DisarmedPlayersListMessage(DisarmedPlayers.Entries).SendToAuthenticated(); + } } - #endregion + /// <summary> + /// Gets a value indicating whether the player is muted. + /// </summary> + public bool IsMuted => VoiceChatMutes.QueryLocalMute(UserId); - #region Get Player from a NetworkIdentity.netId (uint) + /// <summary> + /// Gets a value indicating whether the player is muted from the intercom. + /// </summary> + public bool IsIntercomMuted => VoiceChatMutes.QueryLocalMute(UserId, true); /// <summary> - /// Gets the <see cref="Player"/> associated with the <see cref="NetworkIdentity.netId"/>. + /// Gets a value indicating whether the player is talking through a radio. /// </summary> - /// <param name="netId">The <see cref="NetworkIdentity.netId"/> to get the player from.</param> - /// <returns>The <see cref="Player"/> associated with the <see cref="NetworkIdentity.netId"/> or null if it doesn't exist.</returns> - public static Player? Get(uint netId) => TryGet(netId, out Player? player) ? player : null; + public bool IsUsingRadio => PersonalRadioPlayback.IsTransmitting(ReferenceHub); /// <summary> - /// Tries to get the <see cref="Player"/> associated with the <see cref="NetworkIdentity.netId"/>. + /// Gets a value indicating whether the player is speaking. /// </summary> - /// <param name="netId">The <see cref="NetworkIdentity.netId"/> to get the player from.</param> - /// <param name="player">The <see cref="Player"/> associated with the <see cref="NetworkIdentity.netId"/> or null if it doesn't exist.</param> - /// <returns>Whether the player was successfully retrieved.</returns> - public static bool TryGet(uint netId, [NotNullWhen(true)] out Player? player) - { - player = null; - if (!ReferenceHub.TryGetHubNetID(netId, out ReferenceHub hub)) - return false; + public bool IsSpeaking => VoiceModule != null && VoiceModule.IsSpeaking; - player = Get(hub); - return true; - } + /// <summary> + /// Gets a value indicating whether the player is a Global Moderator. + /// </summary> + public bool IsGlobalModerator => ReferenceHub.authManager.RemoteAdminGlobalAccess; - #endregion + /// <summary> + /// Gets a value indicating whether the player is a Northwood Staff member. + /// </summary> + public bool IsNorthwoodStaff => ReferenceHub.authManager.NorthwoodStaff; - #region Get Player from a ICommandSender + /// <summary> + /// Gets or sets a value indicating whether bypass mode is enabled for the player, allowing them to open doors/gates without keycards. + /// </summary> + public bool IsBypassEnabled + { + get => ReferenceHub.serverRoles.BypassMode; + set => ReferenceHub.serverRoles.BypassMode = value; + } /// <summary> - /// Gets the <see cref="Player"/> associated with the <see cref="ICommandSender"/>. + /// Gets or sets a value indicating whether god mode is enabled for the player. /// </summary> - /// <param name="sender">The <see cref="ICommandSender"/> to get the player from.</param> - /// <returns>The <see cref="Player"/> associated with the <see cref="ICommandSender"/> or null if it doesn't exist.</returns> - public static Player? Get(ICommandSender? sender) => TryGet(sender, out Player? player) ? player : null; + public bool IsGodModeEnabled + { + get => ReferenceHub.characterClassManager.GodMode; + set => ReferenceHub.characterClassManager.GodMode = value; + } /// <summary> - /// Tries to get the <see cref="Player"/> associated with the <see cref="ICommandSender"/>. + /// Gets or sets a value indicating whether noclip mode is enabled for the player. /// </summary> - /// <param name="sender">The <see cref="ICommandSender"/> to get the player from.</param> - /// <param name="player">The <see cref="Player"/> associated with the <see cref="ICommandSender"/> or null if it doesn't exist.</param> - /// <returns>Whether the player was successfully retrieved.</returns> - public static bool TryGet(ICommandSender? sender, [NotNullWhen(true)] out Player? player) + public bool IsNoclipEnabled { - player = null; + get => ReferenceHub.playerStats.GetModule<AdminFlagsStat>().HasFlag(AdminFlags.Noclip); + set => ReferenceHub.playerStats.GetModule<AdminFlagsStat>().SetFlag(AdminFlags.Noclip, value); + } - if (sender is not CommandSender commandSender) - return false; + /// <summary> + /// Gets or sets the player who disarmed this player. + /// </summary> + public Player? DisarmedBy + { + get + { + if (!IsDisarmed) + { + return null; + } - return TryGet(commandSender.SenderId, out player); + DisarmedPlayers.DisarmedEntry entry = DisarmedPlayers.Entries.Find(x => x.DisarmedPlayer == NetworkId); + + return Get(entry.Disarmer); + } + + set + { + Inventory.SetDisarmedStatus(null); + + if (value == null) + { + return; + } + + DisarmedPlayers.Entries.Add(new DisarmedPlayers.DisarmedEntry(NetworkId, value.NetworkId)); + new DisarmedPlayersListMessage(DisarmedPlayers.Entries).SendToAuthenticated(); + } } - #endregion + /// <summary> + /// Gets the player's current <see cref="Team"/>. + /// </summary> + public Team Team => RoleBase.Team; - #region Get Player from a UserId + /// <summary> + /// Gets the player's current <see cref="Faction"/>. + /// </summary> + public Faction Faction => Team.GetFaction(); + + /// <summary> + /// Gets whether the player is currently Alive. + /// </summary> + public bool IsAlive => Team != Team.Dead; + + /// <summary> + /// Gets if the player is an SCP. + /// </summary> + public bool IsSCP => Team == Team.SCPs; /// <summary> - /// Gets the <see cref="Player"/> associated with the <paramref name="userId"/>. + /// Gets if the player is a human. /// </summary> - /// <param name="userId">The User ID of the player.</param> - /// <returns>The <see cref="Player"/> associated with the <paramref name="userId"/> or null if it doesn't exist.</returns> - public static Player? Get(string? userId) => TryGet(userId, out Player? player) ? player : null; + public bool IsHuman => IsAlive && !IsSCP; /// <summary> - /// Tries to get the <see cref="Player"/> associated with the <paramref name="userId"/>. + /// Gets if the player is part of the NTF. /// </summary> - /// <param name="userId">The user ID of the player.</param> - /// <param name="player">The <see cref="Player"/> associated with the <paramref name="userId"/> or null if it doesn't exist.</param> - /// <returns>Whether the player was successfully retrieved.</returns> - public static bool TryGet(string? userId, [NotNullWhen(true)] out Player? player) - { - player = null; - if (string.IsNullOrEmpty(userId)) - return false; - - if (UserIdCache.TryGetValue(userId!, out player) && player.IsOnline) - return true; - - player = List.FirstOrDefault(x => x.UserId == userId); - if (player == null) - return false; - - UserIdCache[userId!] = player; - return true; - } + public bool IsNTF => Team == Team.FoundationForces; - #endregion + /// <summary> + /// Gets if the player is part of the Chaos Insurgency. + /// </summary> + public bool IsChaos => Team == Team.ChaosInsurgency; - #region Get Player from a Player Id + /// <summary> + /// Gets if the player is a tutorial. + /// </summary> + public bool IsTutorial => Role == RoleTypeId.Tutorial; /// <summary> - /// Gets the <see cref="Player" /> associated with the <paramref name="playerId" />. + /// Gets the player's Camera <see cref="Transform"/>. /// </summary> - /// <param name="playerId">The player ID of the player.</param> - /// <returns>The <see cref="Player" /> associated with the <paramref name="playerId" /> or null if it doesn't exist.</returns> - public static Player? Get(int playerId) => TryGet(playerId, out Player? player) ? player : null; + public Transform Camera => ReferenceHub.PlayerCameraReference; /// <summary> - /// Tries to get the <see cref="Player" /> associated with the <paramref name="playerId" />. + /// Gets or sets the player's position.<br/> + /// Returns <see cref="Vector3.zero"/> if the player's role is not currently derived from <see cref="IFpcRole"/>. /// </summary> - /// <param name="playerId">The player ID of the player.</param> - /// <param name="player">The <see cref="Player" /> associated with the <paramref name="playerId" /> or null if it doesn't exist.</param> - /// <returns>Whether the player was successfully retrieved.</returns> - public static bool TryGet(int playerId, [NotNullWhen(true)] out Player? player) + public Vector3 Position { - player = List.FirstOrDefault(n => n.PlayerId == playerId); - return player != null; - } - - #endregion + get + { + if (RoleBase is not IFpcRole fpcRole) + { + return Vector3.zero; + } - #region Get Player from a Name + return fpcRole.FpcModule.Position; + } + set => ReferenceHub.TryOverridePosition(value); + } /// <summary> - /// Get closest player by lexicographical order. - /// Players are compared by their <see cref="DisplayName"/>. + /// Gets or sets the player's rotation. /// </summary> - /// <param name="input">The input to search the player by.</param> - /// <param name="requireFullMatch">Whether the full match is required.</param> - /// <returns>Player or <see langword="null"/> if no close player found.</returns> - public static Player? GetByDisplayName(string input, bool requireFullMatch = false) => GetByName(input, requireFullMatch, static p => p.DisplayName); + public Quaternion Rotation + { + get => GameObject.transform.rotation; + set => ReferenceHub.TryOverrideRotation(value.eulerAngles); + } /// <summary> - /// Gets the closest player by lexicographical order. - /// Players are compared by their <see cref="Nickname"/>. + /// Gets or sets the player's look rotation. X is vertical axis while Y is horizontal. Vertical axis is clamped by the base game logic.<br/> + /// Returns <see cref="Vector2.zero"/> if the player's role is not currently derived from <see cref="IFpcRole"/>. /// </summary> - /// <param name="input">The input to search the player by.</param> - /// <param name="requireFullMatch">Whether the full match is required.</param> - /// <returns>Player or <see langword="null"/> if no close player found.</returns> - public static Player? GetByNickname(string input, bool requireFullMatch = false) => GetByName(input, requireFullMatch, static p => p.Nickname); + public Vector2 LookRotation + { + get + { + if (ReferenceHub.roleManager.CurrentRole is not IFpcRole fpcRole) + { + return Vector2.zero; + } + + FpcMouseLook mouseLook = fpcRole.FpcModule.MouseLook; + return new Vector2(mouseLook.CurrentVertical, mouseLook.CurrentHorizontal); + } + set => ReferenceHub.TryOverrideRotation(value); + } /// <summary> - /// Gets the closest player by lexicographical order. - /// Base function to allow to select by <see langword="string"/> player property. + /// Gets or sets player's scale. Player's role must be <see cref="IFpcRole"/> for it to take effect.<br/> + /// Vertical scale is not linear as the model's origin and scaling is done from player's feet. /// </summary> - /// <param name="input">The input to search the player by.</param> - /// <param name="requireFullMatch">Whether the full match is required.</param> - /// <param name="propertySelector">Function to select player property.</param> - /// <returns>Player or <see langword="null"/> if no close player found.</returns> - public static Player? GetByName(string input, bool requireFullMatch, Func<Player, string> propertySelector) + public Vector3 Scale { - IOrderedEnumerable<Player> sortedPlayers = List.OrderBy(propertySelector); - - foreach (Player player in sortedPlayers) + get { - string toCheck = propertySelector(player); - if (requireFullMatch) + if (ReferenceHub.roleManager.CurrentRole is not IFpcRole fpcRole) { - if (toCheck.Equals(input, StringComparison.OrdinalIgnoreCase)) - return player; + return Vector3.zero; } - else if (toCheck.StartsWith(input, StringComparison.OrdinalIgnoreCase)) + + return fpcRole.FpcModule.Motor.ScaleController.Scale; + } + + set + { + if (ReferenceHub.roleManager.CurrentRole is not IFpcRole fpcRole) { - return player; + return; } - } - return null; + fpcRole.FpcModule.Motor.ScaleController.Scale = value; + } } /// <summary> - /// Tries to get players by name by seeing if their name starts with the input. + /// Gets or sets player's remaining stamina (min = 0, max = 1). /// </summary> - /// <param name="input">The input to search for.</param> - /// <param name="players">The output players if found.</param> - /// <returns>True if the players are found, false otherwise.</returns> - public static bool TryGetPlayersByName(string input, out List<Player> players) + public float StaminaRemaining { - players = GetNonAlloc(ReferenceHub.AllHubs.Where(x => x.nicknameSync.Network_myNickSync.StartsWith(input, StringComparison.OrdinalIgnoreCase)), - ListPool<Player>.Shared.Rent()); - - return players.Count > 0; + get => ReferenceHub.playerStats.GetModule<StaminaStat>().CurValue; + set => ReferenceHub.playerStats.GetModule<StaminaStat>().CurValue = value; } - #endregion - - #endregion - /// <summary> /// Teleports the player by the delta location. /// </summary> @@ -1161,14 +1300,18 @@ public static bool TryGetPlayersByName(string input, out List<Player> players) public void Jump(float jumpStrength) { if (ReferenceHub.roleManager.CurrentRole is IFpcRole fpcRole) + { fpcRole.FpcModule.Motor.JumpController.ForceJump(jumpStrength); + } } /// <inheritdoc cref="Jump(float)"/> public void Jump() { if (ReferenceHub.roleManager.CurrentRole is IFpcRole fpcRole) + { Jump(fpcRole.FpcModule.JumpSpeed); + } } /// <summary> @@ -1200,9 +1343,13 @@ public void SendBroadcast(string message, ushort duration, Broadcast.BroadcastFl public void Mute(bool isTemporary = true) { if (isTemporary) + { VoiceChatMutes.SetFlags(ReferenceHub, VoiceChatMutes.GetFlags(ReferenceHub) | VcMuteFlags.LocalRegular); + } else + { VoiceChatMutes.IssueLocalMute(UserId); + } } /// <summary> @@ -1212,9 +1359,13 @@ public void Mute(bool isTemporary = true) public void Unmute(bool revokeMute) { if (revokeMute) + { VoiceChatMutes.RevokeLocalMute(UserId); + } else + { VoiceChatMutes.SetFlags(ReferenceHub, VoiceChatMutes.GetFlags(ReferenceHub) & ~VcMuteFlags.LocalRegular); + } } /// <summary> @@ -1224,9 +1375,13 @@ public void Unmute(bool revokeMute) public void IntercomMute(bool isTemporary = false) { if (isTemporary) + { VoiceChatMutes.SetFlags(ReferenceHub, VoiceChatMutes.GetFlags(ReferenceHub) | VcMuteFlags.LocalIntercom); + } else + { VoiceChatMutes.IssueLocalMute(UserId, true); + } } /// <summary> @@ -1236,9 +1391,13 @@ public void IntercomMute(bool isTemporary = false) public void IntercomUnmute(bool revokeMute) { if (revokeMute) + { VoiceChatMutes.RevokeLocalMute(UserId, true); + } else + { VoiceChatMutes.SetFlags(ReferenceHub, VoiceChatMutes.GetFlags(ReferenceHub) & ~VcMuteFlags.LocalIntercom); + } } /// <summary> @@ -1300,11 +1459,15 @@ public void RemoveItem(ItemType item, int maxAmount = 1) { ItemBase? itemBase = Items.ElementAt(i).Base; if (itemBase.ItemTypeId != item) + { continue; + } RemoveItem(itemBase); if (++count >= maxAmount) + { break; + } } } @@ -1337,7 +1500,9 @@ public List<Pickup> DropAllItems() { List<Pickup> items = ListPool<Pickup>.Shared.Rent(); foreach (Item item in Items.ToArray()) + { items.Add(DropItem(item)); + } return items; } @@ -1345,7 +1510,7 @@ public List<Pickup> DropAllItems() /// <summary> /// Sets the ammo amount of a specific ammo type. /// </summary> - /// <param name="item">The type of ammo</param> + /// <param name="item">The type of ammo.</param> /// <param name="amount">The amount of ammo.</param> public void SetAmmo(ItemType item, ushort amount) => Inventory.ServerSetAmmo(item, amount); @@ -1374,7 +1539,9 @@ public List<AmmoPickup> DropAllAmmo() List<AmmoPickup> ammo = ListPool<AmmoPickup>.Shared.Rent(); foreach (KeyValuePair<ItemType, ushort> pair in Ammo.ToDictionary(e => e.Key, e => e.Value)) + { ammo.AddRange(DropAmmo(pair.Key, pair.Value)); + } return ammo; } @@ -1390,7 +1557,9 @@ public List<AmmoPickup> DropAllAmmo() public void ClearItems() { foreach (Item item in Items.ToArray()) + { RemoveItem(item); + } } /// <summary> @@ -1399,7 +1568,9 @@ public void ClearItems() public void ClearAmmo() { if (Ammo.Any(x => x.Value > 0)) + { Inventory.SendAmmoNextFrame = true; + } Ammo.Clear(); } @@ -1412,10 +1583,14 @@ public void ClearAmmo() public void ClearInventory(bool clearAmmo = true, bool clearItems = true) { if (clearAmmo) + { ClearAmmo(); + } if (clearItems) + { ClearItems(); + } } /// <summary> @@ -1425,16 +1600,17 @@ public void ClearInventory(bool clearAmmo = true, bool clearItems = true) public void Heal(float amount) => ReferenceHub.playerStats.GetModule<HealthStat>().ServerHeal(amount); /// <summary> - /// Creates and run a new AHP proccess. + /// Creates and run a new AHP process. /// </summary> /// <param name="amount">Amount of AHP to be added.</param> /// <param name="limit">Adds limit to the AHP.</param> /// <param name="decay">Rate of AHP decay (per second).</param> /// <param name="efficacy">Value between 0 and 1. Defines what % of damage will be absorbed.</param> /// <param name="sustain">Pauses decay for specified amount of seconds.</param> - /// <param name="persistant">If true, it won't be automatically removed when reaches 0.</param> + /// <param name="persistent">If true, it won't be automatically removed when reaches 0.</param> /// <returns>Process in case it needs to be removed. Use <see cref="ServerKillProcess(AhpProcess)"/> to kill it.</returns> - public AhpProcess CreateAhpProcess(float amount, float limit, float decay, float efficacy, float sustain, bool persistant) => ReferenceHub.playerStats.GetModule<AhpStat>().ServerAddProcess(amount, limit, decay, efficacy, sustain, persistant); + public AhpProcess CreateAhpProcess(float amount, float limit, float decay, float efficacy, float sustain, bool persistent) => + ReferenceHub.playerStats.GetModule<AhpStat>().ServerAddProcess(amount, limit, decay, efficacy, sustain, persistent); /// <summary> /// Kills the AHP process. @@ -1478,11 +1654,11 @@ public void SendHint(string text, HintEffect[] effects, float duration = 3f) => /// </summary> /// <param name="text">The text which will be displayed.</param> /// <param name="parameters">The parameters to interpolate into the text.</param> - /// <param name="duration">The duration of which the text will be visible.</param> /// <param name="effects">The effects used for hint animations. See <see cref="HintEffect"/>.</param> + /// <param name="duration">The duration of which the text will be visible.</param> /// <remarks> /// Parameters are interpolated into the string on the client. - /// E.g. <c>"Test param1: {0} param2: {1}"</c> + /// E.g. <c>"Test param1: {0} param2: {1}"</c>. /// </remarks> public void SendHint(string text, HintParameter[] parameters, HintEffect[]? effects = null, float duration = 3f) => ReferenceHub.hints.Show(new TextHint(text, parameters.IsEmpty() ? [new StringHintParameter(string.Empty)] : parameters, effects, duration)); @@ -1531,8 +1707,8 @@ public void DisableEffect<T>() /// Enables a specific <see cref="StatusEffectBase">status effect</see>. /// </summary> /// <typeparam name="T">The type of the status effect to enable.</typeparam> - /// <param name="duration">The duration of the status effect.</param> /// <param name="intensity">The intensity of the status effect.</param> + /// <param name="duration">The duration of the status effect.</param> /// <param name="addDuration">Whether to add the duration to the current duration, if the effect is already active.</param> /// <remarks>A duration of 0 means that it will not expire.</remarks> public void EnableEffect<T>(byte intensity = 1, float duration = 0f, bool addDuration = false) @@ -1542,8 +1718,8 @@ public void EnableEffect<T>(byte intensity = 1, float duration = 0f, bool addDur /// Enables a specific <see cref="StatusEffectBase">status effect</see>. /// </summary> /// <param name="effect">The status effect to enable.</param> - /// <param name="duration">The duration of the status effect.</param> /// <param name="intensity">The intensity of the status effect.</param> + /// <param name="duration">The duration of the status effect.</param> /// <param name="addDuration">Whether to add the duration to the current duration, if the effect is already active.</param> /// <remarks>A duration of 0 means that it will not expire.</remarks> public void EnableEffect(StatusEffectBase? effect, byte intensity = 1, float duration = 0f, bool addDuration = false) => effect?.ServerSetState(intensity, duration, addDuration); @@ -1553,7 +1729,7 @@ public void EnableEffect<T>(byte intensity = 1, float duration = 0f, bool addDur /// </summary> /// <typeparam name="T">The specified effect that will be looked for.</typeparam> /// <param name="effect">The found player effect.</param> - /// <returns>Whether the <see cref="StatusEffectBase">status effect</see> was successfully retrieved. (And was cast successfully)</returns> + /// <returns>Whether the <see cref="StatusEffectBase">status effect</see> was successfully retrieved (And was cast successfully).</returns> public bool TryGetEffect<T>([NotNullWhen(true)] out T? effect) where T : StatusEffectBase => ReferenceHub.playerEffectsController.TryGetEffect(out effect) && effect != null; @@ -1596,8 +1772,8 @@ public void Reconnect(float delay = 3f, bool isFastRestart = false) => /// <summary> /// Kills the player. /// </summary> - /// <param name="reason">The reason for the kill</param> - /// <param name="cassieAnnouncement">The cassie announcement to make upon death.</param> + /// <param name="reason">The reason for the kill.</param> + /// <param name="cassieAnnouncement">The CASSIE announcement to make upon death.</param> /// <returns>Whether the player was successfully killed.</returns> public bool Kill(string reason, string cassieAnnouncement = "") => Damage(new CustomReasonDamageHandler(reason, StandardDamageHandler.KillValue, cassieAnnouncement)); @@ -1606,7 +1782,7 @@ public void Reconnect(float delay = 3f, bool isFastRestart = false) => /// </summary> /// <param name="amount">The amount of damage.</param> /// <param name="reason">The reason of damage.</param> - /// <param name="cassieAnnouncement">The cassie announcement send after death.</param> + /// <param name="cassieAnnouncement">The CASSIE announcement send after death.</param> /// <returns>Whether the player was successfully damaged.</returns> public bool Damage(float amount, string reason, string cassieAnnouncement = "") => Damage(new CustomReasonDamageHandler(reason, amount, cassieAnnouncement)); @@ -1614,7 +1790,7 @@ public void Reconnect(float delay = 3f, bool isFastRestart = false) => /// Damages player with explosion force. /// </summary> /// <param name="amount">The amount of damage.</param> - /// <param name="attacker">The player which attacked</param> + /// <param name="attacker">The player which attacked.</param> /// <param name="force">The force of explosion.</param> /// <param name="armorPenetration">The amount of armor penetration.</param> /// <returns>Whether the player was successfully damaged.</returns> @@ -1677,65 +1853,6 @@ public TStore GetDataStore<TStore>() /// <inheritdoc /> public override string ToString() { - return $"[Player: DisplayName={DisplayName}, PlayerId={PlayerId}, NetworkId={NetworkId}, UserId={UserId}, IpAddress={IpAddress}, Role={Role}, IsServer={IsServer}, IsReady={IsReady}]"; - } - - /// <summary> - /// Creates a new wrapper for the player using the player's <see cref="global::ReferenceHub"/>. - /// </summary> - /// <param name="referenceHub">The <see cref="global::ReferenceHub"/> of the player.</param> - /// <returns>The created player wrapper.</returns> - private static Player CreatePlayerWrapper(ReferenceHub referenceHub) - { - Player player = new(referenceHub); - - if (referenceHub.isLocalPlayer) - Server.Host = player; - - return player; - } - - /// <summary> - /// Handles the creation of a player in the server. - /// </summary> - /// <param name="referenceHub">The reference hub of the player.</param> - private static void AddPlayer(ReferenceHub referenceHub) - { - try - { - if (Dictionary.ContainsKey(referenceHub)) - return; - - CreatePlayerWrapper(referenceHub); - } - catch (Exception ex) - { - Console.Logger.InternalError($"Failed to handle player addition with exception: {ex}"); - } - } - - /// <summary> - /// Handles the removal of a player from the server. - /// </summary> - /// <param name="referenceHub">The reference hub of the player.</param> - private static void RemovePlayer(ReferenceHub referenceHub) - { - try - { - if (referenceHub.authManager.UserId != null) - UserIdCache.Remove(referenceHub.authManager.UserId); - - if (TryGet(referenceHub.gameObject, out Player? player)) - CustomDataStoreManager.RemovePlayer(player); - - if (referenceHub.isLocalPlayer) - Server.Host = null; - - Dictionary.Remove(referenceHub); - } - catch (Exception ex) - { - Console.Logger.InternalError($"Failed to handle player removal with exception: {ex}"); - } + return $"[Player: DisplayName={DisplayName}, PlayerId={PlayerId}, NetworkId={NetworkId}, UserId={UserId}, IpAddress={IpAddress}, Role={Role}, IsHost={IsHost}, IsReady={IsReady}]"; } } From 789cd1e973bcd9717edf42651e04649b5471a4d9 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:47:23 +0930 Subject: [PATCH 134/215] ragdoll --- LabApi/Features/Wrappers/Players/Ragdoll.cs | 124 ++++++++++---------- 1 file changed, 64 insertions(+), 60 deletions(-) diff --git a/LabApi/Features/Wrappers/Players/Ragdoll.cs b/LabApi/Features/Wrappers/Players/Ragdoll.cs index 12f39027..194d594b 100644 --- a/LabApi/Features/Wrappers/Players/Ragdoll.cs +++ b/LabApi/Features/Wrappers/Players/Ragdoll.cs @@ -25,6 +25,61 @@ public class Ragdoll /// </summary> public static IReadOnlyCollection<Ragdoll> List => Dictionary.Values; + /// <summary> + /// Spawns a new ragdoll based on a specified player and damage handler. + /// </summary> + /// <param name="player">Player for ragdoll template.</param> + /// <param name="handler">Handler that is shown as a death cause.</param> + /// <returns>New ragdoll.</returns> + public static Ragdoll? SpawnRagdoll(Player player, DamageHandlerBase handler) => SpawnRagdoll(player.Role, player.Position, player.Rotation, handler, player.DisplayName); + + /// <summary> + /// Attempts to spawn a ragdoll from specified role. Ragdoll is not created if specified role doesn't have any ragdoll model available. + /// </summary> + /// <param name="role">Target role type.</param> + /// <param name="position">Spawn position.</param> + /// <param name="rotation">Spawn rotation.</param> + /// <param name="handler">Damage handler of the death cause.</param> + /// <param name="nickname">Nickname that is visible when hovering over.</param> + /// <param name="scale">Spawn scale. Converted to base ragdoll scale if <see langword="null"/>.</param> + /// <returns>Ragdoll object or <see langword="null"/>.</returns> + public static Ragdoll? SpawnRagdoll(RoleTypeId role, Vector3 position, Quaternion rotation, DamageHandlerBase handler, string nickname, Vector3? scale = null) + { + BasicRagdoll ragdoll = RagdollManager.ServerCreateRagdoll(role, position, rotation, handler, nickname, scale); + return ragdoll == null ? null : Get(ragdoll); + } + + /// <summary> + /// Gets the ragdoll wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist. + /// </summary> + /// <param name="ragdoll">The ragdoll.</param> + /// <returns>The requested ragdoll.</returns> + public static Ragdoll Get(BasicRagdoll ragdoll) => Dictionary.TryGetValue(ragdoll, out Ragdoll rag) ? rag : new Ragdoll(ragdoll); + + /// <summary> + /// Initializes the <see cref="Ragdoll"/> class to subscribe to <see cref="RagdollManager"/> events and handle the ragdoll caching. + /// </summary> + [InitializeWrapper] + internal static void Initialize() + { + Dictionary.Clear(); + + RagdollManager.OnRagdollSpawned += RagdollSpawned; + RagdollManager.OnRagdollRemoved += RagdollRemoved; + } + + /// <summary> + /// Event method for <see cref="RagdollManager.OnRagdollSpawned"/>. + /// </summary> + /// <param name="ragdoll">New ragdoll.</param> + private static void RagdollSpawned(BasicRagdoll ragdoll) => _ = new Ragdoll(ragdoll).Base; + + /// <summary> + /// Event method for <see cref="RagdollManager.OnRagdollRemoved"/>. + /// </summary> + /// <param name="ragdoll">Destroyed ragdoll.</param> + private static void RagdollRemoved(BasicRagdoll ragdoll) => Dictionary.Remove(ragdoll); + /// <summary> /// A private constructor to prevent external instantiation. /// </summary> @@ -34,7 +89,9 @@ private Ragdoll(BasicRagdoll ragdoll) Base = ragdoll; if (CanCache) + { Dictionary.TryAdd(ragdoll, this); + } } /// <summary> @@ -69,7 +126,7 @@ public string Nickname /// <summary> /// Gets or sets the ragdoll damage handler, providing death cause. /// </summary> - //TODO: Damage handler wrapper + // TODO: Damage handler wrapper public DamageHandlerBase DamageHandler { get => Base.NetworkInfo.Handler; @@ -104,7 +161,7 @@ public Quaternion Rotation /// <summary> /// Gets or sets the ragdoll's scale. - /// Scale is set relative to the ragdoll's gameobject size. + /// Scale is set relative to the ragdoll's gameObject size. /// </summary> public Vector3 Scale { @@ -139,19 +196,22 @@ public bool IsConsumed /// </summary> protected bool CanCache => !IsDestroyed && Base.isActiveAndEnabled; - /// <summary> /// Gets whether the ragdoll is revivable by SCP-049 player. /// </summary> - /// <param name="scp049">Player who is SCP-049</param> + /// <param name="scp049">Player who is SCP-049.</param> /// <returns>True if corpse is revivable. False if it isn't or specified player is not SCP-049.</returns> public bool IsRevivableBy(Player scp049) { if (scp049.RoleBase is not Scp049Role role) + { return false; + } if (!role.SubroutineModule.TryGetSubroutine(out Scp049ResurrectAbility ability)) + { return false; + } return ability.CheckRagdoll(Base); } @@ -196,60 +256,4 @@ public override string ToString() { return $"[Ragdoll: Nickname={Nickname}, Role={Role}, DamageHandler={DamageHandler}, Position={Position}, Rotation={Rotation}, Scale={Scale}, IsConsumed={IsConsumed}]"; } - - /// <summary> - /// Spawns a new ragdoll based on a specified player and damage handler. - /// </summary> - /// <param name="player">Player for ragdoll template.</param> - /// <param name="handler">Handler that is shown as a death cause.</param> - /// <returns>New ragdoll.</returns> - public static Ragdoll? SpawnRagdoll(Player player, DamageHandlerBase handler) => SpawnRagdoll(player.Role, player.Position, player.Rotation, handler, player.DisplayName); - - /// <summary> - /// Attempts to spawn a ragdoll from specified role. Ragdoll is not created if specified role doesn't have any ragdoll model available. - /// </summary> - /// <param name="role">Target role type.</param> - /// <param name="position">Spawn position.</param> - /// <param name="rotation">Spawn rotation.</param> - /// <param name="scale">Spawn scale. Converted to base ragdoll scale if <see langword="null"/>.</param> - /// <param name="handler">Damage handler of the death cause.</param> - /// <param name="nickname">Nickname that is visible when hovering over.</param> - /// <returns>Ragdoll object or <see langword="null"/>.</returns> - public static Ragdoll? SpawnRagdoll(RoleTypeId role, Vector3 position, Quaternion rotation, DamageHandlerBase handler, string nickname, Vector3? scale = null) - { - BasicRagdoll ragdoll = RagdollManager.ServerCreateRagdoll(role, position, rotation, handler, nickname, scale); - return ragdoll == null ? null : Get(ragdoll); - } - - /// <summary> - /// Initializes the <see cref="Ragdoll"/> class to subscribe to <see cref="RagdollManager"/> events and handle the ragdoll caching. - /// </summary> - [InitializeWrapper] - internal static void Initialize() - { - Dictionary.Clear(); - - RagdollManager.OnRagdollSpawned += RagdollSpawned; - RagdollManager.OnRagdollRemoved += RagdollRemoved; - } - - /// <summary> - /// Event method for <see cref="RagdollManager.OnRagdollSpawned"/>. - /// </summary> - /// <param name="ragdoll">New ragdoll.</param> - private static void RagdollSpawned(BasicRagdoll ragdoll) => _ = new Ragdoll(ragdoll).Base; - - /// <summary> - /// Event method for <see cref="RagdollManager.OnRagdollRemoved"/>. - /// </summary> - /// <param name="ragdoll">Destroyed ragdoll.</param> - private static void RagdollRemoved(BasicRagdoll ragdoll) => Dictionary.Remove(ragdoll); - - /// <summary> - /// Gets the ragdoll wrapper from the <see cref="Dictionary"/>, or creates a new one if it doesn't exist. - /// </summary> - /// <param name="ragdoll">The ragdoll.</param> - /// <returns>The requested ragdoll.</returns> - public static Ragdoll Get(BasicRagdoll ragdoll) => Dictionary.TryGetValue(ragdoll, out Ragdoll rag) ? rag : new Ragdoll(ragdoll); - } \ No newline at end of file From d02b9fa860fe2ecf511fe6d670fb492a2fa6ed7e Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:47:26 +0930 Subject: [PATCH 135/215] server --- LabApi/Features/Wrappers/Players/Server.cs | 80 +++++++++++++++------- 1 file changed, 56 insertions(+), 24 deletions(-) diff --git a/LabApi/Features/Wrappers/Players/Server.cs b/LabApi/Features/Wrappers/Players/Server.cs index dcc686c4..9a3d69c6 100644 --- a/LabApi/Features/Wrappers/Players/Server.cs +++ b/LabApi/Features/Wrappers/Players/Server.cs @@ -120,7 +120,9 @@ public static bool FriendlyFire set { if (FriendlyFire == value) + { return; + } ServerConsole.FriendlyFire = value; ServerConfigSynchronizer.Singleton.RefreshMainBools(); @@ -137,7 +139,9 @@ public static bool AchievementsEnabled set { if (AchievementManager.AchievementsDisabled != value) + { return; + } AchievementManager.AchievementsDisabled = !value; ServerConfigSynchronizer.Singleton.RefreshMainBools(); @@ -157,7 +161,7 @@ public static string ServerListName /// <summary> /// Gets or sets the server name as seen on the player list. /// </summary> - // TODO: maybe move to a playerlist wrapper? + // TODO: maybe move to a player list wrapper? public static string PlayerListName { get => PlayerList.Title.Value; @@ -167,7 +171,7 @@ public static string PlayerListName /// <summary> /// Gets or sets the refresh rate for the player list name. /// </summary> - // TODO: maybe move to a playerlist wrapper? + // TODO: maybe move to a player list wrapper? public static float PlayerListNameRefreshRate { get => PlayerList.RefreshRate.Value; @@ -178,7 +182,7 @@ public static float PlayerListNameRefreshRate /// Gets or sets whether the server has been marked as transparently modded.<br/> /// For this status to be applied automatically, all installed plugins must have their /// <see cref="LabApi.Loader.Features.Plugins.Plugin.IsTransparent"/> property set to <see langword="true"/>.<br/> - /// For more information, see article 5.2 in the official documentation: https://scpslgame.com/csg + /// For more information, see article 5.2 in the official documentation: https://scpslgame.com/csg. /// </summary> public static bool IsTransparentlyModded { get; internal set; } @@ -277,17 +281,21 @@ public static bool BanUserId(string userId, string reason, long duration, string public static bool BanUserId(string userId, Player? issuer, string reason, long duration, string bannedPlayerNickname = "UnknownName") { if (string.IsNullOrEmpty(userId) || string.IsNullOrEmpty(reason) || issuer == null) + { return false; + } - return IssueBan(new BanDetails() - { - Id = userId, - IssuanceTime = TimeBehaviour.CurrentTimestamp(), - Expires = TimeBehaviour.GetBanExpirationTime((uint)duration), - Issuer = issuer.LogName, - OriginalName = bannedPlayerNickname, - Reason = reason, - }, BanType.UserId); + return IssueBan( + new BanDetails() + { + Id = userId, + IssuanceTime = TimeBehaviour.CurrentTimestamp(), + Expires = TimeBehaviour.GetBanExpirationTime((uint)duration), + Issuer = issuer.LogName, + OriginalName = bannedPlayerNickname, + Reason = reason, + }, + BanType.UserId); } /// <summary> @@ -313,17 +321,21 @@ public static bool BanIpAddress(string ipAddress, string reason, long duration, public static bool BanIpAddress(string ipAddress, Player? issuer, string reason, long duration, string bannedPlayerNickname = "UnknownName") { if (string.IsNullOrEmpty(ipAddress) || string.IsNullOrEmpty(reason) || issuer == null) + { return false; + } - return IssueBan(new BanDetails() - { - Id = ipAddress, - IssuanceTime = TimeBehaviour.CurrentTimestamp(), - Expires = TimeBehaviour.GetBanExpirationTime((uint)duration), - Issuer = issuer.LogName, - OriginalName = bannedPlayerNickname, - Reason = reason, - }, BanType.IP); + return IssueBan( + new BanDetails() + { + Id = ipAddress, + IssuanceTime = TimeBehaviour.CurrentTimestamp(), + Expires = TimeBehaviour.GetBanExpirationTime((uint)duration), + Issuer = issuer.LogName, + OriginalName = bannedPlayerNickname, + Reason = reason, + }, + BanType.IP); } /// <summary> @@ -334,7 +346,9 @@ public static bool BanIpAddress(string ipAddress, Player? issuer, string reason, public static bool UnbanUserId(string userId) { if (string.IsNullOrEmpty(userId) || !IsPlayerBanned(userId)) + { return false; + } RemoveBan(userId, BanType.UserId); return true; @@ -348,7 +362,9 @@ public static bool UnbanUserId(string userId) public static bool UnbanIpAddress(string ipAddress) { if (string.IsNullOrEmpty(ipAddress) || !IsPlayerBanned(ipAddress)) + { return false; + } RemoveBan(ipAddress, BanType.IP); return true; @@ -362,7 +378,9 @@ public static bool UnbanIpAddress(string ipAddress) public static bool IsPlayerBanned(string value) { if (string.IsNullOrEmpty(value)) + { return false; + } return (value.Contains("@") ? GetBan(value, BanType.UserId) : GetBan(value, BanType.IP)) != null; } @@ -396,6 +414,7 @@ public static List<BanDetails> GetAllBannedPlayers() /// <summary> /// Restarts the server and reconnects all players to target server port. /// </summary> + /// <param name="redirectPort">The port number of the server to send all the players too.</param> public static void Restart(ushort redirectPort) { NetworkServer.SendToAll(new RoundRestartMessage(RoundRestartType.RedirectRestart, 0.1f, redirectPort, true, false)); @@ -410,6 +429,7 @@ public static void Restart(ushort redirectPort) /// <summary> /// Shutdowns the server and reconnects all players to target server port. /// </summary> + /// <param name="redirectPort">The port number of the server to send all the players too.</param> public static void Shutdown(ushort redirectPort) { NetworkServer.SendToAll(new RoundRestartMessage(RoundRestartType.RedirectRestart, 0.1f, redirectPort, true, false)); @@ -421,6 +441,7 @@ public static void Shutdown(ushort redirectPort) /// </summary> /// <param name="command">The command name.</param> /// <param name="sender">The <see cref="CommandSender"/> running the command.</param> + /// <returns>The commands response.</returns> public static string RunCommand(string command, CommandSender? sender = null) => ServerConsole.EnterCommand(command, sender); @@ -434,7 +455,9 @@ public static string RunCommand(string command, CommandSender? sender = null) => public static void SendBroadcast(string message, ushort duration, Broadcast.BroadcastFlags type = Broadcast.BroadcastFlags.Normal, bool shouldClearPrevious = false) { if (shouldClearPrevious) + { ClearBroadcasts(); + } Broadcast.Singleton.RpcAddElement(message, duration, type); } @@ -450,7 +473,9 @@ public static void SendBroadcast(string message, ushort duration, Broadcast.Broa public static void SendBroadcast(Player player, string message, ushort duration, Broadcast.BroadcastFlags type = Broadcast.BroadcastFlags.Normal, bool shouldClearPrevious = false) { if (shouldClearPrevious) + { ClearBroadcasts(player); + } Broadcast.Singleton.TargetAddElement(player.Connection, message, duration, type); } @@ -472,11 +497,13 @@ public static void SendAdminChatMessage(IEnumerable<Player> targetPlayers, strin { StringBuilder sb = StringBuilderPool.Shared.Rent(); - sb.Append(Host.NetworkId); + sb.Append(Host!.NetworkId); sb.Append('!'); if (isSilent) + { sb.Append("@@"); + } sb.Append(message); @@ -484,7 +511,9 @@ public static void SendAdminChatMessage(IEnumerable<Player> targetPlayers, strin foreach (Player player in targetPlayers) { if (!player.IsPlayer || !player.IsReady) + { continue; + } player.ReferenceHub.encryptedChannelManager.TrySendMessageToClient(toSend, EncryptedChannelManager.EncryptedChannel.AdminChat); } @@ -522,7 +551,7 @@ TValue this[TKey index] } /// <summary> - /// Private implementation class for synchronizing ItemCategory limits + /// Private implementation class for synchronizing ItemCategory limits. /// </summary> private class CategoryLimitsSynchronizer : ILimit<ItemCategory, sbyte> { @@ -533,7 +562,9 @@ public sbyte this[ItemCategory category] set { if (!InventoryLimits.StandardCategoryLimits.ContainsKey(category)) + { throw new IndexOutOfRangeException($"Index {category} was not a valid ItemCategory type"); + } InventoryLimits.StandardCategoryLimits[category] = value; ServerConfigSynchronizer.Singleton.RefreshCategoryLimits(); @@ -553,7 +584,9 @@ public ushort this[ItemType ammo] set { if (!InventoryLimits.StandardAmmoLimits.ContainsKey(ammo)) + { throw new IndexOutOfRangeException($"Index {ammo} was not a valid Ammo type"); + } InventoryLimits.StandardAmmoLimits[ammo] = value; ServerConfigSynchronizer.Singleton.RefreshAmmoLimits(); @@ -561,4 +594,3 @@ public ushort this[ItemType ammo] } } } - From 4a10d84e5bd1d5736461d7b72a99578192542af8 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Mon, 11 Aug 2025 22:47:42 +0930 Subject: [PATCH 136/215] misc --- LabApi/Features/LabApiProperties.cs | 2 + .../Features/Wrappers/Server/ReservedSlots.cs | 7 +- LabApi/Features/Wrappers/Server/Whitelist.cs | 8 +- LabApi/Loader/CommandLoader.cs | 41 ++++++---- LabApi/Loader/ConfigurationLoader.cs | 16 +++- .../Features/Commands/LabApiParentCommand.cs | 4 +- .../Commands/Reload/ConfigsCommand.cs | 4 +- .../Commands/Reload/ReloadParentCommand.cs | 5 +- .../Features/Configuration/LabApiConfig.cs | 8 +- LabApi/Loader/Features/Misc/AssemblyUtils.cs | 12 ++- .../Features/Plugins/Enums/LoadPriority.cs | 2 +- LabApi/Loader/Features/Plugins/Plugin.cs | 10 ++- .../{PluginTConfig.cs => Plugin{TConfig}.cs} | 0 .../CustomColor32Converter.cs | 7 +- .../CustomConverters/CustomColorConverter.cs | 10 ++- .../CustomQuaternionConverter.cs | 17 +++-- .../CustomConverters/CustomVectorConverter.cs | 11 ++- .../Yaml/Extensions/YamlMappingExtensions.cs | 4 +- .../Loader/Features/Yaml/YamlConfigParser.cs | 6 +- LabApi/Loader/PluginLoader.cs | 76 ++++++++++++------- 20 files changed, 169 insertions(+), 81 deletions(-) rename LabApi/Loader/Features/Plugins/{PluginTConfig.cs => Plugin{TConfig}.cs} (100%) diff --git a/LabApi/Features/LabApiProperties.cs b/LabApi/Features/LabApiProperties.cs index b35c6abd..3c7f1895 100644 --- a/LabApi/Features/LabApiProperties.cs +++ b/LabApi/Features/LabApiProperties.cs @@ -29,7 +29,9 @@ private static string GetCompiledVersion() AssemblyInformationalVersionAttribute att = assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>(); if (att == null) + { return defaultVersion; + } string version = att.InformationalVersion ?? defaultVersion; int index = version.IndexOf('+'); diff --git a/LabApi/Features/Wrappers/Server/ReservedSlots.cs b/LabApi/Features/Wrappers/Server/ReservedSlots.cs index 750a9393..fc5ef40e 100644 --- a/LabApi/Features/Wrappers/Server/ReservedSlots.cs +++ b/LabApi/Features/Wrappers/Server/ReservedSlots.cs @@ -39,11 +39,13 @@ public static class ReservedSlots /// <summary> /// Gives the player a reserved slot and saves it to file. /// </summary> - /// <param name="userId">The userid.</param> + /// <param name="userId">The user id.</param> public static void Add(string userId) { if (HasReservedSlot(userId)) + { return; + } List<string> lines = FileManager.ReadAllLinesList(FilePath); lines.Add(userId); @@ -65,7 +67,9 @@ public static void Add(string userId) public static bool Remove(string userId) { if (!HasReservedSlot(userId)) + { return false; + } List<string> lines = FileManager.ReadAllLinesList(FilePath); @@ -84,4 +88,3 @@ public static bool Remove(string userId) /// <returns>Whether the player was found and removed from the reserved slots.</returns> public static bool Remove(Player player) => Remove(player.UserId); } - diff --git a/LabApi/Features/Wrappers/Server/Whitelist.cs b/LabApi/Features/Wrappers/Server/Whitelist.cs index e85bbe17..fcd5078d 100644 --- a/LabApi/Features/Wrappers/Server/Whitelist.cs +++ b/LabApi/Features/Wrappers/Server/Whitelist.cs @@ -41,7 +41,7 @@ public static bool WhitelistEnabled public static bool IsOnWhitelist(string userId) => WhiteList.IsOnWhitelist(userId); /// <summary> - /// Chhecks if the player is allowed on the server if the whitelist is enabled. + /// Checks if the player is allowed on the server if the whitelist is enabled. /// </summary> /// <param name="userId">The user id of the player.</param> /// <returns>Whether the player is whitelisted. Will always return true if whitelist is disabled.</returns> @@ -55,11 +55,13 @@ public static bool WhitelistEnabled /// <summary> /// Adds player to whitelist and saves it to file. /// </summary> - /// <param name="userId">The userid.</param> + /// <param name="userId">The user id.</param> public static void Add(string userId) { if (IsOnWhitelist(userId)) + { return; + } List<string> lines = FileManager.ReadAllLinesList(FilePath); lines.Add(userId); @@ -81,7 +83,9 @@ public static void Add(string userId) public static bool Remove(string userId) { if (!IsOnWhitelist(userId)) + { return false; + } List<string> lines = FileManager.ReadAllLinesList(FilePath); diff --git a/LabApi/Loader/CommandLoader.cs b/LabApi/Loader/CommandLoader.cs index e9bbe8b4..4bcf35b1 100644 --- a/LabApi/Loader/CommandLoader.cs +++ b/LabApi/Loader/CommandLoader.cs @@ -31,7 +31,7 @@ public static class CommandLoader [typeof(RemoteAdminCommandHandler)] = CommandProcessor.RemoteAdminCommandHandler, // The client console command handler. - [typeof(ClientCommandHandler)] = QueryProcessor.DotCommandHandler + [typeof(ClientCommandHandler)] = QueryProcessor.DotCommandHandler, }; /// <summary> @@ -44,16 +44,6 @@ public static class CommandLoader /// </summary> public static IEnumerable<ICommand>? LabApiCommands { get; private set; } - /// <summary> - /// Registers all commands in the LabAPI solution. - /// </summary> - internal static void RegisterCommands() - { - // We register all commands in the LabAPI assembly. - // We convert it to an array since IEnumerable are lazy and need to be iterated through to be executed. - LabApiCommands = RegisterCommands(Assembly.GetExecutingAssembly(), "LabApi").ToArray(); - } - /// <summary> /// Registers all commands in the given <see cref="Plugin"/>. /// </summary> @@ -80,6 +70,7 @@ public static void RegisterCommands(this Plugin plugin) /// </summary> /// <param name="assembly">The <see cref="Assembly"/> to register the commands from.</param> /// <param name="logName">The name of the plugin to log to use when logging errors.</param> + /// <returns>An enumeration of all registered commands.</returns> public static IEnumerable<ICommand> RegisterCommands(Assembly assembly, string logName = "") { // We use reflection to get all types in the assembly. @@ -107,14 +98,18 @@ public static IEnumerable<ICommand> RegisterCommands(Type type, string logName = { // We check if the type implements the ICommand interface. if (!typeof(ICommand).IsAssignableFrom(type)) + { yield break; + } // We iterate through all custom attributes of the type. foreach (CustomAttributeData attributeData in type.GetCustomAttributesData()) { // If the attribute type is not a CommandHandlerAttribute, we continue. if (attributeData.AttributeType != typeof(CommandHandlerAttribute)) + { continue; + } // We retrieve the command handler type from the attribute data. Type commandHandlerType = (Type)attributeData.ConstructorArguments[0].Value; @@ -132,7 +127,9 @@ public static IEnumerable<ICommand> RegisterCommands(Type type, string logName = // And we finally register the command. if (!TryRegisterCommand(type, commandHandlerType, out ICommand? command, logName)) + { continue; + } // We add the command to the list of registered commands. yield return command; @@ -144,8 +141,9 @@ public static IEnumerable<ICommand> RegisterCommands(Type type, string logName = /// </summary> /// <param name="commandType">The <see cref="Type"/> of the command to register.</param> /// <param name="commandHandlerType">The <see cref="Type"/> of the command handler to register the command to.</param> - /// <param name="logName">The name of the plugin to log to use when logging errors.</param> /// <param name="command">The registered command if the command was successfully registered.</param> + /// <param name="logName">The name of the plugin to log to use when logging errors.</param> + /// <returns>Whether the command registered successfully.</returns> public static bool TryRegisterCommand(Type commandType, Type commandHandlerType, [NotNullWhen(true)] out ICommand? command, string logName) { command = null; @@ -202,12 +200,13 @@ public static bool TryRegisterCommand(ICommand command, CommandHandler commandHa // We check if the command type is a parent command. if (command is not ParentCommand parentCommand) + { return true; + } // If the command type is a parent command, we register the command type as a command handler type. // This allows us to register subcommands to the parent command by just using the CommandHandlerAttribute. // [CommandHandler(typeof(MyParentCommand))] - Type commandType = command.GetType(); if (!CommandHandlers.ContainsKey(commandType)) { @@ -241,7 +240,9 @@ public static bool TryRegisterCommand(ICommand command, CommandHandler commandHa public static void UnregisterCommands(this Plugin plugin) { if (!RegisteredCommands.TryGetValue(plugin, out IEnumerable<ICommand> commands)) + { return; + } // We iterate through all commands in the plugin. foreach (ICommand command in commands) @@ -265,7 +266,9 @@ public static void UnregisterCommand(ICommand command) { // If the command handler does not contain the command, we continue. if (!commandHandler.AllCommands.Contains(command)) + { continue; + } // We manually unregister the command from the command handler. commandHandler.UnregisterCommand(command); @@ -273,10 +276,22 @@ public static void UnregisterCommand(ICommand command) // We check if the command is a parent command. if (command is not ParentCommand parentCommand) + { return; + } // If the command is a parent command, we remove the command type from the dictionary of command handlers. Type commandType = parentCommand.GetType(); CommandHandlers.Remove(commandType); } + + /// <summary> + /// Registers all commands in the LabAPI solution. + /// </summary> + internal static void RegisterCommands() + { + // We register all commands in the LabAPI assembly. + // We convert it to an array since IEnumerable are lazy and need to be iterated through to be executed. + LabApiCommands = RegisterCommands(Assembly.GetExecutingAssembly(), "LabApi").ToArray(); + } } \ No newline at end of file diff --git a/LabApi/Loader/ConfigurationLoader.cs b/LabApi/Loader/ConfigurationLoader.cs index 59402ff7..b91899d0 100644 --- a/LabApi/Loader/ConfigurationLoader.cs +++ b/LabApi/Loader/ConfigurationLoader.cs @@ -1,4 +1,5 @@ using LabApi.Features.Console; +using LabApi.Features.Wrappers; using LabApi.Loader.Features.Paths; using LabApi.Loader.Features.Plugins; using LabApi.Loader.Features.Plugins.Configuration; @@ -6,7 +7,6 @@ using System; using System.Diagnostics.CodeAnalysis; using System.IO; -using LabApi.Features.Wrappers; namespace LabApi.Loader; @@ -75,7 +75,9 @@ public static bool TryReadConfig<TConfig>(this Plugin plugin, string fileName, [ // If the configuration file doesn't exist, we return false to indicate that the configuration wasn't successfully read. if (!File.Exists(path)) + { return false; + } // We read the configuration file. string serializedConfig = File.ReadAllText(path); @@ -105,8 +107,6 @@ public static bool TryReadConfig<TConfig>(this Plugin plugin, string fileName, [ public static bool TryLoadConfig<TConfig>(this Plugin plugin, string fileName, [NotNullWhen(true)] out TConfig? config, bool isGlobal = false) where TConfig : class, new() { - config = null; - // We retrieve the path of the configuration file. string path = plugin.GetConfigPath(fileName, isGlobal); @@ -120,10 +120,11 @@ public static bool TryLoadConfig<TConfig>(this Plugin plugin, string fileName, [ return plugin.TrySaveConfig(config, fileName, isGlobal); } } + // We try to read the configuration from its file. else if (plugin.TryReadConfig(fileName, out config, isGlobal)) { - // We save the configuration to update new properties and return whether it was successfully saved. + // We save the configuration to update new properties and return whether it was successfully saved. return plugin.TrySaveConfig(config, fileName, isGlobal); } @@ -194,6 +195,9 @@ public static bool TryCreateDefaultConfig<TConfig>(this Plugin plugin, [NotNullW /// <summary> /// Gets the configuration directory for a plugin, considering whether it's global or per-port. /// </summary> + /// <param name="plugin">The plugin to gets its config directory.</param> + /// <param name="isGlobal">Whether the directory is for global configs or per-port ones.</param> + /// <returns>The <see cref="DirectoryInfo"/> of the plugin.</returns> public static DirectoryInfo GetConfigDirectory(this Plugin plugin, bool isGlobal = false) { DirectoryInfo baseDir = PathManager.Configs; @@ -215,7 +219,9 @@ public static string GetConfigPath(this Plugin plugin, string fileName, bool isG // We check if the file name doesn't end with .yml or .yaml and add it if it doesn't. if (!fileName.EndsWith(".yml", StringComparison.InvariantCultureIgnoreCase) && !fileName.EndsWith(".yaml", StringComparison.InvariantCultureIgnoreCase)) + { fileName += ".yml"; + } // We return the path of the configuration file. return Path.Combine(directory.FullName, fileName); @@ -230,7 +236,9 @@ public static bool TryLoadProperties(this Plugin plugin) { // We try to load the properties of the plugin and return them. if (!plugin.TryLoadConfig(PropertiesFileName, out Properties? properties)) + { return false; + } // We set the properties of the plugin. plugin.Properties = properties; diff --git a/LabApi/Loader/Features/Commands/LabApiParentCommand.cs b/LabApi/Loader/Features/Commands/LabApiParentCommand.cs index 5852db75..53e306b9 100644 --- a/LabApi/Loader/Features/Commands/LabApiParentCommand.cs +++ b/LabApi/Loader/Features/Commands/LabApiParentCommand.cs @@ -21,7 +21,9 @@ public class LabApiParentCommand : ParentCommand public override string Description => "Parent command for all LabAPI subcommands."; /// <inheritdoc /> - public override void LoadGeneratedCommands() { } + public override void LoadGeneratedCommands() + { + } /// <inheritdoc /> protected override bool ExecuteParent(ArraySegment<string> arguments, ICommandSender sender, out string response) diff --git a/LabApi/Loader/Features/Commands/Reload/ConfigsCommand.cs b/LabApi/Loader/Features/Commands/Reload/ConfigsCommand.cs index 693232e8..5ec85e51 100644 --- a/LabApi/Loader/Features/Commands/Reload/ConfigsCommand.cs +++ b/LabApi/Loader/Features/Commands/Reload/ConfigsCommand.cs @@ -25,7 +25,9 @@ public class ConfigsCommand : ICommand public bool Execute(ArraySegment<string> arguments, ICommandSender sender, out string response) { if (!sender.CheckPermission(PlayerPermissions.ServerConfigs, out response)) + { return false; + } int pluginCount = PluginLoader.Plugins.Count; if (pluginCount == 0) @@ -35,7 +37,7 @@ public bool Execute(ArraySegment<string> arguments, ICommandSender sender, out s } StringBuilder sb = StringBuilderPool.Shared.Rent(); - sb.AppendLine($"Reloading configs for {pluginCount} plugin{(pluginCount == 1 ? "" : "s")}"); + sb.AppendLine($"Reloading configs for {pluginCount} plugin{(pluginCount == 1 ? string.Empty : "s")}"); int successCount = 0; bool success = true; diff --git a/LabApi/Loader/Features/Commands/Reload/ReloadParentCommand.cs b/LabApi/Loader/Features/Commands/Reload/ReloadParentCommand.cs index 643d5a5d..d7eaf6d0 100644 --- a/LabApi/Loader/Features/Commands/Reload/ReloadParentCommand.cs +++ b/LabApi/Loader/Features/Commands/Reload/ReloadParentCommand.cs @@ -1,6 +1,5 @@ using CommandSystem; using System; - using static LabApi.Loader.Features.Commands.Extensions.CommandExtensions; namespace LabApi.Loader.Features.Commands.Reload; @@ -21,7 +20,9 @@ public class ReloadParentCommand : ParentCommand public override string Description => "Parent command for all reloading related sub commands."; /// <inheritdoc /> - public override void LoadGeneratedCommands() { } + public override void LoadGeneratedCommands() + { + } /// <inheritdoc /> protected override bool ExecuteParent(ArraySegment<string> arguments, ICommandSender sender, out string response) diff --git a/LabApi/Loader/Features/Configuration/LabApiConfig.cs b/LabApi/Loader/Features/Configuration/LabApiConfig.cs index f01466ac..db52086d 100644 --- a/LabApi/Loader/Features/Configuration/LabApiConfig.cs +++ b/LabApi/Loader/Features/Configuration/LabApiConfig.cs @@ -1,6 +1,6 @@ -using System.Collections.Generic; +using LabApi.Loader.Features.Paths; +using System.Collections.Generic; using System.ComponentModel; -using LabApi.Loader.Features.Paths; namespace LabApi.Loader.Features.Configuration; @@ -13,11 +13,11 @@ public class LabApiConfig /// List of dependency paths relative to <see cref="PathManager.Dependencies"/>. /// </summary> [Description("List of dependency paths relative to the Dependencies folder to load from. Use $port to load from the server port's folder.")] - public List<string> DependencyPaths { get; set; } = new() { "global", "$port" }; + public List<string> DependencyPaths { get; set; } = ["global", "$port"]; /// <summary> /// List of plugin paths relative to <see cref="PathManager.Plugins"/>. /// </summary> [Description("List of plugin paths relative to the Plugins folder to load from. Use $port to load from the server port's folder.")] - public List<string> PluginPaths { get; set; } = new() { "global", "$port" }; + public List<string> PluginPaths { get; set; } = ["global", "$port"]; } \ No newline at end of file diff --git a/LabApi/Loader/Features/Misc/AssemblyUtils.cs b/LabApi/Loader/Features/Misc/AssemblyUtils.cs index a4b9f5d9..fd5acfdb 100644 --- a/LabApi/Loader/Features/Misc/AssemblyUtils.cs +++ b/LabApi/Loader/Features/Misc/AssemblyUtils.cs @@ -65,8 +65,9 @@ public static bool HasMissingDependencies(Assembly assembly, string assemblyPath public static IEnumerable<string> GetLoadedAssemblies() { return AppDomain.CurrentDomain.GetAssemblies().Select(NameSelector); + // We will use this selector to format the assembly names to the format we want. - string NameSelector(Assembly assembly) => FormatAssemblyName(assembly.GetName()); + static string NameSelector(Assembly assembly) => FormatAssemblyName(assembly.GetName()); } /// <summary> @@ -77,6 +78,7 @@ public static IEnumerable<string> GetLoadedAssemblies() public static IEnumerable<string> GetMissingDependencies(Assembly assembly) { IEnumerable<string> loadedAssemblies = GetLoadedAssemblies(); + // Using the same format, we will get the missing dependencies. return assembly.GetReferencedAssemblies().Select(FormatAssemblyName).Where(name => !loadedAssemblies.Contains(name)); } @@ -100,6 +102,7 @@ public static void ResolveEmbeddedResources(Assembly assembly) // If the resource is a dll, we load it as an embedded dll. LoadEmbeddedDll(assembly, resourceName); } + // We check if the resource is a compressed dll. else if (resourceName.EndsWith(compressedDllExtension, StringComparison.OrdinalIgnoreCase)) { @@ -118,7 +121,9 @@ public static void LoadEmbeddedDll(Assembly target, string name) { // We try to get the data stream of the specified resource name. if (!TryGetDataStream(target, name, out Stream? dataStream)) + { return; + } // We copy the data stream to a memory stream and load the assembly from the memory stream. using MemoryStream stream = new(); @@ -135,10 +140,13 @@ public static void LoadCompressedEmbeddedDll(Assembly target, string name) { // We try to get the data stream of the specified resource name. if (!TryGetDataStream(target, name, out Stream? dataStream)) + { return; + } // We decompress the data stream and load the assembly from the memory stream. using DeflateStream stream = new(dataStream, CompressionMode.Decompress); + // We use a memory stream to load the assembly from the decompressed data stream. using MemoryStream memStream = new(); stream.CopyTo(memStream); @@ -159,7 +167,9 @@ public static bool TryGetDataStream(Assembly target, string name, [NotNullWhen(t // If the data stream is not null, we successfully retrieved the data stream and therefore return true. if (dataStream is not null) + { return true; + } // If the data stream is null, we log an error message and return false. Logger.Error($"{LoggerPrefix} Unable to resolve {name} Stream was null"); diff --git a/LabApi/Loader/Features/Plugins/Enums/LoadPriority.cs b/LabApi/Loader/Features/Plugins/Enums/LoadPriority.cs index 46632eac..557bc9a2 100644 --- a/LabApi/Loader/Features/Plugins/Enums/LoadPriority.cs +++ b/LabApi/Loader/Features/Plugins/Enums/LoadPriority.cs @@ -34,5 +34,5 @@ public enum LoadPriority : byte /// These plugins are loaded last. /// <para>We recommend using it in plugins which require plugins as dependencies.</para> /// </summary> - Lowest = Priority.Lowest + Lowest = Priority.Lowest, } \ No newline at end of file diff --git a/LabApi/Loader/Features/Plugins/Plugin.cs b/LabApi/Loader/Features/Plugins/Plugin.cs index f7bc33a1..b85e472a 100644 --- a/LabApi/Loader/Features/Plugins/Plugin.cs +++ b/LabApi/Loader/Features/Plugins/Plugin.cs @@ -43,10 +43,10 @@ public abstract class Plugin /// Whether this plugin is considered transparent.<br/> /// A plugin can be marked as transparent if the server’s modifications are strictly limited to non-intrusive features that do not affect gameplay balance or make significant alterations to the user interface. /// Examples of transparent modifications are: admin tools, automated timed broadcasts for tips, message of the day or other administrative utilities.<br/> - /// For more information, see article 5.2 in the official documentation: https://scpslgame.com/csg + /// For more information, see article 5.2 in the official documentation: https://scpslgame.com/csg. /// </summary> /// <remarks> - /// You can keep using the 'transparently modded' flag during occasional short events organised and supervised by + /// You can keep using the 'transparently modded' flag during occasional short events organized and supervised by /// Server Staff, regardless of the Modifications used for these events. /// </remarks> public virtual bool IsTransparent { get; } = false; @@ -75,10 +75,12 @@ public abstract class Plugin /// <summary> /// Called before the <see cref="Plugin"/> is enabled. - /// + /// <br/> /// <para>Commonly used to load configurations, or any data files before the plugin is enabled.</para> /// </summary> - public virtual void LoadConfigs() { } + public virtual void LoadConfigs() + { + } /// <inheritdoc/> public override string ToString() => $"'{Name}', Version: {Version}, Author: '{Author}'"; diff --git a/LabApi/Loader/Features/Plugins/PluginTConfig.cs b/LabApi/Loader/Features/Plugins/Plugin{TConfig}.cs similarity index 100% rename from LabApi/Loader/Features/Plugins/PluginTConfig.cs rename to LabApi/Loader/Features/Plugins/Plugin{TConfig}.cs diff --git a/LabApi/Loader/Features/Yaml/CustomConverters/CustomColor32Converter.cs b/LabApi/Loader/Features/Yaml/CustomConverters/CustomColor32Converter.cs index af58a713..821d49e4 100644 --- a/LabApi/Loader/Features/Yaml/CustomConverters/CustomColor32Converter.cs +++ b/LabApi/Loader/Features/Yaml/CustomConverters/CustomColor32Converter.cs @@ -18,7 +18,9 @@ public object ReadYaml(IParser parser, Type type) string colorText = scalar.Value; if (!ColorUtility.TryParseHtmlString(colorText, out Color color)) + { throw new ArgumentException($"Unable to parse {nameof(Color32)} value of {colorText}"); + } return (Color32)color; } @@ -26,8 +28,8 @@ public object ReadYaml(IParser parser, Type type) /// <inheritdoc/> public void WriteYaml(IEmitter emitter, object? value, Type type) { - Color32 color = (Color32)value; - emitter.Emit(new Scalar(color.ToHex())); + Color32? color = (Color32?)value; + emitter.Emit(new Scalar(color?.ToHex() ?? Color.white.ToHex())); } /// <inheritdoc/> @@ -36,4 +38,3 @@ public bool Accepts(Type type) return type == typeof(Color32); } } - diff --git a/LabApi/Loader/Features/Yaml/CustomConverters/CustomColorConverter.cs b/LabApi/Loader/Features/Yaml/CustomConverters/CustomColorConverter.cs index d755c349..ef55111c 100644 --- a/LabApi/Loader/Features/Yaml/CustomConverters/CustomColorConverter.cs +++ b/LabApi/Loader/Features/Yaml/CustomConverters/CustomColorConverter.cs @@ -15,7 +15,6 @@ namespace LabApi.Loader.Features.Yaml.CustomConverters; /// </summary> public class CustomColorConverter : IYamlTypeConverter { - /// <inheritdoc/> public object? ReadYaml(IParser parser, Type type) { @@ -28,16 +27,21 @@ public class CustomColorConverter : IYamlTypeConverter for (int i = 0; i <= 3; i++) { if (!parser.TryReadMapping(out string key, out string val)) + { throw new ArgumentException($"Unable to parse {nameof(Color)}, no component at index {i} provided"); + } if (!(key is "r" or "g" or "b" or "a")) + { throw new ArgumentException($"Unable to parse {nameof(Color)}, invalid component name {key}. Only 'r', 'g', 'b' and 'a' are allowed"); + } storedValues[key] = float.Parse(val, CultureInfo.InvariantCulture); } + parser.Consume<MappingEnd>(); - Color value = new Color(storedValues["r"], storedValues["g"], storedValues["b"], storedValues["a"]); + Color value = new(storedValues["r"], storedValues["g"], storedValues["b"], storedValues["a"]); return value; } catch (ArgumentException) @@ -53,7 +57,7 @@ public class CustomColorConverter : IYamlTypeConverter /// <inheritdoc/> public void WriteYaml(IEmitter emitter, object? value, Type type) { - Color color = (Color)value; + Color color = (Color?)value ?? Color.white; emitter.Emit(new MappingStart(AnchorName.Empty, TagName.Empty, isImplicit: true, MappingStyle.Block)); emitter.EmitMapping("r", color.r.ToString(CultureInfo.InvariantCulture)); diff --git a/LabApi/Loader/Features/Yaml/CustomConverters/CustomQuaternionConverter.cs b/LabApi/Loader/Features/Yaml/CustomConverters/CustomQuaternionConverter.cs index 07413660..bc439654 100644 --- a/LabApi/Loader/Features/Yaml/CustomConverters/CustomQuaternionConverter.cs +++ b/LabApi/Loader/Features/Yaml/CustomConverters/CustomQuaternionConverter.cs @@ -1,12 +1,12 @@ -using System; +using LabApi.Loader.Features.Yaml.Extensions; +using System; using System.Collections.Generic; -using YamlDotNet.Serialization; -using UnityEngine; using System.Globalization; +using UnityEngine; using UnityEngine.Pool; -using YamlDotNet.Core.Events; using YamlDotNet.Core; -using LabApi.Loader.Features.Yaml.Extensions; +using YamlDotNet.Core.Events; +using YamlDotNet.Serialization; namespace LabApi.Loader.Features.Yaml.CustomConverters; @@ -27,13 +27,18 @@ public class CustomQuaternionConverter : IYamlTypeConverter for (int i = 0; i <= 2; i++) { if (!parser.TryReadMapping(out string key, out string val)) + { throw new ArgumentException($"Unable to parse {nameof(Quaternion)}, no component at index {i} provided"); + } if (!(key is "x" or "y" or "z")) + { throw new ArgumentException($"Unable to parse {nameof(Quaternion)}, invalid component name {key}. Only 'x', 'y' and 'z' euler angles are allowed"); + } storedValues[key] = float.Parse(val, CultureInfo.InvariantCulture); } + parser.Consume<MappingEnd>(); Quaternion value = Quaternion.Euler(storedValues["x"], storedValues["y"], storedValues["z"]); @@ -52,7 +57,7 @@ public class CustomQuaternionConverter : IYamlTypeConverter /// <inheritdoc/> public void WriteYaml(IEmitter emitter, object? value, Type type) { - Vector3 rotation = ((Quaternion)value).eulerAngles; + Vector3 rotation = ((Quaternion?)value)?.eulerAngles ?? Vector3.zero; emitter.Emit(new MappingStart(AnchorName.Empty, TagName.Empty, isImplicit: true, MappingStyle.Block)); emitter.EmitMapping("x", rotation.x.ToString(CultureInfo.InvariantCulture)); diff --git a/LabApi/Loader/Features/Yaml/CustomConverters/CustomVectorConverter.cs b/LabApi/Loader/Features/Yaml/CustomConverters/CustomVectorConverter.cs index e509d9f9..a061ab51 100644 --- a/LabApi/Loader/Features/Yaml/CustomConverters/CustomVectorConverter.cs +++ b/LabApi/Loader/Features/Yaml/CustomConverters/CustomVectorConverter.cs @@ -15,7 +15,6 @@ namespace LabApi.Loader.Features.Yaml.CustomConverters; /// </summary> public class CustomVectorConverter : IYamlTypeConverter { - /// <inheritdoc/> public object? ReadYaml(IParser parser, Type type) { @@ -29,13 +28,19 @@ public class CustomVectorConverter : IYamlTypeConverter while (!parser.TryConsume(out MappingEnd _)) { if (!parser.TryReadMapping(out string key, out string val)) + { throw new ArgumentException($"Unable to parse Vector, no component at index {idx} provided"); + } if (!(key is "x" or "y" or "z" or "w")) + { throw new ArgumentException($"Unable to parse Vector, invalid component name {key}. Only 'x' 'y' 'z' and 'w' are allowed"); + } if (storedValues.ContainsKey(key)) + { throw new ArgumentException($"Unable to parse Vector, duplicate component {key}"); + } storedValues[key] = float.Parse(val, CultureInfo.InvariantCulture); idx++; @@ -46,12 +51,14 @@ public class CustomVectorConverter : IYamlTypeConverter 2 => new Vector2(storedValues["x"], storedValues["y"]), 3 => new Vector3(storedValues["x"], storedValues["y"], storedValues["z"]), 4 => new Vector4(storedValues["x"], storedValues["y"], storedValues["z"], storedValues["w"]), - _ => throw new ArgumentException($"Unable to deserialize vector with {storedValues.Count} components") + _ => throw new ArgumentException($"Unable to deserialize vector with {storedValues.Count} components"), }; Type createdType = result.GetType(); if (createdType != type) + { throw new ArgumentException($"Attempting to deserialize {createdType.Name} for config type of {type.Name}"); + } return result; } diff --git a/LabApi/Loader/Features/Yaml/Extensions/YamlMappingExtensions.cs b/LabApi/Loader/Features/Yaml/Extensions/YamlMappingExtensions.cs index 7160d825..4e715bcc 100644 --- a/LabApi/Loader/Features/Yaml/Extensions/YamlMappingExtensions.cs +++ b/LabApi/Loader/Features/Yaml/Extensions/YamlMappingExtensions.cs @@ -26,14 +26,16 @@ public static void EmitMapping(this IEmitter emitter, string key, string value) /// <param name="parser">This parser to read from.</param> /// <param name="key">The key value.</param> /// <param name="value">The value.</param> - /// <returns>Whether was the kvp succesfully parsed.</returns> + /// <returns>Whether was the kvp successfully parsed.</returns> public static bool TryReadMapping(this IParser parser, out string key, out string value) { key = string.Empty; value = string.Empty; if (!parser.TryConsume(out Scalar keyScalar) || !parser.TryConsume(out Scalar valueScalar)) + { return false; + } key = keyScalar.Value.Trim(); value = valueScalar.Value.Trim(); diff --git a/LabApi/Loader/Features/Yaml/YamlConfigParser.cs b/LabApi/Loader/Features/Yaml/YamlConfigParser.cs index af5405dd..b8ad46a6 100644 --- a/LabApi/Loader/Features/Yaml/YamlConfigParser.cs +++ b/LabApi/Loader/Features/Yaml/YamlConfigParser.cs @@ -1,7 +1,7 @@ -using YamlDotNet.Serialization.NamingConventions; -using YamlDotNet.Serialization; +using LabApi.Loader.Features.Yaml.CustomConverters; using Serialization; -using LabApi.Loader.Features.Yaml.CustomConverters; +using YamlDotNet.Serialization; +using YamlDotNet.Serialization.NamingConventions; using CommentsObjectGraphVisitor = Serialization.CommentsObjectGraphVisitor; namespace LabApi.Loader.Features.Yaml; diff --git a/LabApi/Loader/PluginLoader.cs b/LabApi/Loader/PluginLoader.cs index 44bf5b2c..ebae5285 100644 --- a/LabApi/Loader/PluginLoader.cs +++ b/LabApi/Loader/PluginLoader.cs @@ -1,17 +1,17 @@ using LabApi.Features.Console; +using LabApi.Features.Permissions; +using LabApi.Features.Permissions.Providers; +using LabApi.Features.Wrappers; +using LabApi.Loader.Features.Configuration; using LabApi.Loader.Features.Misc; using LabApi.Loader.Features.Paths; using LabApi.Loader.Features.Plugins; -using LabApi.Loader.Features.Configuration; +using LabApi.Loader.Features.Yaml; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; -using LabApi.Features.Permissions; -using LabApi.Features.Permissions.Providers; -using LabApi.Features.Wrappers; -using LabApi.Loader.Features.Yaml; namespace LabApi.Loader; @@ -58,7 +58,9 @@ public static void Initialize() { // If the loader has already been initialized, we skip the initialization. if (Initialized) + { return; + } Initialized = true; @@ -84,8 +86,6 @@ public static void Initialize() PermissionsManager.RegisterProvider<DefaultPermissionsProvider>(); } - static partial void InitializeWrappers(); // The contents of this method will be generated by Source Generators - /// <summary> /// Loads all dependencies from the configured dependency paths in <see cref="LabApiConfig.DependencyPaths"/>. /// Each path is relative to <see cref="PathManager.Dependencies"/> and supports port substitution. @@ -152,7 +152,9 @@ public static void LoadAllPlugins() Directory.CreateDirectory(fullPath); if (Directory.Exists(fullPath)) + { LoadPlugins(new DirectoryInfo(fullPath).GetFiles(DllSearchPattern)); + } } // Then we finally enable all the plugins @@ -177,8 +179,10 @@ public static void LoadPlugins(IEnumerable<FileInfo> files) // We load the assembly from the specified file. Assembly pluginAssembly = pdb.Exists + // In the case that the PDB file exists, we load the assembly with the PDB file. ? Assembly.Load(File.ReadAllBytes(file.FullName), File.ReadAllBytes(pdb.FullName)) + // Otherwise, we load the assembly without any debug information. : Assembly.Load(File.ReadAllBytes(file.FullName)); @@ -197,7 +201,9 @@ public static void LoadPlugins(IEnumerable<FileInfo> files) { // If the assembly has missing dependencies, we skip it. if (AssemblyUtils.HasMissingDependencies(assembly, file.FullName, out Type[]? types)) + { continue; + } InstantiatePlugins(types, assembly, file.FullName); } @@ -209,27 +215,6 @@ public static void LoadPlugins(IEnumerable<FileInfo> files) } } - private static void InstantiatePlugins(Type[] types, Assembly assembly, string filePath) - { - foreach (Type type in types) - { - // We check if the type is derived from Plugin. - if (!type.IsSubclassOf(typeof(Plugin))) - continue; - - // We create an instance of the type and check if it was successfully created. - if (Activator.CreateInstance(type) is not Plugin plugin) - continue; - - // Set the file path - plugin.FilePath = filePath; - - // In that case, we add the plugin to the plugins list and log that it has been loaded. - Plugins.Add(plugin, assembly); - Logger.Info($"{LoggerPrefix} Successfully loaded {plugin.Name}"); - } - } - /// <summary> /// Enables a collection of <see cref="Plugin"/>s. /// </summary> @@ -240,11 +225,15 @@ public static void EnablePlugins(IEnumerable<Plugin> plugins) { // We try to load the configuration of the plugin if (!plugin.TryLoadProperties()) + { continue; + } // We check if the plugin is enabled if (plugin.Properties?.IsEnabled == false) + { continue; + } // We finally enable the plugin EnablePlugin(plugin); @@ -284,6 +273,33 @@ public static void EnablePlugin(Plugin plugin) } } + static partial void InitializeWrappers(); // The contents of this method will be generated by Source Generators + + private static void InstantiatePlugins(Type[] types, Assembly assembly, string filePath) + { + foreach (Type type in types) + { + // We check if the type is derived from Plugin. + if (!type.IsSubclassOf(typeof(Plugin))) + { + continue; + } + + // We create an instance of the type and check if it was successfully created. + if (Activator.CreateInstance(type) is not Plugin plugin) + { + continue; + } + + // Set the file path + plugin.FilePath = filePath; + + // In that case, we add the plugin to the plugins list and log that it has been loaded. + Plugins.Add(plugin, assembly); + Logger.Info($"{LoggerPrefix} Successfully loaded {plugin.Name}"); + } + } + /// <summary> /// Loads or creates the LabAPI configuration file. /// </summary> @@ -317,10 +333,14 @@ private static void LoadLabApiConfig() private static void ResolveTransparentlyModdedFlag() { if (Plugins.Count == 0) + { return; + } if (Server.IsTransparentlyModded) + { return; + } bool isTransparent = true; From 78656b292b2e0c8147daf21e4017e5fbe4c27728 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Tue, 12 Aug 2025 00:07:21 +0930 Subject: [PATCH 137/215] player fixes --- LabApi/Features/Wrappers/Players/Player.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LabApi/Features/Wrappers/Players/Player.cs b/LabApi/Features/Wrappers/Players/Player.cs index 5827b55c..23227b15 100644 --- a/LabApi/Features/Wrappers/Players/Player.cs +++ b/LabApi/Features/Wrappers/Players/Player.cs @@ -8,6 +8,7 @@ using InventorySystem.Disarming; using InventorySystem.Items; using InventorySystem.Items.Pickups; +using InventorySystem.Items.Usables.Scp330; using LabApi.Features.Enums; using LabApi.Features.Stores; using MapGeneration; @@ -25,7 +26,6 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; -using InventorySystem.Items.Usables.Scp330; using UnityEngine; using Utils.Networking; using Utils.NonAllocLINQ; @@ -1593,7 +1593,7 @@ public void ClearInventory(bool clearAmmo = true, bool clearItems = true) ClearItems(); } } - + /// <summary> /// Gives a candy to the player. /// </summary> From 88a91281ab8f7a695854a96c6c867dbe08324850 Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Wed, 13 Aug 2025 00:12:09 +0930 Subject: [PATCH 138/215] support for base game relative position changes to ragdoll --- LabApi/Features/Wrappers/Players/Ragdoll.cs | 63 ++++++++++++++++++--- 1 file changed, 56 insertions(+), 7 deletions(-) diff --git a/LabApi/Features/Wrappers/Players/Ragdoll.cs b/LabApi/Features/Wrappers/Players/Ragdoll.cs index 12f39027..3444ae5f 100644 --- a/LabApi/Features/Wrappers/Players/Ragdoll.cs +++ b/LabApi/Features/Wrappers/Players/Ragdoll.cs @@ -5,6 +5,7 @@ using PlayerRoles.PlayableScps.Scp049.Zombies; using PlayerRoles.Ragdolls; using PlayerStatsSystem; +using RelativePositioning; using System.Collections.Generic; using UnityEngine; @@ -54,7 +55,14 @@ private Ragdoll(BasicRagdoll ragdoll) public RoleTypeId Role { get => Base.NetworkInfo.RoleType; - set => Base.NetworkInfo = new RagdollData(Base.NetworkInfo.OwnerHub, Base.NetworkInfo.Handler, value, Base.NetworkInfo.StartPosition, Base.NetworkInfo.StartRotation, Base.NetworkInfo.Nickname, Base.NetworkInfo.CreationTime); + set => Base.NetworkInfo = new RagdollData( + Base.Info.OwnerHub, + Base.Info.Handler, + value, + Base.Info.StartRelativePosition, + Base.Info.StartRelativeRotation, + Base.Info.Nickname, + Base.Info.CreationTime); } /// <summary> @@ -63,7 +71,14 @@ public RoleTypeId Role public string Nickname { get => Base.NetworkInfo.Nickname; - set => Base.NetworkInfo = new RagdollData(Base.NetworkInfo.OwnerHub, Base.NetworkInfo.Handler, Base.NetworkInfo.RoleType, Base.NetworkInfo.StartPosition, Base.NetworkInfo.StartRotation, value, Base.NetworkInfo.CreationTime); + set => Base.NetworkInfo = new RagdollData( + Base.Info.OwnerHub, + Base.Info.Handler, + Base.Info.RoleType, + Base.Info.StartRelativePosition, + Base.Info.StartRelativeRotation, + value, + Base.Info.CreationTime); } /// <summary> @@ -73,7 +88,14 @@ public string Nickname public DamageHandlerBase DamageHandler { get => Base.NetworkInfo.Handler; - set => Base.NetworkInfo = new RagdollData(Base.NetworkInfo.OwnerHub, value, Base.NetworkInfo.RoleType, Base.NetworkInfo.StartPosition, Base.NetworkInfo.StartRotation, Base.NetworkInfo.Nickname, Base.NetworkInfo.CreationTime); + set => Base.NetworkInfo = new RagdollData( + Base.Info.OwnerHub, + value, + Base.Info.RoleType, + Base.Info.StartRelativePosition, + Base.Info.StartRelativeRotation, + Base.Info.Nickname, + Base.Info.CreationTime); } /// <summary> @@ -85,7 +107,17 @@ public Vector3 Position set { Base.transform.position = value; - Base.NetworkInfo = new RagdollData(Base.NetworkInfo.OwnerHub, Base.NetworkInfo.Handler, Base.NetworkInfo.RoleType, value, Base.NetworkInfo.StartRotation, Base.NetworkInfo.Scale, Base.NetworkInfo.Nickname, Base.NetworkInfo.CreationTime); + RelativePosition relPos = new(value); + Quaternion relRot = WaypointBase.GetRelativeRotation(relPos.WaypointId, WaypointBase.GetWorldRotation(Base.Info.StartRelativePosition.WaypointId, Base.Info.StartRelativeRotation)); + Base.NetworkInfo = new RagdollData( + Base.Info.OwnerHub, + Base.Info.Handler, + Base.Info.RoleType, + relPos, + relRot, + Base.Info.Scale, + Base.Info.Nickname, + Base.Info.CreationTime); } } @@ -98,7 +130,16 @@ public Quaternion Rotation set { Base.transform.rotation = value; - Base.NetworkInfo = new RagdollData(Base.NetworkInfo.OwnerHub, Base.NetworkInfo.Handler, Base.NetworkInfo.RoleType, Base.NetworkInfo.StartPosition, value, Base.NetworkInfo.Scale, Base.NetworkInfo.Nickname, Base.NetworkInfo.CreationTime); + Quaternion relRot = WaypointBase.GetRelativeRotation(Base.Info.StartRelativePosition.WaypointId, value); + Base.NetworkInfo = new RagdollData( + Base.Info.OwnerHub, + Base.Info.Handler, + Base.Info.RoleType, + Base.Info.StartRelativePosition, + relRot, + Base.Info.Scale, + Base.Info.Nickname, + Base.Info.CreationTime); } } @@ -112,7 +153,15 @@ public Vector3 Scale set { Base.transform.localScale = value; - Base.NetworkInfo = new RagdollData(Base.NetworkInfo.OwnerHub, Base.NetworkInfo.Handler, Base.NetworkInfo.RoleType, Base.NetworkInfo.StartPosition, Base.NetworkInfo.StartRotation, Vector3.Scale(value, RagdollManager.GetDefaultScale(Role)), Base.NetworkInfo.Nickname, Base.NetworkInfo.CreationTime); + Base.NetworkInfo = new RagdollData( + Base.Info.OwnerHub, + Base.Info.Handler, + Base.Info.RoleType, + Base.Info.StartRelativePosition, + Base.Info.StartRelativeRotation, + Vector3.Scale(value, RagdollManager.GetDefaultScale(Role)), + Base.Info.Nickname, + Base.Info.CreationTime); } } @@ -184,7 +233,7 @@ public void UnFreeze() Destroy(); Dictionary.Remove(Base); - Base = RagdollManager.ServerCreateRagdoll(data.RoleType, data.StartPosition, data.StartRotation, data.Handler, data.Nickname, data.Scale, data.Serial); + Base = RagdollManager.ServerCreateRagdoll(data.RoleType, data.StartRelativePosition.Position, data.StartRelativeRotation, data.Handler, data.Nickname, data.Scale, data.Serial); Dictionary.TryAdd(Base, this); RagdollManager.OnRagdollSpawned += RagdollSpawned; From 26476e58d82027db041f259afa17ad6f9bcab64f Mon Sep 17 00:00:00 2001 From: brayden-dowson <brayden.dowson@gmail.com> Date: Thu, 21 Aug 2025 15:38:11 +0930 Subject: [PATCH 139/215] added bound size to ToString --- LabApi/Features/Wrappers/AdminToys/WaypointToy.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LabApi/Features/Wrappers/AdminToys/WaypointToy.cs b/LabApi/Features/Wrappers/AdminToys/WaypointToy.cs index 00a9a816..ea2ae1ee 100644 --- a/LabApi/Features/Wrappers/AdminToys/WaypointToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/WaypointToy.cs @@ -193,7 +193,7 @@ public float PriorityBias /// <inheritdoc /> public override string ToString() { - return $"[WaypointToy: Position{Position}, VisualizeBounds:{VisualizeBounds}, PriorityBias:{PriorityBias}]"; + return $"[WaypointToy: Position{Position}, BoundsSize:{BoundsSize}, VisualizeBounds:{VisualizeBounds}, PriorityBias:{PriorityBias}]"; } /// <summary> From 62ef3ebae9b69817955c438b830a3d35c245a03a Mon Sep 17 00:00:00 2001 From: davidsebesta <david.sebesta@post.cz> Date: Thu, 28 Aug 2025 16:11:22 +0200 Subject: [PATCH 140/215] Applied suggestion --- LabApi/Features/Wrappers/Players/Player.cs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/LabApi/Features/Wrappers/Players/Player.cs b/LabApi/Features/Wrappers/Players/Player.cs index 56227133..c0168bf8 100644 --- a/LabApi/Features/Wrappers/Players/Player.cs +++ b/LabApi/Features/Wrappers/Players/Player.cs @@ -811,16 +811,10 @@ public Vector3 Scale { if (ReferenceHub.roleManager.CurrentRole is not IFpcRole fpcRole) return Vector3.zero; - - return fpcRole.FpcModule.Motor.ScaleController.Scale; - } - set - { - if (ReferenceHub.roleManager.CurrentRole is not IFpcRole fpcRole) - return; - - fpcRole.FpcModule.Motor.ScaleController.Scale = value; - } + public bool IsSpectatable + { + get => SpectatableVisibilityManager.IsHidden(ReferenceHub); + set => SpectatableVisibilityManager.SetHidden(ReferenceHub, value); } /// <summary> From 4feb0b0886d6d8d060856a38b357d19e0b3d5576 Mon Sep 17 00:00:00 2001 From: The Riptide <theriptideservers@gmail.com> Date: Fri, 29 Aug 2025 01:28:12 +0000 Subject: [PATCH 141/215] Apply 2 suggestion(s) to 1 file(s) Co-authored-by: Jesus-QC <99-jesusqc@users.noreply.git.scpslgame.com> --- LabApi/Features/Wrappers/AdminToys/WaypointToy.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LabApi/Features/Wrappers/AdminToys/WaypointToy.cs b/LabApi/Features/Wrappers/AdminToys/WaypointToy.cs index ea2ae1ee..ff8733cd 100644 --- a/LabApi/Features/Wrappers/AdminToys/WaypointToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/WaypointToy.cs @@ -140,7 +140,7 @@ public override Vector3 Scale if (value != Vector3.one) { - Console.Logger.Warn("Setting scale on WaypointToy is not supported and may causes problems."); + Console.Logger.Warn("Setting scale on WaypointToy is not supported and may cause problems."); } } } @@ -193,7 +193,7 @@ public float PriorityBias /// <inheritdoc /> public override string ToString() { - return $"[WaypointToy: Position{Position}, BoundsSize:{BoundsSize}, VisualizeBounds:{VisualizeBounds}, PriorityBias:{PriorityBias}]"; + return $"[WaypointToy: Position:{Position}, BoundsSize:{BoundsSize}, VisualizeBounds:{VisualizeBounds}, PriorityBias:{PriorityBias}]"; } /// <summary> From c3f82a6300e01d7fca570bcda05bd06263c67ee0 Mon Sep 17 00:00:00 2001 From: davidsebesta1 <david.sebesta@post.cz> Date: Mon, 1 Sep 2025 11:56:42 +0200 Subject: [PATCH 142/215] Reference fix --- LabApi/Features/Wrappers/Server/Server.cs | 2 +- LabApi/Loader/CommandLoader.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/LabApi/Features/Wrappers/Server/Server.cs b/LabApi/Features/Wrappers/Server/Server.cs index 9a3d69c6..f24e69ea 100644 --- a/LabApi/Features/Wrappers/Server/Server.cs +++ b/LabApi/Features/Wrappers/Server/Server.cs @@ -209,7 +209,7 @@ public static float PlayerListNameRefreshRate /// <summary> /// Gets the <see cref="CommandSystem.GameConsoleCommandHandler"/> instance. /// </summary> - public static GameConsoleCommandHandler GameConsoleCommandHandler => GameCore.Console.singleton.ConsoleCommandHandler; + public static GameConsoleCommandHandler GameConsoleCommandHandler => GameCore.Console.ConsoleCommandHandler; /// <summary> /// Gets the <see cref="ServerShutdown.ServerShutdownState"/> of the server. diff --git a/LabApi/Loader/CommandLoader.cs b/LabApi/Loader/CommandLoader.cs index 4bcf35b1..d1a6723a 100644 --- a/LabApi/Loader/CommandLoader.cs +++ b/LabApi/Loader/CommandLoader.cs @@ -25,7 +25,7 @@ public static class CommandLoader public static Dictionary<Type, CommandHandler> CommandHandlers { get; } = new() { // The server console command handler. - [typeof(GameConsoleCommandHandler)] = GameCore.Console.singleton.ConsoleCommandHandler, + [typeof(GameConsoleCommandHandler)] = GameCore.Console.ConsoleCommandHandler, // The remote admin command handler. [typeof(RemoteAdminCommandHandler)] = CommandProcessor.RemoteAdminCommandHandler, @@ -292,6 +292,6 @@ internal static void RegisterCommands() { // We register all commands in the LabAPI assembly. // We convert it to an array since IEnumerable are lazy and need to be iterated through to be executed. - LabApiCommands = RegisterCommands(Assembly.GetExecutingAssembly(), "LabApi").ToArray(); + LabApiCommands = RegisterCommands(Assembly.GetExecutingAssembly(), "LabApi").ToArray(); } } \ No newline at end of file From 3e7be68b7bcf178545e16e82d8cfe2ccb48f4410 Mon Sep 17 00:00:00 2001 From: davidsebesta1 <david.sebesta@post.cz> Date: Tue, 2 Sep 2025 19:12:48 +0200 Subject: [PATCH 143/215] Added EmotionPresetType wrapper --- LabApi/Features/Wrappers/Players/Player.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/LabApi/Features/Wrappers/Players/Player.cs b/LabApi/Features/Wrappers/Players/Player.cs index 23227b15..3c9b2d94 100644 --- a/LabApi/Features/Wrappers/Players/Player.cs +++ b/LabApi/Features/Wrappers/Players/Player.cs @@ -17,6 +17,7 @@ using NorthwoodLib.Pools; using PlayerRoles; using PlayerRoles.FirstPersonControl; +using PlayerRoles.FirstPersonControl.Thirdperson.Subcontrollers; using PlayerRoles.PlayableScps.HumeShield; using PlayerRoles.Spectating; using PlayerRoles.Voice; @@ -40,7 +41,7 @@ namespace LabApi.Features.Wrappers; /// </summary> public class Player { - /// <summary> + /// <summary> /// A cache of players by their User ID. Does not necessarily contain all players. /// </summary> private static readonly Dictionary<string, Player> UserIdCache = new(CustomNetworkManager.slots, StringComparer.OrdinalIgnoreCase); @@ -1281,6 +1282,15 @@ public float StaminaRemaining set => ReferenceHub.playerStats.GetModule<StaminaStat>().CurValue = value; } + /// <summary> + /// Gets or sets the current player's emotion. + /// </summary> + public EmotionPresetType Emotion + { + get => EmotionSync.GetEmotionPreset(ReferenceHub); + set => EmotionSync.ServerSetEmotionPreset(ReferenceHub, value); + } + /// <summary> /// Teleports the player by the delta location. /// </summary> From 5b457205a85e9d20f6e8f8a2ff908409bc56d37f Mon Sep 17 00:00:00 2001 From: jesusqc <contact@jesusqc.es> Date: Thu, 4 Sep 2025 17:27:41 +0200 Subject: [PATCH 144/215] version bump --- LabApi/LabApi.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LabApi/LabApi.csproj b/LabApi/LabApi.csproj index f08b75ec..311ab567 100644 --- a/LabApi/LabApi.csproj +++ b/LabApi/LabApi.csproj @@ -6,7 +6,7 @@ <PlatformTarget>x64</PlatformTarget> <LangVersion>12.0</LangVersion> - <Version>1.1.1</Version> + <Version>1.1.2</Version> <AssemblyName>LabApi</AssemblyName> <PackageId>Northwood.LabAPI</PackageId> From 19c21003e996d9b5ba222d9180e651fa3cf5786f Mon Sep 17 00:00:00 2001 From: jesusqc <contact@jesusqc.es> Date: Thu, 4 Sep 2025 23:50:21 +0200 Subject: [PATCH 145/215] 1.1.2 --- LabApi/Events/CustomHandlers/CustomHandlersManager.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/LabApi/Events/CustomHandlers/CustomHandlersManager.cs b/LabApi/Events/CustomHandlers/CustomHandlersManager.cs index df426b9c..8ec32dc8 100644 --- a/LabApi/Events/CustomHandlers/CustomHandlersManager.cs +++ b/LabApi/Events/CustomHandlers/CustomHandlersManager.cs @@ -58,7 +58,7 @@ public static void CheckEvent<T>(T handler, Type handlerType, string methodDeleg // We first get the method from the handler, there can be custom methods names as the original events but with different overloads, so we filter them. MethodInfo[] candidates = handlerType.GetMethods(BindingFlags.Public | BindingFlags.Instance); - MethodInfo method = null; + MethodInfo? method = null; foreach (MethodInfo candidate in candidates) { if (candidate.Name == methodDelegate && IsOverride(candidate)) @@ -69,6 +69,7 @@ public static void CheckEvent<T>(T handler, Type handlerType, string methodDeleg } if (method == null) + { return; } From 173fcc68f12543beaa40ce96cf725d5f0d86a809 Mon Sep 17 00:00:00 2001 From: davidsebesta1 <david.sebesta@post.cz> Date: Mon, 8 Sep 2025 10:54:10 +0200 Subject: [PATCH 146/215] Fomatting --- LabApi/Features/Wrappers/Players/Player.cs | 30 ++++++++++++---------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/LabApi/Features/Wrappers/Players/Player.cs b/LabApi/Features/Wrappers/Players/Player.cs index fabb2573..45b4e9dc 100644 --- a/LabApi/Features/Wrappers/Players/Player.cs +++ b/LabApi/Features/Wrappers/Players/Player.cs @@ -41,7 +41,7 @@ namespace LabApi.Features.Wrappers; /// </summary> public class Player { - /// <summary> + /// <summary> /// A cache of players by their User ID. Does not necessarily contain all players. /// </summary> private static readonly Dictionary<string, Player> UserIdCache = new(CustomNetworkManager.slots, StringComparer.OrdinalIgnoreCase); @@ -927,14 +927,8 @@ public List<Player> CurrentSpectators /// </remarks> public bool IsSpectatable { - get - { - return SpectatableVisibilityManager.IsHidden(ReferenceHub); - } - set - { - SpectatableVisibilityManager.SetHidden(ReferenceHub, value); - } + get => SpectatableVisibilityManager.IsHidden(ReferenceHub); + set => SpectatableVisibilityManager.SetHidden(ReferenceHub, value); } /// <summary> @@ -1280,10 +1274,20 @@ public Vector3 Scale if (ReferenceHub.roleManager.CurrentRole is not IFpcRole fpcRole) { return Vector3.zero; - public bool IsSpectatable - { - get => SpectatableVisibilityManager.IsHidden(ReferenceHub); - set => SpectatableVisibilityManager.SetHidden(ReferenceHub, value); + } + + return fpcRole.FpcModule.Motor.ScaleController.Scale; + } + + set + { + if (ReferenceHub.roleManager.CurrentRole is not IFpcRole fpcRole) + { + return; + } + + fpcRole.FpcModule.Motor.ScaleController.Scale = value; + } } /// <summary> From c8818eb925c8fac3a82cb41d9d6a860afbe148a0 Mon Sep 17 00:00:00 2001 From: SlejmUr <slejmur@protonmail.com> Date: Wed, 10 Sep 2025 00:26:07 +0200 Subject: [PATCH 147/215] Common fix (#239) * Fix not having setter * rom => room * Not having settters * Use get here to avoid set outside values * room => zone desc * door.s => door. * fix spacing in Map.cs * fix tabs in Warhead.cs * Update LabApi/Features/Wrappers/Facility/Map.cs Co-authored-by: David <david.sebesta@post.cz> --------- Co-authored-by: David <david.sebesta@post.cz> --- .../ObjectiveCompletingBaseEventArgs.cs | 10 +++++----- .../PlayerInteractingWarheadLeverEventArgs.cs | 2 +- .../PlayerEvents/PlayerZoneChangedEventArgs.cs | 6 +++--- LabApi/Features/Wrappers/Facility/Doors/Door.cs | 4 ++-- LabApi/Features/Wrappers/Facility/Map.cs | 8 ++++---- LabApi/Features/Wrappers/Facility/Warhead.cs | 4 ++-- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/LabApi/Events/Arguments/ObjectiveEvents/ObjectiveCompletingBaseEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/ObjectiveCompletingBaseEventArgs.cs index 21194cd5..31e6d633 100644 --- a/LabApi/Events/Arguments/ObjectiveEvents/ObjectiveCompletingBaseEventArgs.cs +++ b/LabApi/Events/Arguments/ObjectiveEvents/ObjectiveCompletingBaseEventArgs.cs @@ -31,17 +31,17 @@ public ObjectiveCompletingBaseEventArgs(ReferenceHub hub, Faction faction, float /// <summary> /// Gets or sets the player who triggered the objective completion. /// </summary> - public Player Player { get; } + public Player Player { get; set; } /// <summary> /// Gets or sets the <see cref="PlayerRoles.Faction"/> which receives the <see cref="InfluenceToGrant"/> and <see cref="TimeToGrant"/> rewards. /// </summary> - public Faction Faction { get; } + public Faction Faction { get; set; } /// <summary> /// Gets or sets the amount of influence granted to the <see cref="Faction"/>. /// </summary> - public float InfluenceToGrant { get; } + public float InfluenceToGrant { get; set; } /// <summary> /// Gets or sets the amount of time reduced from the <see cref="Faction"/>'s timer. @@ -49,12 +49,12 @@ public ObjectiveCompletingBaseEventArgs(ReferenceHub hub, Faction faction, float /// <remarks> /// Negative values reduce the timer, positive extends it. /// </remarks> - public float TimeToGrant { get; } + public float TimeToGrant { get; set; } /// <summary> /// Gets or sets whether the objective completion has been sent to players and is visible on their screen. /// </summary> - public bool SendToPlayers { get; } + public bool SendToPlayers { get; set; } /// <inheritdoc/> public bool IsAllowed { get; set; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingWarheadLeverEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingWarheadLeverEventArgs.cs index f5b88fd4..8947ad74 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingWarheadLeverEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingWarheadLeverEventArgs.cs @@ -28,7 +28,7 @@ public PlayerInteractingWarheadLeverEventArgs(ReferenceHub player, bool enabled) /// <summary> /// Gets or sets whether the warhead should be enabled. /// </summary> - public bool Enabled { get; } + public bool Enabled { get; set; } /// <inheritdoc/> public bool IsAllowed { get; set; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerZoneChangedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerZoneChangedEventArgs.cs index cde8413a..3ae5cb95 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerZoneChangedEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerZoneChangedEventArgs.cs @@ -31,10 +31,10 @@ public PlayerZoneChangedEventArgs(ReferenceHub player, FacilityZone oldZone, Fac /// <summary> /// Gets the old zone. May be <see cref="FacilityZone.None"/> if the player just spawned, went through void and such. /// </summary> - public FacilityZone OldZone; + public FacilityZone OldZone { get; } /// <summary> - /// Gets the new rom. May be <see cref="FacilityZone.None"/> if the player went into void, died and such. + /// Gets the new zone. May be <see cref="FacilityZone.None"/> if the player went into void, died and such. /// </summary> - public FacilityZone NewZone; + public FacilityZone NewZone { get; } } diff --git a/LabApi/Features/Wrappers/Facility/Doors/Door.cs b/LabApi/Features/Wrappers/Facility/Doors/Door.cs index 03a24f24..2ff9e178 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/Door.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/Door.cs @@ -137,7 +137,7 @@ internal virtual void OnRemove() public DoorVariant Base { get; } /// <summary> - /// Gets the <see cref="Enums.DoorName"/> of the door.s + /// Gets the <see cref="Enums.DoorName"/> of the door. /// </summary> /// <remarks> /// Is the enum version of <see cref="NameTag"/>. @@ -363,4 +363,4 @@ private static void Register<T>(Func<T, Door> constructor) where T : DoorVariant { typeWrappers.Add(typeof(T), x => constructor((T)x)); } -} \ No newline at end of file +} diff --git a/LabApi/Features/Wrappers/Facility/Map.cs b/LabApi/Features/Wrappers/Facility/Map.cs index c85765a1..16082267 100644 --- a/LabApi/Features/Wrappers/Facility/Map.cs +++ b/LabApi/Features/Wrappers/Facility/Map.cs @@ -91,10 +91,10 @@ public static class Map public static void RemoveEscapeZone(Bounds escapeZone) => EscapeZones.Remove(escapeZone); #region Get Random - /// <summary> - /// Gets a random <see cref="Room"/>. - /// </summary> - /// <returns>The random room if there were any rooms otherwise null.</returns> + /// <summary> + /// Gets a random <see cref="Room"/>. + /// </summary> + /// <returns>The random room if there were any rooms otherwise <see langword="null"/>.</returns> public static Room? GetRandomRoom() { return Rooms.Count != 0 ? Rooms.ElementAt(UnityEngine.Random.Range(0, Rooms.Count)) : null; diff --git a/LabApi/Features/Wrappers/Facility/Warhead.cs b/LabApi/Features/Wrappers/Facility/Warhead.cs index 963495fc..413a785f 100644 --- a/LabApi/Features/Wrappers/Facility/Warhead.cs +++ b/LabApi/Features/Wrappers/Facility/Warhead.cs @@ -132,8 +132,8 @@ public static bool ForceCountdownToggle } /// <summary> - /// Indicates how much time is left for the DMS to activate. - /// Value is capped by <see cref="DeadManSwitchMaxTime"/>. + /// Indicates how much time is left for the DMS to activate. + /// Value is capped by <see cref="DeadManSwitchMaxTime"/>. /// </summary> public static float DeadManSwitchRemaining { From d250b1a0a4266fbf507c0008d5f36733d3d0f8bc Mon Sep 17 00:00:00 2001 From: Axwabo <95743682+Axwabo@users.noreply.github.com> Date: Wed, 10 Sep 2025 00:26:32 +0200 Subject: [PATCH 148/215] IsAbstract plugin check + separate embedded dependency resolving pass (#212) * don't instantiate abstract plugins Added a condition to skip abstract classes when instantiating plugins. * extra embedded resource pass Added a loop between plugin assembly loading and instantiation that resolves embedded DLLs. Modified `AssemblyUtils::GetMissingDependencies` to create a set of the loaded assemblies. Changed the `LoadEmbeddedDll` and `LoadCompressedEmbeddedDll` methods in `AssemblyUtils` class to write resolved the assembly to a temporary file, load the DLL if no assembly with the same name has been loaded. The file is deleted after this operation. * rearrange & slightly optimize code Moved private methods in AssemblyUtils & PluginLoader to the end of the file. Made the LINQ selectors in `LogMissingDependencies` and `GetLoadedAssemblies` static. Removed the `ToArray` call and made the variable an `IEnumerable<string>` in `LogMissingDependencies` to improve performance. * Apply suggestions from code review Co-authored-by: Jesus QC <69375249+Jesus-QC@users.noreply.github.com> * add embedded dlls to Dependencies set --------- Co-authored-by: Jesus QC <69375249+Jesus-QC@users.noreply.github.com> --- LabApi/Loader/Features/Misc/AssemblyUtils.cs | 54 +++++++++----- LabApi/Loader/PluginLoader.cs | 75 ++++++++++++-------- 2 files changed, 84 insertions(+), 45 deletions(-) diff --git a/LabApi/Loader/Features/Misc/AssemblyUtils.cs b/LabApi/Loader/Features/Misc/AssemblyUtils.cs index a4b9f5d9..54643235 100644 --- a/LabApi/Loader/Features/Misc/AssemblyUtils.cs +++ b/LabApi/Loader/Features/Misc/AssemblyUtils.cs @@ -66,7 +66,7 @@ public static IEnumerable<string> GetLoadedAssemblies() { return AppDomain.CurrentDomain.GetAssemblies().Select(NameSelector); // We will use this selector to format the assembly names to the format we want. - string NameSelector(Assembly assembly) => FormatAssemblyName(assembly.GetName()); + static string NameSelector(Assembly assembly) => FormatAssemblyName(assembly.GetName()); } /// <summary> @@ -76,7 +76,7 @@ public static IEnumerable<string> GetLoadedAssemblies() /// <returns>A formatted <see cref="IEnumerable{T}"/> with the missing dependencies.</returns> public static IEnumerable<string> GetMissingDependencies(Assembly assembly) { - IEnumerable<string> loadedAssemblies = GetLoadedAssemblies(); + HashSet<string> loadedAssemblies = GetLoadedAssemblies().ToHashSet(); // Using the same format, we will get the missing dependencies. return assembly.GetReferencedAssemblies().Select(FormatAssemblyName).Where(name => !loadedAssemblies.Contains(name)); } @@ -85,6 +85,7 @@ public static IEnumerable<string> GetMissingDependencies(Assembly assembly) /// Resolves embedded resources from the specified <see cref="Assembly"/>. /// </summary> /// <param name="assembly">The assembly to resolve embedded resources from.</param> + /// <remarks>This method loads each DLL if no such assembly with the same name has been loaded into the current AppDomain yet.</remarks> public static void ResolveEmbeddedResources(Assembly assembly) { const string dllExtension = ".dll"; @@ -110,39 +111,41 @@ public static void ResolveEmbeddedResources(Assembly assembly) } /// <summary> - /// Loads an embedded dll from the specified <see cref="Assembly"/>. + /// Loads an embedded dll from the specified <see cref="Assembly"/> if no such assembly with the same name has been loaded. /// </summary> /// <param name="target">The assembly to load the embedded dll from.</param> /// <param name="name">The resource name of the embedded dll.</param> + /// <remarks>The name check only checks for the <see cref="AssemblyName.Name"/> of the <see cref="AssemblyName"/>.</remarks> public static void LoadEmbeddedDll(Assembly target, string name) { - // We try to get the data stream of the specified resource name. if (!TryGetDataStream(target, name, out Stream? dataStream)) return; - // We copy the data stream to a memory stream and load the assembly from the memory stream. - using MemoryStream stream = new(); - dataStream.CopyTo(stream); - Assembly.Load(stream.ToArray()); + string path = Path.GetTempFileName(); + using (FileStream file = File.Create(path)) + { + dataStream.CopyTo(file); + } + LoadAssemblyIfMissing(path); } /// <summary> - /// Loads a compressed embedded dll from the specified <see cref="Assembly"/>. + /// Loads a compressed embedded dll from the specified <see cref="Assembly"/> if no such assembly with the same name has been loaded. /// </summary> /// <param name="target">The assembly to load the compressed embedded dll from.</param> /// <param name="name">The resource name of the compressed embedded dll.</param> + /// <remarks>The name check only checks for the <see cref="AssemblyName.Name"/> of the <see cref="AssemblyName"/>.</remarks> public static void LoadCompressedEmbeddedDll(Assembly target, string name) { - // We try to get the data stream of the specified resource name. if (!TryGetDataStream(target, name, out Stream? dataStream)) return; - - // We decompress the data stream and load the assembly from the memory stream. - using DeflateStream stream = new(dataStream, CompressionMode.Decompress); - // We use a memory stream to load the assembly from the decompressed data stream. - using MemoryStream memStream = new(); - stream.CopyTo(memStream); - Assembly.Load(memStream.ToArray()); + string path = Path.GetTempFileName(); + using (DeflateStream stream = new(dataStream, CompressionMode.Decompress)) + using (FileStream file = File.Create(path)) + { + stream.CopyTo(file); + } + LoadAssemblyIfMissing(path); } /// <summary> @@ -180,4 +183,21 @@ public static bool TryGetLoadedAssembly(this Plugin plugin, out Assembly assembl // Used for missing assembly comparisons. private static string FormatAssemblyName(AssemblyName assemblyName) => $"{assemblyName.Name} v{assemblyName.Version}"; + + private static void LoadAssemblyIfMissing(string path) + { + try + { + AssemblyName? name = AssemblyName.GetAssemblyName(path); + // only check name to avoid identity problems + if (name != null && AppDomain.CurrentDomain.GetAssemblies().All(e => e.GetName().Name != name.Name)) + { + PluginLoader.Dependencies.Add(Assembly.Load(File.ReadAllBytes(path))); + } + } + finally + { + File.Delete(path); + } + } } \ No newline at end of file diff --git a/LabApi/Loader/PluginLoader.cs b/LabApi/Loader/PluginLoader.cs index 44bf5b2c..6a2f82dc 100644 --- a/LabApi/Loader/PluginLoader.cs +++ b/LabApi/Loader/PluginLoader.cs @@ -166,7 +166,7 @@ public static void LoadAllPlugins() /// <param name="files">The collection of assemblies to load.</param> public static void LoadPlugins(IEnumerable<FileInfo> files) { - List<(FileInfo File, Assembly Assembly)> plugins = []; + List<(string Path, Assembly Assembly)> plugins = []; foreach (FileInfo file in files) { @@ -181,8 +181,7 @@ public static void LoadPlugins(IEnumerable<FileInfo> files) ? Assembly.Load(File.ReadAllBytes(file.FullName), File.ReadAllBytes(pdb.FullName)) // Otherwise, we load the assembly without any debug information. : Assembly.Load(File.ReadAllBytes(file.FullName)); - - plugins.Add((file, pluginAssembly)); + plugins.Add((file.FullName, pluginAssembly)); } catch (Exception e) { @@ -191,42 +190,32 @@ public static void LoadPlugins(IEnumerable<FileInfo> files) } } - foreach ((FileInfo file, Assembly assembly) in plugins) + foreach ((string path, Assembly assembly) in plugins) { try { - // If the assembly has missing dependencies, we skip it. - if (AssemblyUtils.HasMissingDependencies(assembly, file.FullName, out Type[]? types)) - continue; - - InstantiatePlugins(types, assembly, file.FullName); + AssemblyUtils.ResolveEmbeddedResources(assembly); } catch (Exception e) { - Logger.Error($"{LoggerPrefix} Couldn't load the plugin inside '{file.FullName}'"); + Logger.Error($"{LoggerPrefix} Failed to resolve embedded resources for assembly '{path}'"); + LogMissingDependencies(assembly); Logger.Error(e); } } - } - private static void InstantiatePlugins(Type[] types, Assembly assembly, string filePath) - { - foreach (Type type in types) + foreach ((string path, Assembly assembly) in plugins) { - // We check if the type is derived from Plugin. - if (!type.IsSubclassOf(typeof(Plugin))) - continue; - - // We create an instance of the type and check if it was successfully created. - if (Activator.CreateInstance(type) is not Plugin plugin) - continue; - - // Set the file path - plugin.FilePath = filePath; - - // In that case, we add the plugin to the plugins list and log that it has been loaded. - Plugins.Add(plugin, assembly); - Logger.Info($"{LoggerPrefix} Successfully loaded {plugin.Name}"); + try + { + InstantiatePlugins(assembly.GetTypes(), assembly, path); + } + catch (Exception e) + { + Logger.Error($"{LoggerPrefix} Couldn't load the plugin inside '{path}'"); + LogMissingDependencies(assembly); + Logger.Error(e); + } } } @@ -346,4 +335,34 @@ private static string ResolvePath(string path) { return path.Replace("$port", Server.Port.ToString()); } + + private static void LogMissingDependencies(Assembly assembly) + { + IEnumerable<string> missing = AssemblyUtils.GetMissingDependencies(assembly); + if (missing.Any()) + { + Logger.Error($"{LoggerPrefix} Missing dependencies:\n{string.Join("\n", missing.Select(static x => $"-\t {x}"))}"); + } + } + + private static void InstantiatePlugins(Type[] types, Assembly assembly, string filePath) + { + foreach (Type type in types) + { + // We check if the type is derived from Plugin. + if (!type.IsSubclassOf(typeof(Plugin)) || type.IsAbstract) + continue; + + // We create an instance of the type and check if it was successfully created. + if (Activator.CreateInstance(type) is not Plugin plugin) + continue; + + // Set the file path + plugin.FilePath = filePath; + + // In that case, we add the plugin to the plugins list and log that it has been loaded. + Plugins.Add(plugin, assembly); + Logger.Info($"{LoggerPrefix} Successfully loaded {plugin.Name}"); + } + } } \ No newline at end of file From 8541cab5946142e95efc76b45810d3d0c62ba69b Mon Sep 17 00:00:00 2001 From: Cyn <181435937+xCynDev@users.noreply.github.com> Date: Tue, 9 Sep 2025 15:35:01 -0700 Subject: [PATCH 149/215] Make Player.GameObject nullable and null check ReferenceHub before accessing it. (#144) * Make Player.GameObject nullable and null check ReferenceHub before accessing it. * Don't use null propagation because it doesn't work with Unity --- LabApi/Features/Wrappers/Players/Player.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LabApi/Features/Wrappers/Players/Player.cs b/LabApi/Features/Wrappers/Players/Player.cs index 3c6b1100..d71401c8 100644 --- a/LabApi/Features/Wrappers/Players/Player.cs +++ b/LabApi/Features/Wrappers/Players/Player.cs @@ -143,7 +143,7 @@ internal Player(ReferenceHub referenceHub) /// <summary> /// Gets the player's <see cref="GameObject"/>. /// </summary> - public GameObject GameObject => ReferenceHub.gameObject; + public GameObject? GameObject => ReferenceHub ? ReferenceHub.gameObject : null; /// <summary> /// Gets whether the player is the host or server. From 5171564d9a3561d4fe4a7e639fbcf2d94e1b17c2 Mon Sep 17 00:00:00 2001 From: davidsebesta <david.sebesta@post.cz> Date: Mon, 15 Sep 2025 14:12:31 +0200 Subject: [PATCH 150/215] IsSpectatable negation --- LabApi/Features/Wrappers/Players/Player.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LabApi/Features/Wrappers/Players/Player.cs b/LabApi/Features/Wrappers/Players/Player.cs index 73c0819d..f3cddbf6 100644 --- a/LabApi/Features/Wrappers/Players/Player.cs +++ b/LabApi/Features/Wrappers/Players/Player.cs @@ -927,8 +927,8 @@ public List<Player> CurrentSpectators /// </remarks> public bool IsSpectatable { - get => SpectatableVisibilityManager.IsHidden(ReferenceHub); - set => SpectatableVisibilityManager.SetHidden(ReferenceHub, value); + get => !SpectatableVisibilityManager.IsHidden(ReferenceHub); + set => SpectatableVisibilityManager.SetHidden(ReferenceHub, !value); } /// <summary> From a77923ddc26f57d2d39b941458e4aee0ed387900 Mon Sep 17 00:00:00 2001 From: Naxefir <143349993+NaxefirYT@users.noreply.github.com> Date: Tue, 16 Sep 2025 00:28:08 +0300 Subject: [PATCH 151/215] Update Scp244Pickup.cs (#271) --- LabApi/Features/Wrappers/Pickups/Scp244Pickup.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LabApi/Features/Wrappers/Pickups/Scp244Pickup.cs b/LabApi/Features/Wrappers/Pickups/Scp244Pickup.cs index 79e18475..dd92874b 100644 --- a/LabApi/Features/Wrappers/Pickups/Scp244Pickup.cs +++ b/LabApi/Features/Wrappers/Pickups/Scp244Pickup.cs @@ -65,7 +65,7 @@ public Scp244State State } /// <summary> - /// Gets or set the size of the SCP-244 cloud. + /// Gets the size of the SCP-244 cloud. /// </summary> public float SizePercent => Base.CurrentSizePercent; From a50115ad5e316f914f96ff8b4f8d831abc8b44b6 Mon Sep 17 00:00:00 2001 From: jesusqc <contact@jesusqc.es> Date: Mon, 15 Sep 2025 23:31:56 +0200 Subject: [PATCH 152/215] Version Bump --- LabApi/LabApi.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LabApi/LabApi.csproj b/LabApi/LabApi.csproj index 311ab567..eb703f50 100644 --- a/LabApi/LabApi.csproj +++ b/LabApi/LabApi.csproj @@ -6,7 +6,7 @@ <PlatformTarget>x64</PlatformTarget> <LangVersion>12.0</LangVersion> - <Version>1.1.2</Version> + <Version>1.1.3</Version> <AssemblyName>LabApi</AssemblyName> <PackageId>Northwood.LabAPI</PackageId> From 16fd2b58d32ebc6b1bd5301e0d71496838203077 Mon Sep 17 00:00:00 2001 From: jesusqc <contact@jesusqc.es> Date: Sat, 27 Sep 2025 15:42:42 +0200 Subject: [PATCH 153/215] Replaced MaxSergeants and MaxCaptains with SergeantsPercentage and CaptainsPercentage --- .../Facility/Respawning/Waves/MtfWave.cs | 32 ++++++++++++++++--- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Respawning/Waves/MtfWave.cs b/LabApi/Features/Wrappers/Facility/Respawning/Waves/MtfWave.cs index cfc94fbb..2d461d61 100644 --- a/LabApi/Features/Wrappers/Facility/Respawning/Waves/MtfWave.cs +++ b/LabApi/Features/Wrappers/Facility/Respawning/Waves/MtfWave.cs @@ -1,5 +1,7 @@ -using Respawning.Config; +using LabApi.Features.Console; +using Respawning.Config; using Respawning.Waves; +using System; namespace LabApi.Features.Wrappers; @@ -23,19 +25,39 @@ internal MtfWave(NtfSpawnWave wave) /// <summary> /// Gets or sets the amount of sergeants that can spawn with the wave. /// </summary> + [Obsolete("Use SergeantsPercentage instead", true)] public int MaxSergeants { - get => Base.MaxSergeants; - set => Base.MaxSergeants = value; + get => 0; + set => Logger.Error("Plugin Error. Cannot set MaxSergeants, use SergeantsPercentage instead."); + } + + /// <summary> + /// Gets the percentage of sergeants that can spawn with the wave. + /// </summary> + public float SergeantsPercentage + { + get => Base.SergeantPercent; + set => Base.SergeantPercent = value; } /// <summary> /// Gets or sets the amount of captains that can spawn with the wave. /// </summary> + [Obsolete("Use CaptainsPercentage instead", true)] public int MaxCaptains { - get => Base.MaxCaptains; - set => Base.MaxCaptains = value; + get => 0; + set => Logger.Error("Plugin Error. Cannot set MaxCaptains, use CaptainsPercentage instead."); + } + + /// <summary> + /// Gets the percentage of captains that can spawn with the wave. + /// </summary> + public float CaptainsPercentage + { + get => Base.CaptainPercent; + set => Base.CaptainPercent = value; } /// <inheritdoc/> From 3afd9be830794701f560def6b556d4b589dc9239 Mon Sep 17 00:00:00 2001 From: jesusqc <contact@jesusqc.es> Date: Tue, 30 Sep 2025 00:36:56 +0200 Subject: [PATCH 154/215] gitlab templates --- .github/README.md | 45 +++++++++++++++++++ .gitlab/issue_templates/New Bug.md | 34 ++++++++++++++ .gitlab/issue_templates/New Idea.md | 18 ++++++++ .gitlab/issue_templates/New Task - Docless.md | 17 +++++++ .gitlab/issue_templates/New Task.md | 27 +++++++++++ .../MR Template - Docless.md | 20 +++++++++ .../merge_request_templates/MR Template.md | 22 +++++++++ README.md | 15 ------- 8 files changed, 183 insertions(+), 15 deletions(-) create mode 100644 .github/README.md create mode 100644 .gitlab/issue_templates/New Bug.md create mode 100644 .gitlab/issue_templates/New Idea.md create mode 100644 .gitlab/issue_templates/New Task - Docless.md create mode 100644 .gitlab/issue_templates/New Task.md create mode 100644 .gitlab/merge_request_templates/MR Template - Docless.md create mode 100644 .gitlab/merge_request_templates/MR Template.md delete mode 100644 README.md diff --git a/.github/README.md b/.github/README.md new file mode 100644 index 00000000..8aaaa1b0 --- /dev/null +++ b/.github/README.md @@ -0,0 +1,45 @@ +<p align="center"> + <a href="https://scpslgame.com"> + <picture> + <source srcset="https://github.com/user-attachments/assets/04f437c8-7fa9-4da9-bf71-fa39db141cf2" media="(prefers-color-scheme: dark)"> + <img src="https://github.com/user-attachments/assets/aa811a11-2b8e-4397-972d-27c7305318d7" width="125" alt="NW logo"> + </picture> + </a> +</p> + +<h1 align="center">LabAPI</h1> +<h6 align="center"><a href="https://store.steampowered.com/app/700330/SCP_Secret_Laboratory/">SCP: Secret Laboratory</a>'s official server-side modding framework.</h6> +<div align="center"> + <a href="https://plugins.scpslgame.com">Plugins</a> + <span> - </span> + <a href="https://github.com/northwood-studios/LabAPI/wiki">Docs</a> + <span> - </span> + <a href="https://github.com/northwood-studios/LabAPI/issues">Report Bug</a> + <span> - </span> + <a href="https://discord.gg/scpsl">Discord</a> + <p></p> +</div> + +<div align="center"> + +[![Version](https://img.shields.io/github/v/release/northwood-studios/LabAPI?sort=semver&style=flat-square&color=8DBBE9&label=Version)]() +[![License](https://img.shields.io/github/license/northwood-studios/LabAPI?style=flat-square&label=License&color=df967f)]() +[![Contributors](https://img.shields.io/github/contributors-anon/northwood-studios/LabAPI?color=90E59A&style=flat-square&label=Contributors)]() +[![GitHub Issues](https://img.shields.io/github/issues/northwood-studios/LabAPI.svg?style=flat-square&label=Issues&color=d77982)](https://github.com/northwood-studios/LabAPI/issues) +[![Discord](https://img.shields.io/discord/330432627649544202?color=738adb&label=Discord&logo=discord&logoColor=white&style=flat-square)](https://discord.gg/scpsl) + +</div> + +The LabAPI project is **[SCP: Secret Laboratory](https://store.steampowered.com/app/700330/SCP_Secret_Laboratory/)**'s official server-side plugin loader and framework. It facilitates development of plugins by providing wrappers and events around various game mechanics found throughout the game. + +## Documentation +Code should have self-explanatory documentation, but there's only so much you can explain through comments! +- For guides, tips and tricks, our main source of documentation can be found [here](https://github.com/northwood-studios/LabAPI/wiki). +- For a more practical approach, examples can be found [here](https://github.com/northwood-studios/LabAPI/tree/master/LabApi.Examples). + +## Installation +All **SCP: SL Dedicated Server** builds are bundled with a compiled **`LabAPI.dll`**, so you don't need to install it if you are hosting a server. + +However, [releases](https://github.com/northwood-studios/LabAPI/releases) may occasionally occur *before* the dedicated server is updated, while we advice you wait for an official update, you can always apply the updated release manually. + +To do so, you should update the **`LabAPI.dll`** file located within: `%DEDICATED_SERVER_PATH%/SCPSL_Data/Managed/`. \ No newline at end of file diff --git a/.gitlab/issue_templates/New Bug.md b/.gitlab/issue_templates/New Bug.md new file mode 100644 index 00000000..a1b4ffcd --- /dev/null +++ b/.gitlab/issue_templates/New Bug.md @@ -0,0 +1,34 @@ +> **New Issue Guidelines:** (For you! The writer :writing_hand: ) +> - Make sure to only choose one priority level, the bottom of this template has all labels you'll need. Delete the ones you don't need! +> - Mention the affected system in this issue's title. Something like `[RA] Using X throws an exception` or `[Intercom] Talking blows your computer up`. +> - In some cases, remember to verify with the team in charge of this kind of feature. (Examples: Art, Programming, Game Design) + +> **Choose one task priority level:** *(You can delete this line as well)* +/label ~"P1 - Critical" +/label ~"P2 - Priority Issue" +/label ~"P3 - Regular Priority" +/label ~"P4 - Low Priority" + +## Description +> A description about what the issue / bug is. How it affects players. And finally, how it's supposed to function. + +## Replication Steps & Requirements + +### Requirements: +- Have 2 or more players online, they'll be called Hubert & You. (Example) +- Before entering the game, change your Graphic Settings to **Low**. (Example) + +### Replication Steps: +- You must join the server first, without Hubert in it. +- Hubert must then join after you. +- When Hubert spawns, he will appear as a giant pink-textured role. + +## Attachments +> Any sort of video, image, client/server logs, just proof of the reported issue. For example: +- Related issues: #244 #123 #21 #50 +- Replication video: https://www.youtube.com/watch?v=2Q_ZzBGPdqE + +/label ~bug +/label ~todo + +/cc @jesusqc \ No newline at end of file diff --git a/.gitlab/issue_templates/New Idea.md b/.gitlab/issue_templates/New Idea.md new file mode 100644 index 00000000..dc6854b1 --- /dev/null +++ b/.gitlab/issue_templates/New Idea.md @@ -0,0 +1,18 @@ +> **New Issue Guidelines:** (For you! The writer :writing_hand: ) +> - Mention the affected system in this issue's title. Something like `[RA] Custom Menus Idea` or `[Map] New Map Generation Algorithm Ideas`. + +## Description +> A description of what you would like to see implemented, and perhaps how. Can be as vague and informal as you want. However, being descriptive is always appreciated. 😉 + +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + +## Notes +> These should serve as a guide of different ideas or concerns you may have regarding task, providing some insight of your vision to the programmer that may work on it. +- Example1. +- Example2. + +# Status +- [ ] **Approved for implementation by LabAPI's Management.** + +/label ~experimental +/confidential \ No newline at end of file diff --git a/.gitlab/issue_templates/New Task - Docless.md b/.gitlab/issue_templates/New Task - Docless.md new file mode 100644 index 00000000..55f021e0 --- /dev/null +++ b/.gitlab/issue_templates/New Task - Docless.md @@ -0,0 +1,17 @@ +/label ~"P1 - Critical" +/label ~"P2 - Priority Issue" +/label ~"P3 - Regular Priority" +/label ~"P4 - Low Priority" + +## Description + + +## Task Expectations/Check-list +- [ ] + +## Assets +- Design Document: + +/label ~"Task / Bounty" +/label ~todo +/confidential \ No newline at end of file diff --git a/.gitlab/issue_templates/New Task.md b/.gitlab/issue_templates/New Task.md new file mode 100644 index 00000000..18ac27d6 --- /dev/null +++ b/.gitlab/issue_templates/New Task.md @@ -0,0 +1,27 @@ +> **New Issue Guidelines:** (For you! The writer :writing_hand: ) +> - Make sure to only choose one priority level, the bottom of this template has all labels you'll need. Delete the ones you don't need! +> - Mention the affected system in this issue's title. Something like `[RA] Using X throws an exception` or `[Intercom] Talking blows your computer up`. + +> **Choose one task priority level:** *(You can delete this line as well)* +/label ~"P1 - Critical" +/label ~"P2 - Priority Issue" +/label ~"P3 - Regular Priority" +/label ~"P4 - Low Priority" + +## Description +> A description about what the task is and possibly an idea of how to implement if possible. + +## Task Expectations/Check-list +> **As always,** read the design document before starting work on it (if one was attached), the check-list below is merely done to help assignees follow some steps and not get lost. :smile: +- [ ] Text. +- [ ] Text2. +- [ ] Text3. + +## Assets +> Any assets that the assignee will need to complete this task / implement this feature. Make sure to include the **Design Document** here. +- Asset1. +- Asset2. + +/label ~"Task / Bounty" +/label ~todo +/confidential \ No newline at end of file diff --git a/.gitlab/merge_request_templates/MR Template - Docless.md b/.gitlab/merge_request_templates/MR Template - Docless.md new file mode 100644 index 00000000..3de19d68 --- /dev/null +++ b/.gitlab/merge_request_templates/MR Template - Docless.md @@ -0,0 +1,20 @@ +## Changes + +### Changelog +```yml +- +``` + +## Relevant Issues / Tasks + +Resolves #X + +## Notes (Optional) + + + +# **Status** +- [ ] **Approved by QA.** + +/ready +/done \ No newline at end of file diff --git a/.gitlab/merge_request_templates/MR Template.md b/.gitlab/merge_request_templates/MR Template.md new file mode 100644 index 00000000..a75c866a --- /dev/null +++ b/.gitlab/merge_request_templates/MR Template.md @@ -0,0 +1,22 @@ +## Changes + +### Changelog +> These should stay technical, you don't have to mention exactly what you did step-by-step, but providing something for other programmers to check on later is preferred. Studio Staff in charge of public announcements will use this changelog to create a simplified version of it. +```yml +- Text +``` + +## Relevant Issues / Tasks (Optional) + +> Replace the `X` with the issue ID you wish to automatically close when this is merged. +Resolves #X + +## Notes (Optional) + +> Write down any additional related notes programmers or the current lead programmer should be aware of regarding this merge request. + +# **Status** +- [ ] **Approved by QA.** + +/ready +/done \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index be23938e..00000000 --- a/README.md +++ /dev/null @@ -1,15 +0,0 @@ -[![GitHub release](https://flat.badgen.net/github/release/northwood-studios/LabAPI/)](https://github.com/northwood-studios/NwPluginAPI/releases/) [![NuGet](https://flat.badgen.net/nuget/v/Northwood.LabAPI/latest)](https://www.nuget.org/packages/Northwood.LabAPI/) [![License](https://flat.badgen.net/github/license/northwood-studios/LabAPI)](https://github.com/northwood-studios/LabAPI/blob/master/LICENSE) [![Discord Invitation](https://flat.badgen.net/discord/members/scpsl?icon=discord)](https://discord.gg/scpsl) -# LabAPI -The LabAPI project is **[SCP: Secret Laboratory](https://store.steampowered.com/app/700330/SCP_Secret_Laboratory/)**'s official server-side plugin loader and framework. It facilitates development of plugins by providing wrappers and events around various game mechanics found throughout the game. - -## Documentation -Code should have self-explanatory documentation, but there's only so much you can explain through comments! -- For guides, tips and tricks, our main source of documentation can be found [here](https://github.com/northwood-studios/LabAPI/wiki). -- For a more practical approach, examples can be found [here](https://github.com/northwood-studios/LabAPI/tree/master/LabApi.Examples). - -## Installation -All **SCP: SL Dedicated Server** builds are bundled with a compiled **`LabAPI.dll`**, so you don't need to install it if you are hosting a server. - -However, [releases](https://github.com/northwood-studios/LabAPI/releases) may occasionally occur *before* the dedicated server is updated, while we advice you wait for an official update, you can always apply the updated release manually. - -To do so, you should update the **`LabAPI.dll`** file located within: `%DEDICATED_SERVER_PATH%/SCPSL_Data/Managed/`. \ No newline at end of file From 90e73de3caa49b453981514353ca3e2e9834da8f Mon Sep 17 00:00:00 2001 From: jesusqc <contact@jesusqc.es> Date: Tue, 30 Sep 2025 19:09:22 +0200 Subject: [PATCH 155/215] README changes --- LabApi/README.md | 1 + README.md | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 120000 LabApi/README.md create mode 100644 README.md diff --git a/LabApi/README.md b/LabApi/README.md new file mode 120000 index 00000000..457d2fe8 --- /dev/null +++ b/LabApi/README.md @@ -0,0 +1 @@ +C:/Users/jesusqc/RiderProjects/LabAPI-Internal/.github/README.md \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 00000000..8aaaa1b0 --- /dev/null +++ b/README.md @@ -0,0 +1,45 @@ +<p align="center"> + <a href="https://scpslgame.com"> + <picture> + <source srcset="https://github.com/user-attachments/assets/04f437c8-7fa9-4da9-bf71-fa39db141cf2" media="(prefers-color-scheme: dark)"> + <img src="https://github.com/user-attachments/assets/aa811a11-2b8e-4397-972d-27c7305318d7" width="125" alt="NW logo"> + </picture> + </a> +</p> + +<h1 align="center">LabAPI</h1> +<h6 align="center"><a href="https://store.steampowered.com/app/700330/SCP_Secret_Laboratory/">SCP: Secret Laboratory</a>'s official server-side modding framework.</h6> +<div align="center"> + <a href="https://plugins.scpslgame.com">Plugins</a> + <span> - </span> + <a href="https://github.com/northwood-studios/LabAPI/wiki">Docs</a> + <span> - </span> + <a href="https://github.com/northwood-studios/LabAPI/issues">Report Bug</a> + <span> - </span> + <a href="https://discord.gg/scpsl">Discord</a> + <p></p> +</div> + +<div align="center"> + +[![Version](https://img.shields.io/github/v/release/northwood-studios/LabAPI?sort=semver&style=flat-square&color=8DBBE9&label=Version)]() +[![License](https://img.shields.io/github/license/northwood-studios/LabAPI?style=flat-square&label=License&color=df967f)]() +[![Contributors](https://img.shields.io/github/contributors-anon/northwood-studios/LabAPI?color=90E59A&style=flat-square&label=Contributors)]() +[![GitHub Issues](https://img.shields.io/github/issues/northwood-studios/LabAPI.svg?style=flat-square&label=Issues&color=d77982)](https://github.com/northwood-studios/LabAPI/issues) +[![Discord](https://img.shields.io/discord/330432627649544202?color=738adb&label=Discord&logo=discord&logoColor=white&style=flat-square)](https://discord.gg/scpsl) + +</div> + +The LabAPI project is **[SCP: Secret Laboratory](https://store.steampowered.com/app/700330/SCP_Secret_Laboratory/)**'s official server-side plugin loader and framework. It facilitates development of plugins by providing wrappers and events around various game mechanics found throughout the game. + +## Documentation +Code should have self-explanatory documentation, but there's only so much you can explain through comments! +- For guides, tips and tricks, our main source of documentation can be found [here](https://github.com/northwood-studios/LabAPI/wiki). +- For a more practical approach, examples can be found [here](https://github.com/northwood-studios/LabAPI/tree/master/LabApi.Examples). + +## Installation +All **SCP: SL Dedicated Server** builds are bundled with a compiled **`LabAPI.dll`**, so you don't need to install it if you are hosting a server. + +However, [releases](https://github.com/northwood-studios/LabAPI/releases) may occasionally occur *before* the dedicated server is updated, while we advice you wait for an official update, you can always apply the updated release manually. + +To do so, you should update the **`LabAPI.dll`** file located within: `%DEDICATED_SERVER_PATH%/SCPSL_Data/Managed/`. \ No newline at end of file From d0d641a0e20cad96af098a1b88331d0d0be57958 Mon Sep 17 00:00:00 2001 From: Lumi <me@jxtq.moe> Date: Fri, 3 Oct 2025 14:17:16 +0100 Subject: [PATCH 156/215] feat: new events --- .../ScpEvents/ScpHumeShieldBroken.cs | 23 +++++++++++++++++++ .../DeadmanSequenceActivatingEventArgs.cs | 14 +++++++++++ .../Handlers/ScpEvents.EventHandlers.cs | 14 +++++++++++ .../Handlers/ServerEvents.EventHandlers.cs | 15 ++++++++++++ 4 files changed, 66 insertions(+) create mode 100644 LabApi/Events/Arguments/ScpEvents/ScpHumeShieldBroken.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/DeadmanSequenceActivatingEventArgs.cs create mode 100644 LabApi/Events/Handlers/ScpEvents.EventHandlers.cs diff --git a/LabApi/Events/Arguments/ScpEvents/ScpHumeShieldBroken.cs b/LabApi/Events/Arguments/ScpEvents/ScpHumeShieldBroken.cs new file mode 100644 index 00000000..8170904e --- /dev/null +++ b/LabApi/Events/Arguments/ScpEvents/ScpHumeShieldBroken.cs @@ -0,0 +1,23 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.ScpEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ScpEvents.ScpHumeShieldBroken"/> event. +/// </summary> +public class ScpHumeShieldBroken : EventArgs, IPlayerEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="ScpHumeShieldBroken"/> class. + /// </summary> + /// <param name="player">The player SCP whom hume shield broke.</param> + public ScpHumeShieldBroken(ReferenceHub player) + { + Player = Player.Get(player); + } + + /// <inheritdoc/> + public Player Player { get; } +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/ServerEvents/DeadmanSequenceActivatingEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/DeadmanSequenceActivatingEventArgs.cs new file mode 100644 index 00000000..6f079cea --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/DeadmanSequenceActivatingEventArgs.cs @@ -0,0 +1,14 @@ +using LabApi.Events.Arguments.Interfaces; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.DeadmanSequenceActivating"/> event. +/// </summary> +public class DeadmanSequenceActivatingEventArgs : EventArgs, ICancellableEvent +{ + /// <inheritdoc/> + /// <remarks>Will reset Deadman Sequence timer back to 0 if false.</remarks> + public bool IsAllowed { get; set; } = true; +} \ No newline at end of file diff --git a/LabApi/Events/Handlers/ScpEvents.EventHandlers.cs b/LabApi/Events/Handlers/ScpEvents.EventHandlers.cs new file mode 100644 index 00000000..005a11cf --- /dev/null +++ b/LabApi/Events/Handlers/ScpEvents.EventHandlers.cs @@ -0,0 +1,14 @@ +using LabApi.Events.Arguments.ScpEvents; + +namespace LabApi.Events.Handlers; + +/// <summary> +/// Handles all events related to SCPs. +/// </summary> +public static partial class ScpEvents +{ + /// <summary> + /// Gets called when an SCP has their hume shield broken. + /// </summary> + public static event LabEventHandler<ScpHumeShieldBroken>? HumeShieldBroken; +} \ No newline at end of file diff --git a/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs b/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs index 4ffb37d9..d8f4b697 100644 --- a/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs +++ b/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs @@ -17,6 +17,21 @@ public static partial class ServerEvents /// </summary> public static event LabEventHandler? RoundRestarted; + /// <summary> + /// Gets called when the server shuts down. + /// </summary> + public static event LabEventHandler? Shutdown; + + /// <summary> + /// Gets called when Deadman Sequence is activated + /// </summary> + public static event LabEventHandler? DeadmanSequenceActivated; + + /// <summary> + /// Gets called when Deadman sequence is activating. + /// </summary> + public static event LabEventHandler<DeadmanSequenceActivatingEventArgs>? DeadmanSequenceActivating; + /// <summary> /// Gets called when round end conditions are checked. /// </summary> From 3b138cf92eb94a41ef6a436a9f4e339fb4e820f5 Mon Sep 17 00:00:00 2001 From: Lumi <me@jxtq.moe> Date: Fri, 3 Oct 2025 18:21:53 +0100 Subject: [PATCH 157/215] docs: better spacing and langwording --- .../ServerEvents/DeadmanSequenceActivatingEventArgs.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LabApi/Events/Arguments/ServerEvents/DeadmanSequenceActivatingEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/DeadmanSequenceActivatingEventArgs.cs index 6f079cea..446482a0 100644 --- a/LabApi/Events/Arguments/ServerEvents/DeadmanSequenceActivatingEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/DeadmanSequenceActivatingEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.ServerEvents; /// </summary> public class DeadmanSequenceActivatingEventArgs : EventArgs, ICancellableEvent { - /// <inheritdoc/> - /// <remarks>Will reset Deadman Sequence timer back to 0 if false.</remarks> + /// <inheritdoc /> + /// <remarks>Will reset Deadman Sequence timer back to 0 if <see langword="false"/>.</remarks> public bool IsAllowed { get; set; } = true; } \ No newline at end of file From 71ceb8b5d2cc01e83dde6345576f116931ff9a9f Mon Sep 17 00:00:00 2001 From: Lumi <me@jxtq.moe> Date: Sat, 4 Oct 2025 10:20:19 +0100 Subject: [PATCH 158/215] fix: event args naming scheme --- ...pHumeShieldBroken.cs => ScpHumeShieldBrokenEventArgs.cs} | 6 +++--- LabApi/Events/Handlers/ScpEvents.EventHandlers.cs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) rename LabApi/Events/Arguments/ScpEvents/{ScpHumeShieldBroken.cs => ScpHumeShieldBrokenEventArgs.cs} (77%) diff --git a/LabApi/Events/Arguments/ScpEvents/ScpHumeShieldBroken.cs b/LabApi/Events/Arguments/ScpEvents/ScpHumeShieldBrokenEventArgs.cs similarity index 77% rename from LabApi/Events/Arguments/ScpEvents/ScpHumeShieldBroken.cs rename to LabApi/Events/Arguments/ScpEvents/ScpHumeShieldBrokenEventArgs.cs index 8170904e..51468085 100644 --- a/LabApi/Events/Arguments/ScpEvents/ScpHumeShieldBroken.cs +++ b/LabApi/Events/Arguments/ScpEvents/ScpHumeShieldBrokenEventArgs.cs @@ -7,13 +7,13 @@ namespace LabApi.Events.Arguments.ScpEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.ScpEvents.ScpHumeShieldBroken"/> event. /// </summary> -public class ScpHumeShieldBroken : EventArgs, IPlayerEvent +public class ScpHumeShieldBrokenEventArgs : EventArgs, IPlayerEvent { /// <summary> - /// Initializes a new instance of the <see cref="ScpHumeShieldBroken"/> class. + /// Initializes a new instance of the <see cref="ScpHumeShieldBrokenEventArgs"/> class. /// </summary> /// <param name="player">The player SCP whom hume shield broke.</param> - public ScpHumeShieldBroken(ReferenceHub player) + public ScpHumeShieldBrokenEventArgs(ReferenceHub player) { Player = Player.Get(player); } diff --git a/LabApi/Events/Handlers/ScpEvents.EventHandlers.cs b/LabApi/Events/Handlers/ScpEvents.EventHandlers.cs index 005a11cf..1e1acac2 100644 --- a/LabApi/Events/Handlers/ScpEvents.EventHandlers.cs +++ b/LabApi/Events/Handlers/ScpEvents.EventHandlers.cs @@ -10,5 +10,5 @@ public static partial class ScpEvents /// <summary> /// Gets called when an SCP has their hume shield broken. /// </summary> - public static event LabEventHandler<ScpHumeShieldBroken>? HumeShieldBroken; + public static event LabEventHandler<ScpHumeShieldBrokenEventArgs>? HumeShieldBroken; } \ No newline at end of file From 15c0eef6fda59ecad8703820d56b032de7056437 Mon Sep 17 00:00:00 2001 From: Lumi <me@jxtq.moe> Date: Sat, 4 Oct 2025 10:20:31 +0100 Subject: [PATCH 159/215] docs: fix inconsistencies --- LabApi/Events/Handlers/ServerEvents.EventHandlers.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs b/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs index d8f4b697..fc86a31d 100644 --- a/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs +++ b/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs @@ -23,12 +23,12 @@ public static partial class ServerEvents public static event LabEventHandler? Shutdown; /// <summary> - /// Gets called when Deadman Sequence is activated + /// Gets called when Deadman Sequence is activated. /// </summary> public static event LabEventHandler? DeadmanSequenceActivated; /// <summary> - /// Gets called when Deadman sequence is activating. + /// Gets called when Deadman Sequence is activating. /// </summary> public static event LabEventHandler<DeadmanSequenceActivatingEventArgs>? DeadmanSequenceActivating; From f84e2ef9f0b42ae4398c866a3181e3d1e08e3116 Mon Sep 17 00:00:00 2001 From: jesusqc <contact@jesusqc.es> Date: Sat, 4 Oct 2025 18:10:53 +0200 Subject: [PATCH 160/215] Scp173 Snap Events --- .../LogAll/LogPlugin/MyCustomEventsHandler.cs | 10 +++++ .../Scp173Events/Scp173SnappedEventArgs.cs | 32 ++++++++++++++++ .../Scp173Events/Scp173SnappingEventArgs.cs | 38 +++++++++++++++++++ .../Handlers/Scp173Events.EventHandlers.cs | 10 +++++ 4 files changed, 90 insertions(+) create mode 100644 LabApi/Events/Arguments/Scp173Events/Scp173SnappedEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp173Events/Scp173SnappingEventArgs.cs diff --git a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs index 8cc52f5b..eb7c2665 100644 --- a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs +++ b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs @@ -1150,6 +1150,16 @@ public override void OnScp173PlayedSound(Scp173PlayedSoundEventArgs ev) Logger.Info($"{nameof(OnScp173PlayedSound)} triggered by {ev.Player.UserId}"); } + public override void OnScp173Snapped(Scp173SnappedEventArgs ev) + { + Logger.Info($"{nameof(OnScp173Snapped)} triggered by {ev.Player.UserId} targeting {ev.Target.UserId}"); + } + + public override void OnScp173Snapping(Scp173SnappingEventArgs ev) + { + Logger.Info($"{nameof(OnScp173Snapping)} triggered by {ev.Player.UserId} targeting {ev.Target.UserId}"); + } + public override void OnScp3114StrangleAborting(Scp3114StrangleAbortingEventArgs ev) { Logger.Info($"{nameof(OnScp3114StrangleAborting)} triggered by {ev.Player.UserId}"); diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173SnappedEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173SnappedEventArgs.cs new file mode 100644 index 00000000..bc97f889 --- /dev/null +++ b/LabApi/Events/Arguments/Scp173Events/Scp173SnappedEventArgs.cs @@ -0,0 +1,32 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp173Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp173Events.Snapped"/> event. +/// </summary> +public class Scp173SnappedEventArgs : EventArgs, IPlayerEvent, ITargetEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp173SnappedEventArgs"/> class. + /// </summary> + /// <param name="hub">The SCP-173 player.</param> + /// <param name="target">The player that has been snapped.</param> + public Scp173SnappedEventArgs(ReferenceHub hub, ReferenceHub target) + { + Player = Player.Get(hub); + Target = Player.Get(target); + } + + /// <summary> + /// Gets the SCP-173 player instance. + /// </summary> + public Player Player { get; } + + /// <summary> + /// Gets the player that has been snapped. + /// </summary> + public Player Target { get; } +} diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173SnappingEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173SnappingEventArgs.cs new file mode 100644 index 00000000..e499dd11 --- /dev/null +++ b/LabApi/Events/Arguments/Scp173Events/Scp173SnappingEventArgs.cs @@ -0,0 +1,38 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp173Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp173Events.Snapping"/> event. +/// </summary> +public class Scp173SnappingEventArgs : EventArgs, IPlayerEvent, ITargetEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp173SnappingEventArgs"/> class. + /// </summary> + /// <param name="hub">The SCP-173 player.</param> + /// <param name="target">The player to snap.</param> + public Scp173SnappingEventArgs(ReferenceHub hub, ReferenceHub target) + { + IsAllowed = true; + Player = Player.Get(hub); + Target = Player.Get(target); + } + + /// <summary> + /// Gets the SCP-173 player instance. + /// </summary> + public Player Player { get; } + + /// <summary> + /// Gets the player to snap. + /// </summary> + public Player Target { get; set; } + + /// <summary> + /// Gets or sets whether the SCP-173 player can snap the target.<para/> + /// </summary> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Handlers/Scp173Events.EventHandlers.cs b/LabApi/Events/Handlers/Scp173Events.EventHandlers.cs index fef62eb3..a6886da6 100644 --- a/LabApi/Events/Handlers/Scp173Events.EventHandlers.cs +++ b/LabApi/Events/Handlers/Scp173Events.EventHandlers.cs @@ -66,4 +66,14 @@ public static partial class Scp173Events /// Gets called when SCP-173 has teleported. /// </summary> public static event LabEventHandler<Scp173TeleportedEventArgs>? Teleported; + + /// <summary> + /// Gets called when SCP-173 is attempting to snap a target. + /// </summary> + public static event LabEventHandler<Scp173SnappingEventArgs>? Snapping; + + /// <summary> + /// Gets called when SCP-173 has snapped a target. + /// </summary> + public static event LabEventHandler<Scp173SnappedEventArgs>? Snapped; } \ No newline at end of file From 612277e2b8eb5c0192aaa283c7a47c37e4ce3cd1 Mon Sep 17 00:00:00 2001 From: Jesus-QC <99-jesusqc@users.noreply.git.scpslgame.com> Date: Sun, 5 Oct 2025 12:56:26 +0200 Subject: [PATCH 161/215] Apply 1 suggestion(s) to 1 file(s) Co-authored-by: The Riptide <theriptideservers@gmail.com> --- LabApi/Events/Arguments/Scp173Events/Scp173SnappingEventArgs.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173SnappingEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173SnappingEventArgs.cs index e499dd11..d05edee4 100644 --- a/LabApi/Events/Arguments/Scp173Events/Scp173SnappingEventArgs.cs +++ b/LabApi/Events/Arguments/Scp173Events/Scp173SnappingEventArgs.cs @@ -27,7 +27,7 @@ public Scp173SnappingEventArgs(ReferenceHub hub, ReferenceHub target) public Player Player { get; } /// <summary> - /// Gets the player to snap. + /// Gets or sets the player to snap. /// </summary> public Player Target { get; set; } From a2cecee4f930db516f8a275a4adef41ec4a10fc0 Mon Sep 17 00:00:00 2001 From: SlejmUr <slejmur@protonmail.com> Date: Sun, 5 Oct 2025 13:41:09 +0200 Subject: [PATCH 162/215] Add CheckedHitmarker event Add Send/ing Hitmarker event Add log for new events. --- .../LogAll/LogPlugin/MyCustomEventsHandler.cs | 15 ++++++ .../PlayerCheckedHitmarkerEventArgs.cs | 47 +++++++++++++++++++ .../PlayerSendHitmarkerEventArgs.cs | 39 +++++++++++++++ .../PlayerSendingHitmarkerEventArgs.cs | 44 +++++++++++++++++ .../Handlers/PlayerEvents.EventHandlers.cs | 15 ++++++ 5 files changed, 160 insertions(+) create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerCheckedHitmarkerEventArgs.cs create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerSendHitmarkerEventArgs.cs create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerSendingHitmarkerEventArgs.cs diff --git a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs index 8cc52f5b..f7174af7 100644 --- a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs +++ b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs @@ -1654,6 +1654,21 @@ public override void OnScp127Talked(Scp127TalkedEventArgs ev) { Logger.Info($"{nameof(OnScp127Talked)} triggered by {ev.Scp127Item.CurrentOwner}"); } + + public override void OnPlayerCheckedHitmarker(PlayerCheckedHitmarkerEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerCheckedHitmarker)} triggered by {ev.Player} {ev.Victim}"); + } + + public override void OnPlayerSendHitmarker(PlayerSendHitmarkerEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerSendHitmarker)} triggered by {ev.Player} {ev.Size} {ev.PlayAudio}"); + } + + public override void OnPlayerSendingHitmarker(PlayerSendingHitmarkerEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerSendingHitmarker)} triggered by {ev.Player} {ev.Size} {ev.PlayAudio}"); + } #region Excluded Events diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerCheckedHitmarkerEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerCheckedHitmarkerEventArgs.cs new file mode 100644 index 00000000..dda42328 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerCheckedHitmarkerEventArgs.cs @@ -0,0 +1,47 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using PlayerStatsSystem; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.CheckedHitmarker"/> event. +/// </summary> +public class PlayerCheckedHitmarkerEventArgs : EventArgs, IPlayerEvent +{ + /// <summary> + /// Initializes a new instance for the <see cref="PlayerSendHitmarkerEventArgs"/> class. + /// </summary> + /// <param name="hub">The player that hitmarker should send.</param> + /// <param name="adh">The damage dealth to the <paramref name="victim"/>.</param> + /// <param name="victim">The player who got hurt by <paramref name="hub"/>.</param> + /// <param name="result">The reuslt of the check.</param> + public PlayerCheckedHitmarkerEventArgs(ReferenceHub hub, AttackerDamageHandler adh, ReferenceHub victim, bool result) + { + Player = Player.Get(hub); + DamageHandler = adh; + Victim = Player.Get(victim); + Result = result; + } + + /// <summary> + /// Gets the player that canceled the search on the toy. + /// </summary> + public Player Player { get; } + + /// <summary> + /// Gets the player that canceled the search on the toy. + /// </summary> + public Player Victim { get; } + + /// <summary> + /// Gets the damage handler. + /// </summary> + public AttackerDamageHandler DamageHandler { get; } + + /// <summary> + /// Gets the check result. + /// </summary> + public bool Result { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSendHitmarkerEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSendHitmarkerEventArgs.cs new file mode 100644 index 00000000..2b68547f --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSendHitmarkerEventArgs.cs @@ -0,0 +1,39 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.SendHitmarker"/> event. +/// </summary> +public class PlayerSendHitmarkerEventArgs : EventArgs, IPlayerEvent +{ + /// <summary> + /// Initializes a new instance for the <see cref="PlayerSendHitmarkerEventArgs"/> class. + /// </summary> + /// <param name="hub">The player that canceled the search on the toy.</param> + /// <param name="size">The target size multiplier.</param> + /// <param name="playAudio">The hitmarker sound effect play.</param> + public PlayerSendHitmarkerEventArgs(ReferenceHub hub, float size, bool playAudio) + { + Player = Player.Get(hub); + Size = size; + PlayAudio = playAudio; + } + + /// <summary> + /// Gets the player that canceled the search on the toy. + /// </summary> + public Player Player { get; } + + /// <summary> + /// Gets the target size multiplier. + /// </summary> + public float Size { get; } + + /// <summary> + /// Gets if the hitmarker sound effect play. + /// </summary> + public bool PlayAudio { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSendingHitmarkerEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSendingHitmarkerEventArgs.cs new file mode 100644 index 00000000..f078951b --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSendingHitmarkerEventArgs.cs @@ -0,0 +1,44 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.SendingHitmarker"/> event. +/// </summary> +public class PlayerSendingHitmarkerEventArgs : EventArgs, IPlayerEvent, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance for the <see cref="PlayerSendHitmarkerEventArgs"/> class. + /// </summary> + /// <param name="hub">The player that canceled the search on the toy.</param> + /// <param name="size">The target size multiplier.</param> + /// <param name="playAudio">The hitmarker sound effect play.</param> + public PlayerSendingHitmarkerEventArgs(ReferenceHub hub, float size, bool playAudio) + { + Player = Player.Get(hub); + Size = size; + PlayAudio = playAudio; + + IsAllowed = true; + } + + /// <summary> + /// Gets or sets the player that canceled the search on the toy. + /// </summary> + public Player Player { get; set; } + + /// <summary> + /// Gets or sets the target size multiplier. + /// </summary> + public float Size { get; set; } + + /// <summary> + /// Gets or sets if the hitmarker sound effect play. + /// </summary> + public bool PlayAudio { get; set; } + + /// <inheritdoc/> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs b/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs index b06c0de5..94383fa8 100644 --- a/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs +++ b/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs @@ -883,6 +883,21 @@ public static partial class PlayerEvents /// </summary> public static event LabEventHandler<PlayerInteractedWarheadLeverEventArgs>? InteractedWarheadLever; + /// <summary> + /// Gets called when player sending a hitmarker. + /// </summary> + public static event LabEventHandler<PlayerSendingHitmarkerEventArgs>? SendingHitmarker; + + /// <summary> + /// Gets called when player sent a hitmarker. + /// </summary> + public static event LabEventHandler<PlayerSendHitmarkerEventArgs>? SendHitmarker; + + /// <summary> + /// Gets called when player checked a hitmarker permission. + /// </summary> + public static event LabEventHandler<PlayerCheckedHitmarkerEventArgs>? CheckedHitmarker; + #endregion #region Spectating From 3fa2718e00dc3aa08d3a8b54346a924445a4f576 Mon Sep 17 00:00:00 2001 From: SlejmUr <slejmur@protonmail.com> Date: Mon, 6 Oct 2025 11:09:44 +0200 Subject: [PATCH 163/215] Fix docs. SendHitmarker to SentHitmarker --- .../LogAll/LogPlugin/MyCustomEventsHandler.cs | 13 +++++++++---- .../PlayerEvents/PlayerCheckedHitmarkerEventArgs.cs | 6 +++--- .../PlayerEvents/PlayerSendingHitmarkerEventArgs.cs | 6 +++--- ...EventArgs.cs => PlayerSentHitmarkerEventArgs.cs} | 12 ++++++------ .../Events/Handlers/PlayerEvents.EventHandlers.cs | 2 +- 5 files changed, 22 insertions(+), 17 deletions(-) rename LabApi/Events/Arguments/PlayerEvents/{PlayerSendHitmarkerEventArgs.cs => PlayerSentHitmarkerEventArgs.cs} (70%) diff --git a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs index f7174af7..d080add6 100644 --- a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs +++ b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs @@ -20,6 +20,7 @@ namespace LogPlugin; internal class MyCustomEventsHandler : CustomEventsHandler { + /* public override void OnPlayerActivatingGenerator(PlayerActivatingGeneratorEventArgs ev) { Logger.Info($"{nameof(OnPlayerActivatingGenerator)} triggered by {ev.Player.UserId}"); @@ -1654,20 +1655,24 @@ public override void OnScp127Talked(Scp127TalkedEventArgs ev) { Logger.Info($"{nameof(OnScp127Talked)} triggered by {ev.Scp127Item.CurrentOwner}"); } - + */ public override void OnPlayerCheckedHitmarker(PlayerCheckedHitmarkerEventArgs ev) { - Logger.Info($"{nameof(OnPlayerCheckedHitmarker)} triggered by {ev.Player} {ev.Victim}"); + Logger.Info($"{nameof(OnPlayerCheckedHitmarker)} triggered by {ev.Player} {ev.Victim} {ev.Result}"); } - public override void OnPlayerSendHitmarker(PlayerSendHitmarkerEventArgs ev) + public override void OnPlayerSentHitmarker(PlayerSentHitmarkerEventArgs ev) { - Logger.Info($"{nameof(OnPlayerSendHitmarker)} triggered by {ev.Player} {ev.Size} {ev.PlayAudio}"); + Logger.Info($"{nameof(OnPlayerSentHitmarker)} triggered by {ev.Player} {ev.Size} {ev.PlayAudio}"); } public override void OnPlayerSendingHitmarker(PlayerSendingHitmarkerEventArgs ev) { Logger.Info($"{nameof(OnPlayerSendingHitmarker)} triggered by {ev.Player} {ev.Size} {ev.PlayAudio}"); + if (ev.Player.Role is PlayerRoles.RoleTypeId.Scp939) + { + ev.IsAllowed = false; + } } #region Excluded Events diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerCheckedHitmarkerEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerCheckedHitmarkerEventArgs.cs index dda42328..2369e710 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerCheckedHitmarkerEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerCheckedHitmarkerEventArgs.cs @@ -11,7 +11,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; public class PlayerCheckedHitmarkerEventArgs : EventArgs, IPlayerEvent { /// <summary> - /// Initializes a new instance for the <see cref="PlayerSendHitmarkerEventArgs"/> class. + /// Initializes a new instance for the <see cref="PlayerSentHitmarkerEventArgs"/> class. /// </summary> /// <param name="hub">The player that hitmarker should send.</param> /// <param name="adh">The damage dealth to the <paramref name="victim"/>.</param> @@ -26,12 +26,12 @@ public PlayerCheckedHitmarkerEventArgs(ReferenceHub hub, AttackerDamageHandler a } /// <summary> - /// Gets the player that canceled the search on the toy. + /// Gets the player that sending the hitmarker. /// </summary> public Player Player { get; } /// <summary> - /// Gets the player that canceled the search on the toy. + /// Gets the player that provides the hitmarker. /// </summary> public Player Victim { get; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSendingHitmarkerEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSendingHitmarkerEventArgs.cs index f078951b..b406a079 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSendingHitmarkerEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSendingHitmarkerEventArgs.cs @@ -10,9 +10,9 @@ namespace LabApi.Events.Arguments.PlayerEvents; public class PlayerSendingHitmarkerEventArgs : EventArgs, IPlayerEvent, ICancellableEvent { /// <summary> - /// Initializes a new instance for the <see cref="PlayerSendHitmarkerEventArgs"/> class. + /// Initializes a new instance for the <see cref="PlayerSentHitmarkerEventArgs"/> class. /// </summary> - /// <param name="hub">The player that canceled the search on the toy.</param> + /// <param name="hub">The player that sending the hitmark.</param> /// <param name="size">The target size multiplier.</param> /// <param name="playAudio">The hitmarker sound effect play.</param> public PlayerSendingHitmarkerEventArgs(ReferenceHub hub, float size, bool playAudio) @@ -25,7 +25,7 @@ public PlayerSendingHitmarkerEventArgs(ReferenceHub hub, float size, bool playAu } /// <summary> - /// Gets or sets the player that canceled the search on the toy. + /// Gets or sets the player that sending the hitmark. /// </summary> public Player Player { get; set; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSendHitmarkerEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSentHitmarkerEventArgs.cs similarity index 70% rename from LabApi/Events/Arguments/PlayerEvents/PlayerSendHitmarkerEventArgs.cs rename to LabApi/Events/Arguments/PlayerEvents/PlayerSentHitmarkerEventArgs.cs index 2b68547f..2414d68d 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSendHitmarkerEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSentHitmarkerEventArgs.cs @@ -5,17 +5,17 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> -/// Represents the arguments for the <see cref="Handlers.PlayerEvents.SendHitmarker"/> event. +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.SentHitmarker"/> event. /// </summary> -public class PlayerSendHitmarkerEventArgs : EventArgs, IPlayerEvent +public class PlayerSentHitmarkerEventArgs : EventArgs, IPlayerEvent { /// <summary> - /// Initializes a new instance for the <see cref="PlayerSendHitmarkerEventArgs"/> class. + /// Initializes a new instance for the <see cref="PlayerSentHitmarkerEventArgs"/> class. /// </summary> - /// <param name="hub">The player that canceled the search on the toy.</param> + /// <param name="hub">The player that sent the hitmark.</param> /// <param name="size">The target size multiplier.</param> /// <param name="playAudio">The hitmarker sound effect play.</param> - public PlayerSendHitmarkerEventArgs(ReferenceHub hub, float size, bool playAudio) + public PlayerSentHitmarkerEventArgs(ReferenceHub hub, float size, bool playAudio) { Player = Player.Get(hub); Size = size; @@ -23,7 +23,7 @@ public PlayerSendHitmarkerEventArgs(ReferenceHub hub, float size, bool playAudio } /// <summary> - /// Gets the player that canceled the search on the toy. + /// Gets the player that sent the hitmark. /// </summary> public Player Player { get; } diff --git a/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs b/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs index 94383fa8..9d91d5c4 100644 --- a/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs +++ b/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs @@ -891,7 +891,7 @@ public static partial class PlayerEvents /// <summary> /// Gets called when player sent a hitmarker. /// </summary> - public static event LabEventHandler<PlayerSendHitmarkerEventArgs>? SendHitmarker; + public static event LabEventHandler<PlayerSentHitmarkerEventArgs>? SentHitmarker; /// <summary> /// Gets called when player checked a hitmarker permission. From b9bc818d8935a8482310091b3c8117c58788c6eb Mon Sep 17 00:00:00 2001 From: SlejmUr <slejmur@protonmail.com> Date: Wed, 8 Oct 2025 13:18:07 +0200 Subject: [PATCH 164/215] Add Scp049 Attacked / ing Add Scp049 Sense Lost/ Killed Target --- .../Scp049Events/Scp049AttackedEventArgs.cs | 46 ++++++++++++++++ .../Scp049Events/Scp049AttackingEventArgs.cs | 55 +++++++++++++++++++ .../Scp049SenseKilledTargetEventArgs.cs | 32 +++++++++++ .../Scp049SenseLostTargetEventArgs.cs | 32 +++++++++++ .../Handlers/Scp049Events.EventHandlers.cs | 20 +++++++ 5 files changed, 185 insertions(+) create mode 100644 LabApi/Events/Arguments/Scp049Events/Scp049AttackedEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp049Events/Scp049AttackingEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp049Events/Scp049SenseKilledTargetEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp049Events/Scp049SenseLostTargetEventArgs.cs diff --git a/LabApi/Events/Arguments/Scp049Events/Scp049AttackedEventArgs.cs b/LabApi/Events/Arguments/Scp049Events/Scp049AttackedEventArgs.cs new file mode 100644 index 00000000..76c4d5d2 --- /dev/null +++ b/LabApi/Events/Arguments/Scp049Events/Scp049AttackedEventArgs.cs @@ -0,0 +1,46 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp049Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp049Events.Attacked"/> event. +/// </summary> +public class Scp049AttackedEventArgs : EventArgs, IPlayerEvent, ITargetEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp049AttackedEventArgs"/> class. + /// </summary> + /// <param name="hub">The SCP-049 player instance.</param> + /// <param name="target">The player that SCP-049 has attacked.</param> + /// <param name="instantKill">The attack was insta kill.</param> + /// <param name="isSenseTarget">The <paramref name="target"/> was a sense target.</param> + public Scp049AttackedEventArgs(ReferenceHub hub, ReferenceHub target, bool instantKill, bool isSenseTarget) + { + Player = Player.Get(hub); + Target = Player.Get(target); + InstantKill = instantKill; + IsSenseTarget = isSenseTarget; + } + + /// <summary> + /// The SCP-049 player instance. + /// </summary> + public Player Player { get; } + + /// <summary> + /// The player that SCP-049 has attacked. + /// </summary> + public Player Target { get; } + + /// <summary> + /// The attack was instant kill. + /// </summary> + public bool InstantKill { get; } + + /// <summary> + /// The <see cref="Target"/> is a sense target. + /// </summary> + public bool IsSenseTarget { get; } +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/Scp049Events/Scp049AttackingEventArgs.cs b/LabApi/Events/Arguments/Scp049Events/Scp049AttackingEventArgs.cs new file mode 100644 index 00000000..5900f9b5 --- /dev/null +++ b/LabApi/Events/Arguments/Scp049Events/Scp049AttackingEventArgs.cs @@ -0,0 +1,55 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp049Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp049Events.Attacking"/> event. +/// </summary> +public class Scp049AttackingEventArgs : EventArgs, IPlayerEvent, ITargetEvent, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp049AttackingEventArgs"/> class. + /// </summary> + /// <param name="hub">The SCP-049 player instance.</param> + /// <param name="target">The player that SCP-049 has attacked.</param> + /// <param name="instantKill">The attack is insta kill.</param> + /// <param name="isSenseTarget">The <paramref name="target"/> is a sense target.</param> + /// <param name="cooldownTime">The attack cooldown.</param> + public Scp049AttackingEventArgs(ReferenceHub hub, ReferenceHub target, bool instantKill, bool isSenseTarget, float cooldownTime) + { + Player = Player.Get(hub); + Target = Player.Get(target); + InstantKill = instantKill; + IsSenseTarget = isSenseTarget; + } + + /// <summary> + /// The SCP-049 player instance. + /// </summary> + public Player Player { get; } + + /// <summary> + /// The player that SCP-049 has attacked. + /// </summary> + public Player Target { get; } + + /// <summary> + /// Gets or sets the attack is instant kill. + /// </summary> + public bool InstantKill { get; set; } + + /// <summary> + /// Gets or sets the <see cref="Target"/> is a sense target. + /// </summary> + public bool IsSenseTarget { get; set; } + + /// <summary> + /// Gets or sets the cooldown for the attack ability. + /// </summary> + public float CooldownTime { get; set; } + + /// <inheritdoc/> + public bool IsAllowed { get; set; } +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/Scp049Events/Scp049SenseKilledTargetEventArgs.cs b/LabApi/Events/Arguments/Scp049Events/Scp049SenseKilledTargetEventArgs.cs new file mode 100644 index 00000000..8400ec69 --- /dev/null +++ b/LabApi/Events/Arguments/Scp049Events/Scp049SenseKilledTargetEventArgs.cs @@ -0,0 +1,32 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp049Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp049Events.SenseKilledTarget"/> event. +/// </summary> +public class Scp049SenseKilledTargetEventArgs : EventArgs, IPlayerEvent, ITargetEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp049SenseKilledTargetEventArgs"/> class. + /// </summary> + /// <param name="hub">The SCP-049 player instance.</param> + /// <param name="target">The player that SCP-049 killed.</param> + public Scp049SenseKilledTargetEventArgs(ReferenceHub hub, ReferenceHub target) + { + Player = Player.Get(hub); + Target = Player.Get(target); + } + + /// <summary> + /// The SCP-049 player instance. + /// </summary> + public Player Player { get; } + + /// <summary> + /// The player that SCP-049 has killed. + /// </summary> + public Player? Target { get; } +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/Scp049Events/Scp049SenseLostTargetEventArgs.cs b/LabApi/Events/Arguments/Scp049Events/Scp049SenseLostTargetEventArgs.cs new file mode 100644 index 00000000..89b564e3 --- /dev/null +++ b/LabApi/Events/Arguments/Scp049Events/Scp049SenseLostTargetEventArgs.cs @@ -0,0 +1,32 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp049Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp049Events.SenseLostTarget"/> event. +/// </summary> +public class Scp049SenseLostTargetEventArgs : EventArgs, IPlayerEvent, ITargetEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp049SenseLostTargetEventArgs"/> class. + /// </summary> + /// <param name="hub">The SCP-049 player instance.</param> + /// <param name="target">The player that SCP-049 has targeted.</param> + public Scp049SenseLostTargetEventArgs(ReferenceHub hub, ReferenceHub target) + { + Player = Player.Get(hub); + Target = Player.Get(target); + } + + /// <summary> + /// The SCP-049 player instance. + /// </summary> + public Player Player { get; } + + /// <summary> + /// The player that SCP-049 has targeted. + /// </summary> + public Player? Target { get; } +} \ No newline at end of file diff --git a/LabApi/Events/Handlers/Scp049Events.EventHandlers.cs b/LabApi/Events/Handlers/Scp049Events.EventHandlers.cs index cc92149d..7e632c77 100644 --- a/LabApi/Events/Handlers/Scp049Events.EventHandlers.cs +++ b/LabApi/Events/Handlers/Scp049Events.EventHandlers.cs @@ -41,4 +41,24 @@ public static partial class Scp049Events /// Gets called when SCP-049 has used its sense ability. /// </summary> public static event LabEventHandler<Scp049UsedSenseEventArgs>? UsedSense; + + /// <summary> + /// Gets called when SCP-049 is using its attack ability. + /// </summary> + public static event LabEventHandler<Scp049AttackingEventArgs>? Attacking; + + /// <summary> + /// Gets called when SCP-049 has used its attack ability. + /// </summary> + public static event LabEventHandler<Scp049AttackedEventArgs>? Attacked; + + /// <summary> + /// Gets called when SCP-049 has lost a target. + /// </summary> + public static event LabEventHandler<Scp049SenseLostTargetEventArgs>? SenseLostTarget; + + /// <summary> + /// Gets called when SCP-049 has killed a target. + /// </summary> + public static event LabEventHandler<Scp049SenseKilledTargetEventArgs>? SenseKilledTarget; } \ No newline at end of file From f72cf8c3d286193dd3a98b51743ea82035dee5b8 Mon Sep 17 00:00:00 2001 From: SlejmUr <slejmur@protonmail.com> Date: Wed, 8 Oct 2025 18:44:13 +0000 Subject: [PATCH 165/215] Apply 4 suggestion(s) to 2 file(s) Co-authored-by: Lumi <me@jxtq.moe> --- .../Events/Arguments/Scp049Events/Scp049AttackedEventArgs.cs | 4 ++-- .../Events/Arguments/Scp049Events/Scp049AttackingEventArgs.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/LabApi/Events/Arguments/Scp049Events/Scp049AttackedEventArgs.cs b/LabApi/Events/Arguments/Scp049Events/Scp049AttackedEventArgs.cs index 76c4d5d2..d960667a 100644 --- a/LabApi/Events/Arguments/Scp049Events/Scp049AttackedEventArgs.cs +++ b/LabApi/Events/Arguments/Scp049Events/Scp049AttackedEventArgs.cs @@ -35,12 +35,12 @@ public Scp049AttackedEventArgs(ReferenceHub hub, ReferenceHub target, bool insta public Player Target { get; } /// <summary> - /// The attack was instant kill. + /// Gets whether the attack was an instant kill. /// </summary> public bool InstantKill { get; } /// <summary> - /// The <see cref="Target"/> is a sense target. + /// Gets whether the <see cref="Target"/> is a sense target. /// </summary> public bool IsSenseTarget { get; } } \ No newline at end of file diff --git a/LabApi/Events/Arguments/Scp049Events/Scp049AttackingEventArgs.cs b/LabApi/Events/Arguments/Scp049Events/Scp049AttackingEventArgs.cs index 5900f9b5..00bbdfb8 100644 --- a/LabApi/Events/Arguments/Scp049Events/Scp049AttackingEventArgs.cs +++ b/LabApi/Events/Arguments/Scp049Events/Scp049AttackingEventArgs.cs @@ -36,12 +36,12 @@ public Scp049AttackingEventArgs(ReferenceHub hub, ReferenceHub target, bool inst public Player Target { get; } /// <summary> - /// Gets or sets the attack is instant kill. + /// Gets or sets whether the attack is an instant kill. /// </summary> public bool InstantKill { get; set; } /// <summary> - /// Gets or sets the <see cref="Target"/> is a sense target. + /// Gets or sets whether the <see cref="Target"/> is a sense target. /// </summary> public bool IsSenseTarget { get; set; } From 47ea4f93c57c59820bdc4e5c60c2ccc159e6c30c Mon Sep 17 00:00:00 2001 From: SlejmUr <slejmur@protonmail.com> Date: Wed, 8 Oct 2025 18:46:59 +0000 Subject: [PATCH 166/215] Apply 10 suggestion(s) to 5 file(s) Co-authored-by: Axwabo <axwabo@gmail.com> --- LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs | 2 +- .../PlayerEvents/PlayerCheckedHitmarkerEventArgs.cs | 4 ++-- .../PlayerEvents/PlayerSendingHitmarkerEventArgs.cs | 4 ++-- .../Arguments/PlayerEvents/PlayerSentHitmarkerEventArgs.cs | 4 ++-- LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs | 6 +++--- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs index d080add6..a0c94c6a 100644 --- a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs +++ b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs @@ -1668,7 +1668,7 @@ public override void OnPlayerSentHitmarker(PlayerSentHitmarkerEventArgs ev) public override void OnPlayerSendingHitmarker(PlayerSendingHitmarkerEventArgs ev) { - Logger.Info($"{nameof(OnPlayerSendingHitmarker)} triggered by {ev.Player} {ev.Size} {ev.PlayAudio}"); + Logger.Info($"{nameof(OnPlayerSendingHitmarker)} triggered by {ev.Player} {ev.Size} {ev.PlayAudio}"); if (ev.Player.Role is PlayerRoles.RoleTypeId.Scp939) { ev.IsAllowed = false; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerCheckedHitmarkerEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerCheckedHitmarkerEventArgs.cs index 2369e710..d629e173 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerCheckedHitmarkerEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerCheckedHitmarkerEventArgs.cs @@ -16,7 +16,7 @@ public class PlayerCheckedHitmarkerEventArgs : EventArgs, IPlayerEvent /// <param name="hub">The player that hitmarker should send.</param> /// <param name="adh">The damage dealth to the <paramref name="victim"/>.</param> /// <param name="victim">The player who got hurt by <paramref name="hub"/>.</param> - /// <param name="result">The reuslt of the check.</param> + /// <param name="result">The result of the check.</param> public PlayerCheckedHitmarkerEventArgs(ReferenceHub hub, AttackerDamageHandler adh, ReferenceHub victim, bool result) { Player = Player.Get(hub); @@ -26,7 +26,7 @@ public PlayerCheckedHitmarkerEventArgs(ReferenceHub hub, AttackerDamageHandler a } /// <summary> - /// Gets the player that sending the hitmarker. + /// Gets the player that the hitmarker is being sent to. /// </summary> public Player Player { get; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSendingHitmarkerEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSendingHitmarkerEventArgs.cs index b406a079..77362290 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSendingHitmarkerEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSendingHitmarkerEventArgs.cs @@ -14,7 +14,7 @@ public class PlayerSendingHitmarkerEventArgs : EventArgs, IPlayerEvent, ICancell /// </summary> /// <param name="hub">The player that sending the hitmark.</param> /// <param name="size">The target size multiplier.</param> - /// <param name="playAudio">The hitmarker sound effect play.</param> + /// <param name="playAudio">Whether the hitmarker sound effect play.</param> public PlayerSendingHitmarkerEventArgs(ReferenceHub hub, float size, bool playAudio) { Player = Player.Get(hub); @@ -25,7 +25,7 @@ public PlayerSendingHitmarkerEventArgs(ReferenceHub hub, float size, bool playAu } /// <summary> - /// Gets or sets the player that sending the hitmark. + /// Gets or sets the player that the hitmark is being sent to. /// </summary> public Player Player { get; set; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSentHitmarkerEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSentHitmarkerEventArgs.cs index 2414d68d..795720de 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSentHitmarkerEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSentHitmarkerEventArgs.cs @@ -14,7 +14,7 @@ public class PlayerSentHitmarkerEventArgs : EventArgs, IPlayerEvent /// </summary> /// <param name="hub">The player that sent the hitmark.</param> /// <param name="size">The target size multiplier.</param> - /// <param name="playAudio">The hitmarker sound effect play.</param> + /// <param name="playAudio">Whether the hitmarker sound effect play.</param> public PlayerSentHitmarkerEventArgs(ReferenceHub hub, float size, bool playAudio) { Player = Player.Get(hub); @@ -23,7 +23,7 @@ public PlayerSentHitmarkerEventArgs(ReferenceHub hub, float size, bool playAudio } /// <summary> - /// Gets the player that sent the hitmark. + /// Gets the player that the hitmarker is being sent to. /// </summary> public Player Player { get; } diff --git a/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs b/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs index 9d91d5c4..bd9e2ac2 100644 --- a/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs +++ b/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs @@ -884,17 +884,17 @@ public static partial class PlayerEvents public static event LabEventHandler<PlayerInteractedWarheadLeverEventArgs>? InteractedWarheadLever; /// <summary> - /// Gets called when player sending a hitmarker. + /// Gets called when a hitmarker is being sent to a player. /// </summary> public static event LabEventHandler<PlayerSendingHitmarkerEventArgs>? SendingHitmarker; /// <summary> - /// Gets called when player sent a hitmarker. + /// Gets called when a hitmarker is sent to a player. /// </summary> public static event LabEventHandler<PlayerSentHitmarkerEventArgs>? SentHitmarker; /// <summary> - /// Gets called when player checked a hitmarker permission. + /// Gets called when a hitmarker permission is checked for a player. /// </summary> public static event LabEventHandler<PlayerCheckedHitmarkerEventArgs>? CheckedHitmarker; From 35b53cc0b87f2501846fd568da2c023cfb59b8b9 Mon Sep 17 00:00:00 2001 From: SlejmUr <slejmur@protonmail.com> Date: Wed, 8 Oct 2025 21:13:16 +0200 Subject: [PATCH 167/215] fix IsAllowed not set in Attacking Added log of the new events --- .../LogAll/LogPlugin/MyCustomEventsHandler.cs | 21 +++++++++++++++++++ .../Scp049Events/Scp049AttackingEventArgs.cs | 2 ++ 2 files changed, 23 insertions(+) diff --git a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs index 8cc52f5b..6848174b 100644 --- a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs +++ b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs @@ -20,6 +20,7 @@ namespace LogPlugin; internal class MyCustomEventsHandler : CustomEventsHandler { + public override void OnPlayerActivatingGenerator(PlayerActivatingGeneratorEventArgs ev) { Logger.Info($"{nameof(OnPlayerActivatingGenerator)} triggered by {ev.Player.UserId}"); @@ -815,6 +816,26 @@ public override void OnPlayerLeftHazard(PlayerLeftHazardEventArgs ev) Logger.Info($"{nameof(OnPlayerLeftHazard)} triggered by {ev.Player.UserId}"); } + public override void OnScp049Attacking(Scp049AttackingEventArgs ev) + { + Logger.Info($"{nameof(OnScp049Attacking)} triggered by {ev.Player} {ev.Target} {ev.InstantKill} {ev.IsSenseTarget} {ev.CooldownTime}"); + } + + public override void OnScp049Attacked(Scp049AttackedEventArgs ev) + { + Logger.Info($"{nameof(OnScp049Attacked)} triggered by {ev.Player} {ev.Target} {ev.InstantKill} {ev.IsSenseTarget}"); + } + + public override void OnScp049SenseKilledTarget(Scp049SenseKilledTargetEventArgs ev) + { + Logger.Info($"{nameof(OnScp049SenseKilledTarget)} triggered by {ev.Player} {ev.Target}"); + } + + public override void OnScp049SenseLostTarget(Scp049SenseLostTargetEventArgs ev) + { + Logger.Info($"{nameof(OnScp049SenseLostTarget)} triggered by {ev.Player} {ev.Target}"); + } + public override void OnScp049StartingResurrection(Scp049StartingResurrectionEventArgs ev) { Logger.Info($"{nameof(OnScp049StartingResurrection)} triggered by {ev.Player.UserId}"); diff --git a/LabApi/Events/Arguments/Scp049Events/Scp049AttackingEventArgs.cs b/LabApi/Events/Arguments/Scp049Events/Scp049AttackingEventArgs.cs index 00bbdfb8..be5a2ff3 100644 --- a/LabApi/Events/Arguments/Scp049Events/Scp049AttackingEventArgs.cs +++ b/LabApi/Events/Arguments/Scp049Events/Scp049AttackingEventArgs.cs @@ -23,6 +23,8 @@ public Scp049AttackingEventArgs(ReferenceHub hub, ReferenceHub target, bool inst Target = Player.Get(target); InstantKill = instantKill; IsSenseTarget = isSenseTarget; + + IsAllowed = true; } /// <summary> From d7b3da447c63121096c27fb2885acc2219fbcd85 Mon Sep 17 00:00:00 2001 From: SlejmUr <slejmur@protonmail.com> Date: Sat, 11 Oct 2025 11:35:43 +0000 Subject: [PATCH 168/215] Apply suggestions --- .../PlayerEvents/PlayerCheckedHitmarkerEventArgs.cs | 6 +++--- .../PlayerEvents/PlayerSendingHitmarkerEventArgs.cs | 10 +++++----- .../PlayerEvents/PlayerSentHitmarkerEventArgs.cs | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerCheckedHitmarkerEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerCheckedHitmarkerEventArgs.cs index d629e173..9291f616 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerCheckedHitmarkerEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerCheckedHitmarkerEventArgs.cs @@ -11,10 +11,10 @@ namespace LabApi.Events.Arguments.PlayerEvents; public class PlayerCheckedHitmarkerEventArgs : EventArgs, IPlayerEvent { /// <summary> - /// Initializes a new instance for the <see cref="PlayerSentHitmarkerEventArgs"/> class. + /// Initializes a new instance for the <see cref="PlayerCheckedHitmarkerEventArgs"/> class. /// </summary> /// <param name="hub">The player that hitmarker should send.</param> - /// <param name="adh">The damage dealth to the <paramref name="victim"/>.</param> + /// <param name="adh">The damage dealt to the <paramref name="victim"/>.</param> /// <param name="victim">The player who got hurt by <paramref name="hub"/>.</param> /// <param name="result">The result of the check.</param> public PlayerCheckedHitmarkerEventArgs(ReferenceHub hub, AttackerDamageHandler adh, ReferenceHub victim, bool result) @@ -31,7 +31,7 @@ public PlayerCheckedHitmarkerEventArgs(ReferenceHub hub, AttackerDamageHandler a public Player Player { get; } /// <summary> - /// Gets the player that provides the hitmarker. + /// Gets the player that was hit. /// </summary> public Player Victim { get; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSendingHitmarkerEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSendingHitmarkerEventArgs.cs index 77362290..cfca9f8f 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSendingHitmarkerEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSendingHitmarkerEventArgs.cs @@ -10,11 +10,11 @@ namespace LabApi.Events.Arguments.PlayerEvents; public class PlayerSendingHitmarkerEventArgs : EventArgs, IPlayerEvent, ICancellableEvent { /// <summary> - /// Initializes a new instance for the <see cref="PlayerSentHitmarkerEventArgs"/> class. + /// Initializes a new instance for the <see cref="PlayerSendingHitmarkerEventArgs"/> class. /// </summary> - /// <param name="hub">The player that sending the hitmark.</param> + /// <param name="hub">The player that is sending the hitmarker.</param> /// <param name="size">The target size multiplier.</param> - /// <param name="playAudio">Whether the hitmarker sound effect play.</param> + /// <param name="playAudio">Whether the hitmarker sound effect should play.</param> public PlayerSendingHitmarkerEventArgs(ReferenceHub hub, float size, bool playAudio) { Player = Player.Get(hub); @@ -25,7 +25,7 @@ public PlayerSendingHitmarkerEventArgs(ReferenceHub hub, float size, bool playAu } /// <summary> - /// Gets or sets the player that the hitmark is being sent to. + /// Gets or sets the player that the hitmarker is being sent to. /// </summary> public Player Player { get; set; } @@ -35,7 +35,7 @@ public PlayerSendingHitmarkerEventArgs(ReferenceHub hub, float size, bool playAu public float Size { get; set; } /// <summary> - /// Gets or sets if the hitmarker sound effect play. + /// Gets or sets a value indicating whether the hitmarker sound effect should play. /// </summary> public bool PlayAudio { get; set; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSentHitmarkerEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSentHitmarkerEventArgs.cs index 795720de..521c01a3 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSentHitmarkerEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSentHitmarkerEventArgs.cs @@ -12,9 +12,9 @@ public class PlayerSentHitmarkerEventArgs : EventArgs, IPlayerEvent /// <summary> /// Initializes a new instance for the <see cref="PlayerSentHitmarkerEventArgs"/> class. /// </summary> - /// <param name="hub">The player that sent the hitmark.</param> + /// <param name="hub">The player that sent the hitmarker.</param> /// <param name="size">The target size multiplier.</param> - /// <param name="playAudio">Whether the hitmarker sound effect play.</param> + /// <param name="playAudio">Whether the hitmarker sound effect was played.</param> public PlayerSentHitmarkerEventArgs(ReferenceHub hub, float size, bool playAudio) { Player = Player.Get(hub); @@ -23,7 +23,7 @@ public PlayerSentHitmarkerEventArgs(ReferenceHub hub, float size, bool playAudio } /// <summary> - /// Gets the player that the hitmarker is being sent to. + /// Gets the player that the hitmarker was sent to. /// </summary> public Player Player { get; } @@ -33,7 +33,7 @@ public PlayerSentHitmarkerEventArgs(ReferenceHub hub, float size, bool playAudio public float Size { get; } /// <summary> - /// Gets if the hitmarker sound effect play. + /// Gets a value indicating whether the hitmarker sound effect was played. /// </summary> public bool PlayAudio { get; } } From 0e8229888d22e1fade06f6b0532ec8c3469b0f53 Mon Sep 17 00:00:00 2001 From: SlejmUr <slejmur@protonmail.com> Date: Sat, 11 Oct 2025 13:45:21 +0200 Subject: [PATCH 169/215] Rename PlayAudio to PlayedAudio Revert LogPlugin handlers tolog everything too --- .../LogAll/LogPlugin/MyCustomEventsHandler.cs | 9 ++------- .../PlayerEvents/PlayerSentHitmarkerEventArgs.cs | 8 ++++---- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs index a0c94c6a..c14e5718 100644 --- a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs +++ b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs @@ -20,7 +20,6 @@ namespace LogPlugin; internal class MyCustomEventsHandler : CustomEventsHandler { - /* public override void OnPlayerActivatingGenerator(PlayerActivatingGeneratorEventArgs ev) { Logger.Info($"{nameof(OnPlayerActivatingGenerator)} triggered by {ev.Player.UserId}"); @@ -1655,7 +1654,7 @@ public override void OnScp127Talked(Scp127TalkedEventArgs ev) { Logger.Info($"{nameof(OnScp127Talked)} triggered by {ev.Scp127Item.CurrentOwner}"); } - */ + public override void OnPlayerCheckedHitmarker(PlayerCheckedHitmarkerEventArgs ev) { Logger.Info($"{nameof(OnPlayerCheckedHitmarker)} triggered by {ev.Player} {ev.Victim} {ev.Result}"); @@ -1663,16 +1662,12 @@ public override void OnPlayerCheckedHitmarker(PlayerCheckedHitmarkerEventArgs ev public override void OnPlayerSentHitmarker(PlayerSentHitmarkerEventArgs ev) { - Logger.Info($"{nameof(OnPlayerSentHitmarker)} triggered by {ev.Player} {ev.Size} {ev.PlayAudio}"); + Logger.Info($"{nameof(OnPlayerSentHitmarker)} triggered by {ev.Player} {ev.Size} {ev.PlayedAudio}"); } public override void OnPlayerSendingHitmarker(PlayerSendingHitmarkerEventArgs ev) { Logger.Info($"{nameof(OnPlayerSendingHitmarker)} triggered by {ev.Player} {ev.Size} {ev.PlayAudio}"); - if (ev.Player.Role is PlayerRoles.RoleTypeId.Scp939) - { - ev.IsAllowed = false; - } } #region Excluded Events diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSentHitmarkerEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSentHitmarkerEventArgs.cs index 521c01a3..0532502b 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSentHitmarkerEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSentHitmarkerEventArgs.cs @@ -14,12 +14,12 @@ public class PlayerSentHitmarkerEventArgs : EventArgs, IPlayerEvent /// </summary> /// <param name="hub">The player that sent the hitmarker.</param> /// <param name="size">The target size multiplier.</param> - /// <param name="playAudio">Whether the hitmarker sound effect was played.</param> - public PlayerSentHitmarkerEventArgs(ReferenceHub hub, float size, bool playAudio) + /// <param name="playedAudio">Whether the hitmarker sound effect was played.</param> + public PlayerSentHitmarkerEventArgs(ReferenceHub hub, float size, bool playedAudio) { Player = Player.Get(hub); Size = size; - PlayAudio = playAudio; + PlayedAudio = playedAudio; } /// <summary> @@ -35,5 +35,5 @@ public PlayerSentHitmarkerEventArgs(ReferenceHub hub, float size, bool playAudio /// <summary> /// Gets a value indicating whether the hitmarker sound effect was played. /// </summary> - public bool PlayAudio { get; } + public bool PlayedAudio { get; } } From f6b4fa1b412eea5cf50eab416ebdda8e8dac9f7f Mon Sep 17 00:00:00 2001 From: SlejmUr <slejmur@protonmail.com> Date: Sat, 11 Oct 2025 23:15:37 +0000 Subject: [PATCH 170/215] Add Wave event --- .../LogAll/LogPlugin/MyCustomEventsHandler.cs | 20 +++++++++ .../AchievedMilestoneEventArgs.cs | 38 ++++++++++++++++ .../AchievingMilestoneEventArgs.cs | 44 +++++++++++++++++++ .../ModifiedFactionInfluenceEventArgs.cs | 32 ++++++++++++++ .../ModifyingFactionInfluenceEventArgs.cs | 38 ++++++++++++++++ .../Handlers/ServerEvents.EventHandlers.cs | 20 +++++++++ 6 files changed, 192 insertions(+) create mode 100644 LabApi/Events/Arguments/ServerEvents/AchievedMilestoneEventArgs.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/AchievingMilestoneEventArgs.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/ModifiedFactionInfluenceEventArgs.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/ModifyingFactionInfluenceEventArgs.cs diff --git a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs index 8cc52f5b..c00ac1d5 100644 --- a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs +++ b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs @@ -1655,6 +1655,26 @@ public override void OnScp127Talked(Scp127TalkedEventArgs ev) Logger.Info($"{nameof(OnScp127Talked)} triggered by {ev.Scp127Item.CurrentOwner}"); } + public override void OnServerMilestoneAchieving(AchievingMilestoneEventArgs ev) + { + Logger.Info($"{nameof(OnServerMilestoneAchieving)} triggered by {ev.Faction} {ev.Threshold} {ev.MilestoneIndex}"); + } + + public override void OnServerMilestoneAchieved(AchievedMilestoneEventArgs ev) + { + Logger.Info($"{nameof(OnServerMilestoneAchieved)} triggered by {ev.Faction} {ev.Threshold} {ev.MilestoneIndex}"); + } + + public override void OnServerFactionInfluenceModifying(ModifyingFactionInfluenceEventArgs ev) + { + Logger.Info($"{nameof(OnServerFactionInfluenceModifying)} triggered by {ev.Faction} {ev.Influence}"); + } + + public override void OnServerFactionInfluenceModified(ModifiedFactionInfluenceEventArgs ev) + { + Logger.Info($"{nameof(OnServerFactionInfluenceModified)} triggered by {ev.Faction} {ev.Influence}"); + } + #region Excluded Events // The following events spam the console and are therefore excluded from this example: diff --git a/LabApi/Events/Arguments/ServerEvents/AchievedMilestoneEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/AchievedMilestoneEventArgs.cs new file mode 100644 index 00000000..d98b73a9 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/AchievedMilestoneEventArgs.cs @@ -0,0 +1,38 @@ +using PlayerRoles; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.MilestoneAchieved"/> event. +/// </summary> +public class AchievedMilestoneEventArgs : EventArgs +{ + /// <summary> + /// Initializes a new instance of the <see cref="AchievedMilestoneEventArgs"/> class. + /// </summary> + /// <param name="faction">The faction that achieved this milestone.</param> + /// <param name="threshold">The influence threshold for this milestone.</param> + /// <param name="milestoneIndex">The index of the achieved milestone.</param> + public AchievedMilestoneEventArgs(Faction faction, int threshold, int milestoneIndex) + { + Faction = faction; + Threshold = threshold; + MilestoneIndex = milestoneIndex; + } + + /// <summary> + /// Gets the faction that achieved this milestone. + /// </summary> + public Faction Faction { get; } + + /// <summary> + /// Gets the influence threshold for this milestone. + /// </summary> + public int Threshold { get; } + + /// <summary> + /// Gets the index of the achieved milestone. + /// </summary> + public int MilestoneIndex { get; } +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/ServerEvents/AchievingMilestoneEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/AchievingMilestoneEventArgs.cs new file mode 100644 index 00000000..9eb81e33 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/AchievingMilestoneEventArgs.cs @@ -0,0 +1,44 @@ +using LabApi.Events.Arguments.Interfaces; +using PlayerRoles; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.MilestoneAchieving"/> event. +/// </summary> +public class AchievingMilestoneEventArgs : EventArgs, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="AchievingMilestoneEventArgs"/> class. + /// </summary> + /// <param name="faction">The faction that achieved this milestone.</param> + /// <param name="threshold">The influence threshold for this milestone.</param> + /// <param name="milestoneIndex">The index of the achieved milestone.</param> + public AchievingMilestoneEventArgs(Faction faction, int threshold, int milestoneIndex) + { + Faction = faction; + Threshold = threshold; + MilestoneIndex = milestoneIndex; + + IsAllowed = true; + } + + /// <summary> + /// Gets the faction that achieved this milestone. + /// </summary> + public Faction Faction { get; } + + /// <summary> + /// Gets the influence threshold for this milestone. + /// </summary> + public int Threshold { get; } + + /// <summary> + /// Gets the index of the achieved milestone. + /// </summary> + public int MilestoneIndex { get; } + + /// <inheritdoc/> + public bool IsAllowed { get; set; } +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/ServerEvents/ModifiedFactionInfluenceEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/ModifiedFactionInfluenceEventArgs.cs new file mode 100644 index 00000000..46351d12 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/ModifiedFactionInfluenceEventArgs.cs @@ -0,0 +1,32 @@ +using PlayerRoles; +using Respawning; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.FactionInfluenceModified"/> event. +/// </summary> +public class ModifiedFactionInfluenceEventArgs : EventArgs +{ + /// <summary> + /// Initializes a new instance of the <see cref="ModifiedFactionInfluenceEventArgs"/> class. + /// </summary> + /// <param name="faction">The faction whose influence is modified.</param> + /// <param name="influence">The <see cref="FactionInfluenceManager.Influence">influence</see> amount the <paramref name="faction"/> has now.</param> + public ModifiedFactionInfluenceEventArgs(Faction faction, float influence) + { + Faction = faction; + Influence = influence; + } + + /// <summary> + /// Gets the faction whose influence is modified. + /// </summary> + public Faction Faction { get; } + + /// <summary> + /// Gets the new influence of the <see cref="Faction"/>. + /// </summary> + public float Influence { get; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/ModifyingFactionInfluenceEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/ModifyingFactionInfluenceEventArgs.cs new file mode 100644 index 00000000..55bdd025 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/ModifyingFactionInfluenceEventArgs.cs @@ -0,0 +1,38 @@ +using LabApi.Events.Arguments.Interfaces; +using PlayerRoles; +using Respawning; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.FactionInfluenceModifying"/> event. +/// </summary> +public class ModifyingFactionInfluenceEventArgs : EventArgs, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="ModifyingFactionInfluenceEventArgs"/> class. + /// </summary> + /// <param name="faction">The faction whose influence is being modified.</param> + /// <param name="influence">The <see cref="FactionInfluenceManager.Influence">influence</see> amount the <paramref name="faction"/> has now.</param> + public ModifyingFactionInfluenceEventArgs(Faction faction, float influence) + { + Faction = faction; + Influence = influence; + + IsAllowed = true; + } + + /// <summary> + /// Gets or sets the faction whose influence is being modified. + /// </summary> + public Faction Faction { get; set; } + + /// <summary> + /// Gets or sets the new influence of the <see cref="Faction"/>. + /// </summary> + public float Influence { get; set; } + + /// <inheritdoc/> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs b/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs index 4ffb37d9..e70c7b24 100644 --- a/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs +++ b/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs @@ -211,4 +211,24 @@ public static partial class ServerEvents /// Gets called when elevator's sequence has changed. /// </summary> public static event LabEventHandler<ElevatorSequenceChangedEventArgs>? ElevatorSequenceChanged; + + /// <summary> + /// Gets called when a faction's influence is changing. + /// </summary> + public static event LabEventHandler<ModifyingFactionInfluenceEventArgs>? ModifyingFactionInfluence; + + /// <summary> + /// Gets called when a faction's influence has changed. + /// </summary> + public static event LabEventHandler<ModifiedFactionInfluenceEventArgs>? ModifiedFactionInfluence; + + /// <summary> + /// Gets called when a faction is achieving a milestone. + /// </summary> + public static event LabEventHandler<AchievingMilestoneEventArgs>? AchievingMilestone; + + /// <summary> + /// Gets called when a faction achieved a milestone. + /// </summary> + public static event LabEventHandler<AchievedMilestoneEventArgs>? AchievedMilestone; } \ No newline at end of file From 91645fd12f8b3765c4207049d1b79d210bd9056a Mon Sep 17 00:00:00 2001 From: SlejmUr <slejmur@protonmail.com> Date: Sun, 12 Oct 2025 16:34:28 +0000 Subject: [PATCH 171/215] Apply 5 suggestion(s) to 2 file(s) Co-authored-by: Jesus-QC <99-jesusqc@users.noreply.git.scpslgame.com> --- .../Arguments/Scp049Events/Scp049AttackedEventArgs.cs | 2 +- .../Arguments/Scp049Events/Scp049AttackingEventArgs.cs | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/LabApi/Events/Arguments/Scp049Events/Scp049AttackedEventArgs.cs b/LabApi/Events/Arguments/Scp049Events/Scp049AttackedEventArgs.cs index d960667a..0a227784 100644 --- a/LabApi/Events/Arguments/Scp049Events/Scp049AttackedEventArgs.cs +++ b/LabApi/Events/Arguments/Scp049Events/Scp049AttackedEventArgs.cs @@ -14,7 +14,7 @@ public class Scp049AttackedEventArgs : EventArgs, IPlayerEvent, ITargetEvent /// </summary> /// <param name="hub">The SCP-049 player instance.</param> /// <param name="target">The player that SCP-049 has attacked.</param> - /// <param name="instantKill">The attack was insta kill.</param> + /// <param name="instantKill">The attack was an instant kill.</param> /// <param name="isSenseTarget">The <paramref name="target"/> was a sense target.</param> public Scp049AttackedEventArgs(ReferenceHub hub, ReferenceHub target, bool instantKill, bool isSenseTarget) { diff --git a/LabApi/Events/Arguments/Scp049Events/Scp049AttackingEventArgs.cs b/LabApi/Events/Arguments/Scp049Events/Scp049AttackingEventArgs.cs index be5a2ff3..8568470b 100644 --- a/LabApi/Events/Arguments/Scp049Events/Scp049AttackingEventArgs.cs +++ b/LabApi/Events/Arguments/Scp049Events/Scp049AttackingEventArgs.cs @@ -13,8 +13,8 @@ public class Scp049AttackingEventArgs : EventArgs, IPlayerEvent, ITargetEvent, I /// Initializes a new instance of the <see cref="Scp049AttackingEventArgs"/> class. /// </summary> /// <param name="hub">The SCP-049 player instance.</param> - /// <param name="target">The player that SCP-049 has attacked.</param> - /// <param name="instantKill">The attack is insta kill.</param> + /// <param name="target">The player that SCP-049 is attacking.</param> + /// <param name="instantKill">The attack is an instant kill.</param> /// <param name="isSenseTarget">The <paramref name="target"/> is a sense target.</param> /// <param name="cooldownTime">The attack cooldown.</param> public Scp049AttackingEventArgs(ReferenceHub hub, ReferenceHub target, bool instantKill, bool isSenseTarget, float cooldownTime) @@ -23,6 +23,7 @@ public Scp049AttackingEventArgs(ReferenceHub hub, ReferenceHub target, bool inst Target = Player.Get(target); InstantKill = instantKill; IsSenseTarget = isSenseTarget; + CooldownTime = cooldownTime; IsAllowed = true; } @@ -33,7 +34,7 @@ public Scp049AttackingEventArgs(ReferenceHub hub, ReferenceHub target, bool inst public Player Player { get; } /// <summary> - /// The player that SCP-049 has attacked. + /// The player that SCP-049 is attacking. /// </summary> public Player Target { get; } From f870474fb389acf79733f582533a80cb080c9486 Mon Sep 17 00:00:00 2001 From: SlejmUr <slejmur@protonmail.com> Date: Sun, 12 Oct 2025 18:35:13 +0200 Subject: [PATCH 172/215] Fix nullable target --- LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs | 1 - .../Arguments/Scp049Events/Scp049SenseKilledTargetEventArgs.cs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs index 6848174b..dc4129ec 100644 --- a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs +++ b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs @@ -20,7 +20,6 @@ namespace LogPlugin; internal class MyCustomEventsHandler : CustomEventsHandler { - public override void OnPlayerActivatingGenerator(PlayerActivatingGeneratorEventArgs ev) { Logger.Info($"{nameof(OnPlayerActivatingGenerator)} triggered by {ev.Player.UserId}"); diff --git a/LabApi/Events/Arguments/Scp049Events/Scp049SenseKilledTargetEventArgs.cs b/LabApi/Events/Arguments/Scp049Events/Scp049SenseKilledTargetEventArgs.cs index 8400ec69..96e557ad 100644 --- a/LabApi/Events/Arguments/Scp049Events/Scp049SenseKilledTargetEventArgs.cs +++ b/LabApi/Events/Arguments/Scp049Events/Scp049SenseKilledTargetEventArgs.cs @@ -28,5 +28,5 @@ public Scp049SenseKilledTargetEventArgs(ReferenceHub hub, ReferenceHub target) /// <summary> /// The player that SCP-049 has killed. /// </summary> - public Player? Target { get; } + public Player Target { get; } } \ No newline at end of file From 4b9c4a8c18504965840cab90960c8dc9ebe88e3f Mon Sep 17 00:00:00 2001 From: Axwabo <axwabo@gmail.com> Date: Sun, 12 Oct 2025 18:48:21 +0200 Subject: [PATCH 173/215] basic required version check --- LabApi/Loader/PluginLoader.cs | 41 +++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/LabApi/Loader/PluginLoader.cs b/LabApi/Loader/PluginLoader.cs index 7563818a..dbbdf220 100644 --- a/LabApi/Loader/PluginLoader.cs +++ b/LabApi/Loader/PluginLoader.cs @@ -1,3 +1,4 @@ +using LabApi.Features; using LabApi.Features.Console; using LabApi.Features.Permissions; using LabApi.Features.Permissions.Providers; @@ -6,12 +7,12 @@ using LabApi.Loader.Features.Misc; using LabApi.Loader.Features.Paths; using LabApi.Loader.Features.Plugins; +using LabApi.Loader.Features.Yaml; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; -using LabApi.Loader.Features.Yaml; namespace LabApi.Loader; @@ -245,6 +246,12 @@ public static void EnablePlugins(IEnumerable<Plugin> plugins) continue; } + // We check if the required version is compatible with the installed LabAPI version + if (!ValidateVersion(plugin)) + { + continue; + } + // We finally enable the plugin EnablePlugin(plugin); } @@ -359,6 +366,36 @@ private static void LogMissingDependencies(Assembly assembly) } } + private static bool ValidateVersion(Plugin plugin) + { + Version required = plugin.RequiredApiVersion; + Version current = LabApiProperties.CurrentVersion; + + if (required.Major != current.Major) + { + Logger.Error($""" + {LoggerPrefix} Couldn't enable the plugin {plugin} + It was built for a different major version of LabAPI, and would likely be unable to function at all. + Current LabAPI version: {LabApiProperties.CompiledVersion} + Required by plugin: {required} + """); + return false; + } + + if (required > current) + { + Logger.Warn($""" + {LoggerPrefix} Potential issue with plugin {plugin} + It was built for a newer minor/patch version of LabAPI, and might not be able to access some features it depends on. + Are you running an older version of the server? + Current LabAPI version: {LabApiProperties.CompiledVersion} + Required by plugin: {required} + """); + } + + return true; + } + private static void InstantiatePlugins(Type[] types, Assembly assembly, string filePath) { foreach (Type type in types) @@ -383,4 +420,4 @@ private static void InstantiatePlugins(Type[] types, Assembly assembly, string f Logger.Info($"{LoggerPrefix} Successfully loaded {plugin.Name}"); } } -} \ No newline at end of file +} From b11a846702efdeeebdbf775215033835dc63ae9b Mon Sep 17 00:00:00 2001 From: Axwabo <axwabo@gmail.com> Date: Sun, 12 Oct 2025 19:03:38 +0200 Subject: [PATCH 174/215] allow force-loading unsupported versions + improve messages --- .../Plugins/Configuration/Properties.cs | 8 +++- LabApi/Loader/PluginLoader.cs | 40 +++++++++++++------ 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/LabApi/Loader/Features/Plugins/Configuration/Properties.cs b/LabApi/Loader/Features/Plugins/Configuration/Properties.cs index 5706fb11..0a208522 100644 --- a/LabApi/Loader/Features/Plugins/Configuration/Properties.cs +++ b/LabApi/Loader/Features/Plugins/Configuration/Properties.cs @@ -18,4 +18,10 @@ public class Properties /// </summary> [Description("Whether or not the plugin is enabled.")] public bool IsEnabled { get; set; } = true; -} \ No newline at end of file + + /// <summary> + /// Whether to allow loading the plugin even if it was built for a different major version of LabAPI. + /// </summary> + [Description("Whether to allow loading the plugin even if it was built for a different major version of LabAPI.")] + public bool ForceUnsupportedMajorVersion { get; set; } +} diff --git a/LabApi/Loader/PluginLoader.cs b/LabApi/Loader/PluginLoader.cs index dbbdf220..4fed3a7b 100644 --- a/LabApi/Loader/PluginLoader.cs +++ b/LabApi/Loader/PluginLoader.cs @@ -371,19 +371,13 @@ private static bool ValidateVersion(Plugin plugin) Version required = plugin.RequiredApiVersion; Version current = LabApiProperties.CurrentVersion; - if (required.Major != current.Major) + if (required.Major == current.Major) { - Logger.Error($""" - {LoggerPrefix} Couldn't enable the plugin {plugin} - It was built for a different major version of LabAPI, and would likely be unable to function at all. - Current LabAPI version: {LabApiProperties.CompiledVersion} - Required by plugin: {required} - """); - return false; - } + if (required <= current) + { + return true; + } - if (required > current) - { Logger.Warn($""" {LoggerPrefix} Potential issue with plugin {plugin} It was built for a newer minor/patch version of LabAPI, and might not be able to access some features it depends on. @@ -391,9 +385,31 @@ Are you running an older version of the server? Current LabAPI version: {LabApiProperties.CompiledVersion} Required by plugin: {required} """); + + return true; + } + + string difference = required.Major < current.Major ? "an outdated major version" : "a newer major version"; + + if (plugin.Properties?.ForceUnsupportedMajorVersion == true) + { + Logger.Warn($""" + {LoggerPrefix} Forcefully loading unsupported plugin {plugin} + It was built for {difference} of LabAPI, and will likely have degraded functionality. + Current LabAPI version: {LabApiProperties.CompiledVersion} + Required by plugin: {required} + """); + return true; } - return true; + Logger.Error($""" + {LoggerPrefix} Couldn't enable the plugin {plugin} + It was built for {difference} of LabAPI, and would likely have degraded functionality. + To forcefully load it, set the appropriate property in the plugins's properties.yml file. + Current LabAPI version: {LabApiProperties.CompiledVersion} + Required by plugin: {required} + """); + return false; } private static void InstantiatePlugins(Type[] types, Assembly assembly, string filePath) From 5cd46e25cb2759c167a755782bdb28dc262fdfe5 Mon Sep 17 00:00:00 2001 From: SlejmUr <slejmur@protonmail.com> Date: Sun, 12 Oct 2025 19:19:12 +0200 Subject: [PATCH 175/215] Add Focuesd Add Mimiced/ing Enviroment --- .../Scp939Events/Scp939FocusedEventArgs.cs | 32 ++++++++++++++ .../Scp939MimicedEnviromentEventArgs.cs | 32 ++++++++++++++ .../Scp939MimicingEnviromentEventArgs.cs | 44 +++++++++++++++++++ .../Handlers/Scp939Events.EventHandlers.cs | 15 +++++++ 4 files changed, 123 insertions(+) create mode 100644 LabApi/Events/Arguments/Scp939Events/Scp939FocusedEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp939Events/Scp939MimicedEnviromentEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp939Events/Scp939MimicingEnviromentEventArgs.cs diff --git a/LabApi/Events/Arguments/Scp939Events/Scp939FocusedEventArgs.cs b/LabApi/Events/Arguments/Scp939Events/Scp939FocusedEventArgs.cs new file mode 100644 index 00000000..fe5a1cb6 --- /dev/null +++ b/LabApi/Events/Arguments/Scp939Events/Scp939FocusedEventArgs.cs @@ -0,0 +1,32 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp939Events; + +/// <summary> +/// Represents the event arguments for when SCP-939 has focused. +/// </summary> +public class Scp939FocusedEventArgs : EventArgs, IPlayerEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp939FocusedEventArgs"/> class. + /// </summary> + /// <param name="hub">The SCP-939 player instance.</param> + /// <param name="focusState">The SCP-939 is in focus state.</param> + public Scp939FocusedEventArgs(ReferenceHub hub, bool focusState) + { + Player = Player.Get(hub); + FocusState = focusState; + } + + /// <summary> + /// The 939 player instance. + /// </summary> + public Player Player { get; } + + /// <summary> + /// Gets the current state of the SCP-939 focus ability. + /// </summary> + public bool FocusState { get; } +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/Scp939Events/Scp939MimicedEnviromentEventArgs.cs b/LabApi/Events/Arguments/Scp939Events/Scp939MimicedEnviromentEventArgs.cs new file mode 100644 index 00000000..63b52843 --- /dev/null +++ b/LabApi/Events/Arguments/Scp939Events/Scp939MimicedEnviromentEventArgs.cs @@ -0,0 +1,32 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp939Events; + +/// <summary> +/// Represents the event arguments for when SCP-939 has mimiced enviroment. +/// </summary> +public class Scp939MimicedEnviromentEventArgs : EventArgs, IPlayerEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp939MimicedEnviromentEventArgs"/> class. + /// </summary> + /// <param name="hub">The SCP-939 player instance.</param> + /// <param name="playedSequence">The played enviromental sequence.</param> + public Scp939MimicedEnviromentEventArgs(ReferenceHub hub, byte playedSequence) + { + Player = Player.Get(hub); + PlayedSequence = playedSequence; + } + + /// <summary> + /// The 939 player instance. + /// </summary> + public Player Player { get; } + + /// <summary> + /// Gets the played enviromental sequence. + /// </summary> + public byte PlayedSequence { get; } +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/Scp939Events/Scp939MimicingEnviromentEventArgs.cs b/LabApi/Events/Arguments/Scp939Events/Scp939MimicingEnviromentEventArgs.cs new file mode 100644 index 00000000..0e08813e --- /dev/null +++ b/LabApi/Events/Arguments/Scp939Events/Scp939MimicingEnviromentEventArgs.cs @@ -0,0 +1,44 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp939Events; + +/// <summary> +/// Represents the event arguments for when SCP-939 is mimicing enviroment. +/// </summary> +public class Scp939MimicingEnviromentEventArgs : EventArgs, IPlayerEvent, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp939MimicingEnviromentEventArgs"/> class. + /// </summary> + /// <param name="hub">The SCP-939 player instance.</param> + /// <param name="selectedSequence">The selected enviromental sequence to play.</param> + /// <param name="cooldownTime">The cooldown for mimicing enviroment.</param> + public Scp939MimicingEnviromentEventArgs(ReferenceHub hub, byte selectedSequence, float cooldownTime) + { + Player = Player.Get(hub); + SelectedSequence = selectedSequence; + CooldownTime = cooldownTime; + + IsAllowed = true; + } + + /// <summary> + /// The 939 player instance. + /// </summary> + public Player Player { get; } + + /// <summary> + /// Gets or sets the selected sequence to play. + /// </summary> + public byte SelectedSequence { get; set; } + + /// <summary> + /// Gets or sets the cooldown for the mimicing enviroment. + /// </summary> + public float CooldownTime { get; set; } + + /// <inheritdoc/> + public bool IsAllowed { get; set; } +} \ No newline at end of file diff --git a/LabApi/Events/Handlers/Scp939Events.EventHandlers.cs b/LabApi/Events/Handlers/Scp939Events.EventHandlers.cs index b322067f..d0560ae6 100644 --- a/LabApi/Events/Handlers/Scp939Events.EventHandlers.cs +++ b/LabApi/Events/Handlers/Scp939Events.EventHandlers.cs @@ -36,4 +36,19 @@ public static partial class Scp939Events /// Gets called when SCP-939 has lunged. /// </summary> public static event LabEventHandler<Scp939LungedEventArgs>? Lunged; + + /// <summary> + /// Gets called when SCP-939 has focused. + /// </summary> + public static event LabEventHandler<Scp939FocusedEventArgs>? Focused; + + /// <summary> + /// Gets called when SCP-939 has focused. + /// </summary> + public static event LabEventHandler<Scp939MimicingEnviromentEventArgs>? MimicingEnviroment; + + /// <summary> + /// Gets called when SCP-939 has focused. + /// </summary> + public static event LabEventHandler<Scp939MimicedEnviromentEventArgs>? MimicedEnviroment; } \ No newline at end of file From 6f7251ec09d9b3d172a2287684237e64b0ba3475 Mon Sep 17 00:00:00 2001 From: jesusqc <contact@jesusqc.es> Date: Tue, 14 Oct 2025 18:14:11 +0200 Subject: [PATCH 176/215] version bump just in case --- LabApi/LabApi.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LabApi/LabApi.csproj b/LabApi/LabApi.csproj index eb703f50..edd29d88 100644 --- a/LabApi/LabApi.csproj +++ b/LabApi/LabApi.csproj @@ -6,7 +6,7 @@ <PlatformTarget>x64</PlatformTarget> <LangVersion>12.0</LangVersion> - <Version>1.1.3</Version> + <Version>1.1.4</Version> <AssemblyName>LabApi</AssemblyName> <PackageId>Northwood.LabAPI</PackageId> From e6859beff376e7516dc95ae60c82a58b5108d7d1 Mon Sep 17 00:00:00 2001 From: jesusqc <contact@jesusqc.es> Date: Tue, 14 Oct 2025 23:35:44 +0200 Subject: [PATCH 177/215] Fix methods --- .../LogAll/LogPlugin/MyCustomEventsHandler.cs | 20 ------------------- .../Facility/Respawning/Waves/RespawnWave.cs | 19 ++++++++++++++++-- LabApi/Features/Wrappers/Facility/Warhead.cs | 3 ++- .../Features/Wrappers/Items/MicroHIDItem.cs | 2 +- .../Wrappers/Items/Usable/UsableItem.cs | 2 +- 5 files changed, 21 insertions(+), 25 deletions(-) diff --git a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs index a30d16b4..b9600bb3 100644 --- a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs +++ b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs @@ -1680,26 +1680,6 @@ public override void OnPlayerSendingHitmarker(PlayerSendingHitmarkerEventArgs ev Logger.Info($"{nameof(OnPlayerSendingHitmarker)} triggered by {ev.Player} {ev.Size} {ev.PlayAudio}"); } - public override void OnServerMilestoneAchieving(AchievingMilestoneEventArgs ev) - { - Logger.Info($"{nameof(OnServerMilestoneAchieving)} triggered by {ev.Faction} {ev.Threshold} {ev.MilestoneIndex}"); - } - - public override void OnServerMilestoneAchieved(AchievedMilestoneEventArgs ev) - { - Logger.Info($"{nameof(OnServerMilestoneAchieved)} triggered by {ev.Faction} {ev.Threshold} {ev.MilestoneIndex}"); - } - - public override void OnServerFactionInfluenceModifying(ModifyingFactionInfluenceEventArgs ev) - { - Logger.Info($"{nameof(OnServerFactionInfluenceModifying)} triggered by {ev.Faction} {ev.Influence}"); - } - - public override void OnServerFactionInfluenceModified(ModifiedFactionInfluenceEventArgs ev) - { - Logger.Info($"{nameof(OnServerFactionInfluenceModified)} triggered by {ev.Faction} {ev.Influence}"); - } - #region Excluded Events // The following events spam the console and are therefore excluded from this example: diff --git a/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs b/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs index 5118ee4f..c5eb647a 100644 --- a/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs +++ b/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs @@ -1,4 +1,7 @@ -using PlayerRoles; +using System; +using System.Collections.Generic; +using System.Linq; +using PlayerRoles; using Respawning; using Respawning.Config; using Respawning.Waves; @@ -144,11 +147,21 @@ public float PausedTime /// <summary> /// Plays the respawn announcement. /// </summary> + [Obsolete("Use PlayAnnouncement(IEnumerable<Player>) instead.", true)] public void PlayAnnouncement() + { + PlayAnnouncement([]); + } + + /// <summary> + /// Plays the respawn announcement. + /// </summary> + /// <param name="spawnedPlayers">The players that have spawned to take into account for the announcement.</param> + public void PlayAnnouncement(IEnumerable<Player> spawnedPlayers) { if (Base is IAnnouncedWave wave) { - wave.Announcement.PlayAnnouncement(); + wave.Announcement.PlayAnnouncement(spawnedPlayers.Select(p => p.ReferenceHub).ToList()); } } @@ -158,7 +171,9 @@ public void PlayAnnouncement() public void PlayRespawnEffect() { if (Base is not IAnimatedWave) + { return; + } WaveUpdateMessage.ServerSendUpdate(Base, UpdateMessageFlags.Trigger); } diff --git a/LabApi/Features/Wrappers/Facility/Warhead.cs b/LabApi/Features/Wrappers/Facility/Warhead.cs index fdc3557e..3ef016a2 100644 --- a/LabApi/Features/Wrappers/Facility/Warhead.cs +++ b/LabApi/Features/Wrappers/Facility/Warhead.cs @@ -347,7 +347,8 @@ public readonly struct DetonationScenario internal DetonationScenario(AlphaWarheadController.DetonationScenario detonationScenario, byte id, WarheadScenarioType type) { TimeToDetonate = detonationScenario.TimeToDetonate; - AdditionalTime = detonationScenario.AdditionalTime; + // TODO: Remove the cast on 2.0.0 and change additional time to float + AdditionalTime = (int)detonationScenario.AdditionalTime; Type = type; Id = id; } diff --git a/LabApi/Features/Wrappers/Items/MicroHIDItem.cs b/LabApi/Features/Wrappers/Items/MicroHIDItem.cs index 840fe279..0afe1d0d 100644 --- a/LabApi/Features/Wrappers/Items/MicroHIDItem.cs +++ b/LabApi/Features/Wrappers/Items/MicroHIDItem.cs @@ -139,7 +139,7 @@ public MicroHidFiringMode FiringMode /// </summary> /// <param name="range">The sounds range in meters.</param> /// <returns>Returns true if the micro is emitting sound, otherwise false.</returns> - public bool TryGetSoundEmissionRange(out float range) => Base.ServerTryGetSoundEmissionRange(out range); + public bool TryGetSoundEmissionRange(out float range) => Base.TryGetSoundEmissionRange(out range); /// <summary> /// An internal method to remove itself from the cache when the base object is destroyed. diff --git a/LabApi/Features/Wrappers/Items/Usable/UsableItem.cs b/LabApi/Features/Wrappers/Items/Usable/UsableItem.cs index 717d0ab0..6c3debac 100644 --- a/LabApi/Features/Wrappers/Items/Usable/UsableItem.cs +++ b/LabApi/Features/Wrappers/Items/Usable/UsableItem.cs @@ -141,7 +141,7 @@ public float PersonalCooldownDuration /// </summary> /// <param name="range">The sounds range in meters.</param> /// <returns>Returns true if item is being used, otherwise false.</returns> - public bool TryGetSoundEmissionRange(out float range) => Base.ServerTryGetSoundEmissionRange(out range); + public bool TryGetSoundEmissionRange(out float range) => Base.TryGetSoundEmissionRange(out range); /// <summary> /// An internal method to remove itself from the cache when the base object is destroyed. From 84d68bc60b9eb646c993150c75a063a92af5ae36 Mon Sep 17 00:00:00 2001 From: Axwabo <axwabo@gmail.com> Date: Wed, 15 Oct 2025 11:55:26 +0200 Subject: [PATCH 178/215] per-port global LoadUnsupportedPlugins property --- LabApi/Loader/Features/Configuration/LabApiConfig.cs | 8 +++++++- LabApi/Loader/PluginLoader.cs | 3 ++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/LabApi/Loader/Features/Configuration/LabApiConfig.cs b/LabApi/Loader/Features/Configuration/LabApiConfig.cs index db52086d..764f3c3a 100644 --- a/LabApi/Loader/Features/Configuration/LabApiConfig.cs +++ b/LabApi/Loader/Features/Configuration/LabApiConfig.cs @@ -20,4 +20,10 @@ public class LabApiConfig /// </summary> [Description("List of plugin paths relative to the Plugins folder to load from. Use $port to load from the server port's folder.")] public List<string> PluginPaths { get; set; } = ["global", "$port"]; -} \ No newline at end of file + + /// <summary> + /// Whether to allow loading plugins even if they were built for a different major version of LabAPI. + /// </summary> + [Description("Whether to allow loading plugins even if they were built for a different major version of LabAPI.")] + public bool LoadUnsupportedPlugins { get; set; } +} diff --git a/LabApi/Loader/PluginLoader.cs b/LabApi/Loader/PluginLoader.cs index 4fed3a7b..f653814d 100644 --- a/LabApi/Loader/PluginLoader.cs +++ b/LabApi/Loader/PluginLoader.cs @@ -391,7 +391,7 @@ Are you running an older version of the server? string difference = required.Major < current.Major ? "an outdated major version" : "a newer major version"; - if (plugin.Properties?.ForceUnsupportedMajorVersion == true) + if (Config.LoadUnsupportedPlugins || plugin.Properties?.ForceUnsupportedMajorVersion == true) { Logger.Warn($""" {LoggerPrefix} Forcefully loading unsupported plugin {plugin} @@ -406,6 +406,7 @@ Are you running an older version of the server? {LoggerPrefix} Couldn't enable the plugin {plugin} It was built for {difference} of LabAPI, and would likely have degraded functionality. To forcefully load it, set the appropriate property in the plugins's properties.yml file. + To forcefully load all unsupported plugins, set the appropriate property in the LabAPI configuration for the current port (LabApi-{Server.Port}.yml). Current LabAPI version: {LabApiProperties.CompiledVersion} Required by plugin: {required} """); From e2adeb762f62473b2e9a427d72d8ffbf9969eb03 Mon Sep 17 00:00:00 2001 From: Axwabo <axwabo@gmail.com> Date: Wed, 15 Oct 2025 12:11:25 +0200 Subject: [PATCH 179/215] rename ForceUnsupportedMajorVersion --- LabApi/Loader/Features/Plugins/Configuration/Properties.cs | 2 +- LabApi/Loader/PluginLoader.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LabApi/Loader/Features/Plugins/Configuration/Properties.cs b/LabApi/Loader/Features/Plugins/Configuration/Properties.cs index 0a208522..d8fcbf47 100644 --- a/LabApi/Loader/Features/Plugins/Configuration/Properties.cs +++ b/LabApi/Loader/Features/Plugins/Configuration/Properties.cs @@ -23,5 +23,5 @@ public class Properties /// Whether to allow loading the plugin even if it was built for a different major version of LabAPI. /// </summary> [Description("Whether to allow loading the plugin even if it was built for a different major version of LabAPI.")] - public bool ForceUnsupportedMajorVersion { get; set; } + public bool LoadIfUnsupported { get; set; } } diff --git a/LabApi/Loader/PluginLoader.cs b/LabApi/Loader/PluginLoader.cs index f653814d..5867dbea 100644 --- a/LabApi/Loader/PluginLoader.cs +++ b/LabApi/Loader/PluginLoader.cs @@ -391,7 +391,7 @@ Are you running an older version of the server? string difference = required.Major < current.Major ? "an outdated major version" : "a newer major version"; - if (Config.LoadUnsupportedPlugins || plugin.Properties?.ForceUnsupportedMajorVersion == true) + if (Config.LoadUnsupportedPlugins || plugin.Properties?.LoadIfUnsupported == true) { Logger.Warn($""" {LoggerPrefix} Forcefully loading unsupported plugin {plugin} From 7422030253167553637c0336eadb11263d136965 Mon Sep 17 00:00:00 2001 From: Axwabo <axwabo@gmail.com> Date: Thu, 16 Oct 2025 07:51:28 +0200 Subject: [PATCH 180/215] OutdatedLoadingBehavior --- .../Features/Configuration/LabApiConfig.cs | 1 + .../Plugins/Configuration/Properties.cs | 10 ++++-- .../Plugins/Enums/OutdatedLoadingBehavior.cs | 32 +++++++++++++++++++ LabApi/Loader/PluginLoader.cs | 10 +++++- 4 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 LabApi/Loader/Features/Plugins/Enums/OutdatedLoadingBehavior.cs diff --git a/LabApi/Loader/Features/Configuration/LabApiConfig.cs b/LabApi/Loader/Features/Configuration/LabApiConfig.cs index 764f3c3a..47bea231 100644 --- a/LabApi/Loader/Features/Configuration/LabApiConfig.cs +++ b/LabApi/Loader/Features/Configuration/LabApiConfig.cs @@ -24,6 +24,7 @@ public class LabApiConfig /// <summary> /// Whether to allow loading plugins even if they were built for a different major version of LabAPI. /// </summary> + /// <seealso cref="LabApi.Loader.Features.Plugins.Configuration.Properties.UnsupportedLoading"/> [Description("Whether to allow loading plugins even if they were built for a different major version of LabAPI.")] public bool LoadUnsupportedPlugins { get; set; } } diff --git a/LabApi/Loader/Features/Plugins/Configuration/Properties.cs b/LabApi/Loader/Features/Plugins/Configuration/Properties.cs index d8fcbf47..c6a81b4b 100644 --- a/LabApi/Loader/Features/Plugins/Configuration/Properties.cs +++ b/LabApi/Loader/Features/Plugins/Configuration/Properties.cs @@ -1,3 +1,4 @@ +using LabApi.Loader.Features.Plugins.Enums; using System.ComponentModel; namespace LabApi.Loader.Features.Plugins.Configuration; @@ -22,6 +23,11 @@ public class Properties /// <summary> /// Whether to allow loading the plugin even if it was built for a different major version of LabAPI. /// </summary> - [Description("Whether to allow loading the plugin even if it was built for a different major version of LabAPI.")] - public bool LoadIfUnsupported { get; set; } + [Description(""" + Whether to allow loading the plugin even if it was built for a different major version of LabAPI. + Default = use port-specific config + True/Enabled = load if unsupported + False/Disabled = do not load if unsupported + """)] + public OutdatedLoadingBehavior UnsupportedLoading { get; set; } } diff --git a/LabApi/Loader/Features/Plugins/Enums/OutdatedLoadingBehavior.cs b/LabApi/Loader/Features/Plugins/Enums/OutdatedLoadingBehavior.cs new file mode 100644 index 00000000..0cc59e5b --- /dev/null +++ b/LabApi/Loader/Features/Plugins/Enums/OutdatedLoadingBehavior.cs @@ -0,0 +1,32 @@ +using LabApi.Loader.Features.Plugins.Configuration; + +namespace LabApi.Loader.Features.Plugins.Enums; + +/// <summary> +/// Represents values whether a specific unsupported <see cref="Plugin"/> should be loaded. +/// </summary> +/// <seealso cref="Properties.UnsupportedLoading"/> +public enum OutdatedLoadingBehavior +{ + /// <summary> + /// Uses the setting in the port-specific LabAPI config. + /// </summary> + /// <seealso cref="LabApi.Loader.Features.Configuration.LabApiConfig.LoadUnsupportedPlugins"/> + Default, + + /// <summary> + /// Overrides the port-specific setting to load the plugin even if it's unsupported. + /// </summary> + True, + + /// <summary> + /// Overrides the port-specific setting not to load the plugin if it's unsupported. + /// </summary> + False, + + /// <inheritdoc cref="True" /> + Enabled = True, + + /// <inheritdoc cref="False" /> + Disabled = False, +} diff --git a/LabApi/Loader/PluginLoader.cs b/LabApi/Loader/PluginLoader.cs index 5867dbea..6f7a3422 100644 --- a/LabApi/Loader/PluginLoader.cs +++ b/LabApi/Loader/PluginLoader.cs @@ -7,6 +7,7 @@ using LabApi.Loader.Features.Misc; using LabApi.Loader.Features.Paths; using LabApi.Loader.Features.Plugins; +using LabApi.Loader.Features.Plugins.Enums; using LabApi.Loader.Features.Yaml; using System; using System.Collections.Generic; @@ -391,7 +392,14 @@ Are you running an older version of the server? string difference = required.Major < current.Major ? "an outdated major version" : "a newer major version"; - if (Config.LoadUnsupportedPlugins || plugin.Properties?.LoadIfUnsupported == true) + bool shouldLoad = plugin.Properties?.UnsupportedLoading switch + { + OutdatedLoadingBehavior.True => true, + OutdatedLoadingBehavior.False => false, + _ => Config.LoadUnsupportedPlugins, + }; + + if (shouldLoad) { Logger.Warn($""" {LoggerPrefix} Forcefully loading unsupported plugin {plugin} From 8882412f1c59df2bfb9621bb8a0b0da32d1ebb19 Mon Sep 17 00:00:00 2001 From: SlejmUr <slejmur@protonmail.com> Date: Sat, 18 Oct 2025 12:06:56 +0200 Subject: [PATCH 181/215] Adding support for multiple command handlers. --- LabApi/Loader/CommandLoader.cs | 60 ++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 21 deletions(-) diff --git a/LabApi/Loader/CommandLoader.cs b/LabApi/Loader/CommandLoader.cs index d1a6723a..57fc35fb 100644 --- a/LabApi/Loader/CommandLoader.cs +++ b/LabApi/Loader/CommandLoader.cs @@ -22,16 +22,16 @@ public static class CommandLoader /// <summary> /// The dictionary of command handlers. /// </summary> - public static Dictionary<Type, CommandHandler> CommandHandlers { get; } = new() + public static Dictionary<Type, List<CommandHandler>> CommandHandlers { get; } = new() { // The server console command handler. - [typeof(GameConsoleCommandHandler)] = GameCore.Console.ConsoleCommandHandler, + [typeof(GameConsoleCommandHandler)] = [GameCore.Console.ConsoleCommandHandler], // The remote admin command handler. - [typeof(RemoteAdminCommandHandler)] = CommandProcessor.RemoteAdminCommandHandler, + [typeof(RemoteAdminCommandHandler)] = [CommandProcessor.RemoteAdminCommandHandler], // The client console command handler. - [typeof(ClientCommandHandler)] = QueryProcessor.DotCommandHandler, + [typeof(ClientCommandHandler)] = [QueryProcessor.DotCommandHandler], }; /// <summary> @@ -148,14 +148,8 @@ public static bool TryRegisterCommand(Type commandType, Type commandHandlerType, { command = null; - if (CommandHandlers.ContainsKey(commandType)) - { - // This parent command was already registered. - return false; - } - // We try to get the command handler from the dictionary of command handlers. - if (!CommandHandlers.TryGetValue(commandHandlerType, out CommandHandler commandHandler)) + if (!CommandHandlers.TryGetValue(commandHandlerType, out List<CommandHandler> commandHandlers)) { Logger.Error($"{LoggerPrefix} Unable to register command '{commandType.Name}' from '{logName}'. CommandHandler '{commandHandlerType}' not found."); return false; @@ -180,8 +174,17 @@ public static bool TryRegisterCommand(Type commandType, Type commandHandlerType, throw; } - // We finally try to register the command in the command handler. - return TryRegisterCommand(command, commandHandler, logName); + // We iterate through all command handlers (including subcommand that has multiple handler). + foreach (CommandHandler commandHandler in commandHandlers) + { + // We finally try to register the command in the command handler. + if (!TryRegisterCommand(command, commandHandler, logName)) + { + return false; + } + } + + return true; } /// <summary> @@ -195,6 +198,12 @@ public static bool TryRegisterCommand(ICommand command, CommandHandler commandHa { try { + // We check if the command already registered (might happen) and just return. + if (commandHandler.AllCommands.Any(x => string.Equals(x.Command, command.Command, StringComparison.OrdinalIgnoreCase))) + { + return true; + } + // We try to register the command. commandHandler.RegisterCommand(command); @@ -208,10 +217,16 @@ public static bool TryRegisterCommand(ICommand command, CommandHandler commandHa // This allows us to register subcommands to the parent command by just using the CommandHandlerAttribute. // [CommandHandler(typeof(MyParentCommand))] Type commandType = command.GetType(); + if (!CommandHandlers.ContainsKey(commandType)) { // We add the command type to the dictionary of command handlers. - CommandHandlers.Add(commandType, parentCommand); + CommandHandlers[commandType] = []; + } + + if (!CommandHandlers[commandType].Contains(parentCommand)) + { + CommandHandlers[commandType].Add(parentCommand); } // We can finally return true. @@ -262,16 +277,19 @@ public static void UnregisterCommands(this Plugin plugin) public static void UnregisterCommand(ICommand command) { // We iterate through all command handlers. - foreach (CommandHandler commandHandler in CommandHandlers.Values) + foreach (List<CommandHandler> commandHandlers in CommandHandlers.Values) { - // If the command handler does not contain the command, we continue. - if (!commandHandler.AllCommands.Contains(command)) + foreach (CommandHandler commandHandler in commandHandlers) { - continue; - } + // If the command handler does not contain the command, we continue. + if (!commandHandler.AllCommands.Contains(command)) + { + continue; + } - // We manually unregister the command from the command handler. - commandHandler.UnregisterCommand(command); + // We manually unregister the command from the command handler. + commandHandler.UnregisterCommand(command); + } } // We check if the command is a parent command. From 7f2487915342ee08c69ee499acfb69df68627fc5 Mon Sep 17 00:00:00 2001 From: Axwabo <axwabo@gmail.com> Date: Sat, 18 Oct 2025 16:36:49 +0200 Subject: [PATCH 182/215] make OutdatedLoadingBehavior more generic & reorder its values --- .../Plugins/Configuration/Properties.cs | 2 +- .../Features/Plugins/Enums/OptionalBoolean.cs | 28 ++++++++++++++++ .../Plugins/Enums/OutdatedLoadingBehavior.cs | 32 ------------------- LabApi/Loader/PluginLoader.cs | 14 ++++---- 4 files changed, 36 insertions(+), 40 deletions(-) create mode 100644 LabApi/Loader/Features/Plugins/Enums/OptionalBoolean.cs delete mode 100644 LabApi/Loader/Features/Plugins/Enums/OutdatedLoadingBehavior.cs diff --git a/LabApi/Loader/Features/Plugins/Configuration/Properties.cs b/LabApi/Loader/Features/Plugins/Configuration/Properties.cs index c6a81b4b..938e5956 100644 --- a/LabApi/Loader/Features/Plugins/Configuration/Properties.cs +++ b/LabApi/Loader/Features/Plugins/Configuration/Properties.cs @@ -29,5 +29,5 @@ public class Properties True/Enabled = load if unsupported False/Disabled = do not load if unsupported """)] - public OutdatedLoadingBehavior UnsupportedLoading { get; set; } + public OptionalBoolean UnsupportedLoading { get; set; } = OptionalBoolean.Default; } diff --git a/LabApi/Loader/Features/Plugins/Enums/OptionalBoolean.cs b/LabApi/Loader/Features/Plugins/Enums/OptionalBoolean.cs new file mode 100644 index 00000000..3295ab49 --- /dev/null +++ b/LabApi/Loader/Features/Plugins/Enums/OptionalBoolean.cs @@ -0,0 +1,28 @@ +namespace LabApi.Loader.Features.Plugins.Enums; + +/// <summary> +/// Represents values that specify whether a feature should be activated. +/// </summary> +public enum OptionalBoolean +{ + /// <summary> + /// Uses default behavior, specified in the feature's implementation or in a broader scope. + /// </summary> + Default = -1, + + /// <summary> + /// Overrides default behavior to disable the feature. + /// </summary> + False = 0, + + /// <summary> + /// Overrides default behavior to enable the feature. + /// </summary> + True = 1, + + /// <inheritdoc cref="True" /> + Enabled = True, + + /// <inheritdoc cref="False" /> + Disabled = False, +} diff --git a/LabApi/Loader/Features/Plugins/Enums/OutdatedLoadingBehavior.cs b/LabApi/Loader/Features/Plugins/Enums/OutdatedLoadingBehavior.cs deleted file mode 100644 index 0cc59e5b..00000000 --- a/LabApi/Loader/Features/Plugins/Enums/OutdatedLoadingBehavior.cs +++ /dev/null @@ -1,32 +0,0 @@ -using LabApi.Loader.Features.Plugins.Configuration; - -namespace LabApi.Loader.Features.Plugins.Enums; - -/// <summary> -/// Represents values whether a specific unsupported <see cref="Plugin"/> should be loaded. -/// </summary> -/// <seealso cref="Properties.UnsupportedLoading"/> -public enum OutdatedLoadingBehavior -{ - /// <summary> - /// Uses the setting in the port-specific LabAPI config. - /// </summary> - /// <seealso cref="LabApi.Loader.Features.Configuration.LabApiConfig.LoadUnsupportedPlugins"/> - Default, - - /// <summary> - /// Overrides the port-specific setting to load the plugin even if it's unsupported. - /// </summary> - True, - - /// <summary> - /// Overrides the port-specific setting not to load the plugin if it's unsupported. - /// </summary> - False, - - /// <inheritdoc cref="True" /> - Enabled = True, - - /// <inheritdoc cref="False" /> - Disabled = False, -} diff --git a/LabApi/Loader/PluginLoader.cs b/LabApi/Loader/PluginLoader.cs index 6f7a3422..545cfd64 100644 --- a/LabApi/Loader/PluginLoader.cs +++ b/LabApi/Loader/PluginLoader.cs @@ -394,19 +394,19 @@ Are you running an older version of the server? bool shouldLoad = plugin.Properties?.UnsupportedLoading switch { - OutdatedLoadingBehavior.True => true, - OutdatedLoadingBehavior.False => false, + OptionalBoolean.True => true, + OptionalBoolean.False => false, _ => Config.LoadUnsupportedPlugins, }; if (shouldLoad) { Logger.Warn($""" - {LoggerPrefix} Forcefully loading unsupported plugin {plugin} - It was built for {difference} of LabAPI, and will likely have degraded functionality. - Current LabAPI version: {LabApiProperties.CompiledVersion} - Required by plugin: {required} - """); + {LoggerPrefix} Forcefully loading unsupported plugin {plugin} + It was built for {difference} of LabAPI, and will likely have degraded functionality. + Current LabAPI version: {LabApiProperties.CompiledVersion} + Required by plugin: {required} + """); return true; } From fef3a3793e0aef3426754a257191b00074b54e8f Mon Sep 17 00:00:00 2001 From: SlejmUr <slejmur@protonmail.com> Date: Sat, 18 Oct 2025 14:57:44 +0000 Subject: [PATCH 183/215] Apply 13 suggestion(s) to 4 file(s) Co-authored-by: Jesus-QC <99-jesusqc@users.noreply.git.scpslgame.com> --- .../Arguments/Scp939Events/Scp939FocusedEventArgs.cs | 4 ++-- .../Scp939Events/Scp939MimicedEnviromentEventArgs.cs | 8 ++++---- .../Scp939Events/Scp939MimicingEnviromentEventArgs.cs | 10 +++++----- LabApi/Events/Handlers/Scp939Events.EventHandlers.cs | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/LabApi/Events/Arguments/Scp939Events/Scp939FocusedEventArgs.cs b/LabApi/Events/Arguments/Scp939Events/Scp939FocusedEventArgs.cs index fe5a1cb6..67400b06 100644 --- a/LabApi/Events/Arguments/Scp939Events/Scp939FocusedEventArgs.cs +++ b/LabApi/Events/Arguments/Scp939Events/Scp939FocusedEventArgs.cs @@ -13,7 +13,7 @@ public class Scp939FocusedEventArgs : EventArgs, IPlayerEvent /// Initializes a new instance of the <see cref="Scp939FocusedEventArgs"/> class. /// </summary> /// <param name="hub">The SCP-939 player instance.</param> - /// <param name="focusState">The SCP-939 is in focus state.</param> + /// <param name="focusState">A value indicating whether SCP-939 is in the focus state.</param> public Scp939FocusedEventArgs(ReferenceHub hub, bool focusState) { Player = Player.Get(hub); @@ -21,7 +21,7 @@ public Scp939FocusedEventArgs(ReferenceHub hub, bool focusState) } /// <summary> - /// The 939 player instance. + /// Gets the 939 player instance. /// </summary> public Player Player { get; } diff --git a/LabApi/Events/Arguments/Scp939Events/Scp939MimicedEnviromentEventArgs.cs b/LabApi/Events/Arguments/Scp939Events/Scp939MimicedEnviromentEventArgs.cs index 63b52843..6e49e181 100644 --- a/LabApi/Events/Arguments/Scp939Events/Scp939MimicedEnviromentEventArgs.cs +++ b/LabApi/Events/Arguments/Scp939Events/Scp939MimicedEnviromentEventArgs.cs @@ -5,7 +5,7 @@ namespace LabApi.Events.Arguments.Scp939Events; /// <summary> -/// Represents the event arguments for when SCP-939 has mimiced enviroment. +/// Represents the event arguments for when SCP-939 has mimicked the environment. /// </summary> public class Scp939MimicedEnviromentEventArgs : EventArgs, IPlayerEvent { @@ -13,7 +13,7 @@ public class Scp939MimicedEnviromentEventArgs : EventArgs, IPlayerEvent /// Initializes a new instance of the <see cref="Scp939MimicedEnviromentEventArgs"/> class. /// </summary> /// <param name="hub">The SCP-939 player instance.</param> - /// <param name="playedSequence">The played enviromental sequence.</param> + /// <param name="playedSequence">The played environmental sequence.</param> public Scp939MimicedEnviromentEventArgs(ReferenceHub hub, byte playedSequence) { Player = Player.Get(hub); @@ -21,12 +21,12 @@ public Scp939MimicedEnviromentEventArgs(ReferenceHub hub, byte playedSequence) } /// <summary> - /// The 939 player instance. + /// Gets the 939 player instance. /// </summary> public Player Player { get; } /// <summary> - /// Gets the played enviromental sequence. + /// Gets the played environmental sequence. /// </summary> public byte PlayedSequence { get; } } \ No newline at end of file diff --git a/LabApi/Events/Arguments/Scp939Events/Scp939MimicingEnviromentEventArgs.cs b/LabApi/Events/Arguments/Scp939Events/Scp939MimicingEnviromentEventArgs.cs index 0e08813e..ca5cc4b9 100644 --- a/LabApi/Events/Arguments/Scp939Events/Scp939MimicingEnviromentEventArgs.cs +++ b/LabApi/Events/Arguments/Scp939Events/Scp939MimicingEnviromentEventArgs.cs @@ -5,7 +5,7 @@ namespace LabApi.Events.Arguments.Scp939Events; /// <summary> -/// Represents the event arguments for when SCP-939 is mimicing enviroment. +/// Represents the event arguments for when SCP-939 is mimicking the environment. /// </summary> public class Scp939MimicingEnviromentEventArgs : EventArgs, IPlayerEvent, ICancellableEvent { @@ -13,8 +13,8 @@ public class Scp939MimicingEnviromentEventArgs : EventArgs, IPlayerEvent, ICance /// Initializes a new instance of the <see cref="Scp939MimicingEnviromentEventArgs"/> class. /// </summary> /// <param name="hub">The SCP-939 player instance.</param> - /// <param name="selectedSequence">The selected enviromental sequence to play.</param> - /// <param name="cooldownTime">The cooldown for mimicing enviroment.</param> + /// <param name="selectedSequence">The selected environmental sequence to play.</param> + /// <param name="cooldownTime">The cooldown for mimicking the environment.</param> public Scp939MimicingEnviromentEventArgs(ReferenceHub hub, byte selectedSequence, float cooldownTime) { Player = Player.Get(hub); @@ -25,7 +25,7 @@ public Scp939MimicingEnviromentEventArgs(ReferenceHub hub, byte selectedSequence } /// <summary> - /// The 939 player instance. + /// Gets the 939 player instance. /// </summary> public Player Player { get; } @@ -35,7 +35,7 @@ public Scp939MimicingEnviromentEventArgs(ReferenceHub hub, byte selectedSequence public byte SelectedSequence { get; set; } /// <summary> - /// Gets or sets the cooldown for the mimicing enviroment. + /// Gets or sets the cooldown for mimicking the environment. /// </summary> public float CooldownTime { get; set; } diff --git a/LabApi/Events/Handlers/Scp939Events.EventHandlers.cs b/LabApi/Events/Handlers/Scp939Events.EventHandlers.cs index d0560ae6..39606df3 100644 --- a/LabApi/Events/Handlers/Scp939Events.EventHandlers.cs +++ b/LabApi/Events/Handlers/Scp939Events.EventHandlers.cs @@ -43,12 +43,12 @@ public static partial class Scp939Events public static event LabEventHandler<Scp939FocusedEventArgs>? Focused; /// <summary> - /// Gets called when SCP-939 has focused. + /// Gets called when SCP-939 is mimicking the environment. /// </summary> public static event LabEventHandler<Scp939MimicingEnviromentEventArgs>? MimicingEnviroment; /// <summary> - /// Gets called when SCP-939 has focused. + /// Gets called when SCP-939 has mimicked the environment. /// </summary> public static event LabEventHandler<Scp939MimicedEnviromentEventArgs>? MimicedEnviroment; } \ No newline at end of file From 4661ff09dc4c3d11c0bbb517c0808d284a405fd5 Mon Sep 17 00:00:00 2001 From: SlejmUr <slejmur@protonmail.com> Date: Sat, 18 Oct 2025 17:05:54 +0200 Subject: [PATCH 184/215] Rename Mimicing -> Mimicking Rename Enviroment -> Environment --- ...ntEventArgs.cs => Scp939MimickedEnvironmentEventArgs.cs} | 6 +++--- ...tEventArgs.cs => Scp939MimickingEnvironmentEventArgs.cs} | 6 +++--- LabApi/Events/Handlers/Scp939Events.EventHandlers.cs | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) rename LabApi/Events/Arguments/Scp939Events/{Scp939MimicedEnviromentEventArgs.cs => Scp939MimickedEnvironmentEventArgs.cs} (80%) rename LabApi/Events/Arguments/Scp939Events/{Scp939MimicingEnviromentEventArgs.cs => Scp939MimickingEnvironmentEventArgs.cs} (83%) diff --git a/LabApi/Events/Arguments/Scp939Events/Scp939MimicedEnviromentEventArgs.cs b/LabApi/Events/Arguments/Scp939Events/Scp939MimickedEnvironmentEventArgs.cs similarity index 80% rename from LabApi/Events/Arguments/Scp939Events/Scp939MimicedEnviromentEventArgs.cs rename to LabApi/Events/Arguments/Scp939Events/Scp939MimickedEnvironmentEventArgs.cs index 6e49e181..cb49c1e2 100644 --- a/LabApi/Events/Arguments/Scp939Events/Scp939MimicedEnviromentEventArgs.cs +++ b/LabApi/Events/Arguments/Scp939Events/Scp939MimickedEnvironmentEventArgs.cs @@ -7,14 +7,14 @@ namespace LabApi.Events.Arguments.Scp939Events; /// <summary> /// Represents the event arguments for when SCP-939 has mimicked the environment. /// </summary> -public class Scp939MimicedEnviromentEventArgs : EventArgs, IPlayerEvent +public class Scp939MimickedEnvironmentEventArgs : EventArgs, IPlayerEvent { /// <summary> - /// Initializes a new instance of the <see cref="Scp939MimicedEnviromentEventArgs"/> class. + /// Initializes a new instance of the <see cref="Scp939MimickedEnvironmentEventArgs"/> class. /// </summary> /// <param name="hub">The SCP-939 player instance.</param> /// <param name="playedSequence">The played environmental sequence.</param> - public Scp939MimicedEnviromentEventArgs(ReferenceHub hub, byte playedSequence) + public Scp939MimickedEnvironmentEventArgs(ReferenceHub hub, byte playedSequence) { Player = Player.Get(hub); PlayedSequence = playedSequence; diff --git a/LabApi/Events/Arguments/Scp939Events/Scp939MimicingEnviromentEventArgs.cs b/LabApi/Events/Arguments/Scp939Events/Scp939MimickingEnvironmentEventArgs.cs similarity index 83% rename from LabApi/Events/Arguments/Scp939Events/Scp939MimicingEnviromentEventArgs.cs rename to LabApi/Events/Arguments/Scp939Events/Scp939MimickingEnvironmentEventArgs.cs index ca5cc4b9..c2381769 100644 --- a/LabApi/Events/Arguments/Scp939Events/Scp939MimicingEnviromentEventArgs.cs +++ b/LabApi/Events/Arguments/Scp939Events/Scp939MimickingEnvironmentEventArgs.cs @@ -7,15 +7,15 @@ namespace LabApi.Events.Arguments.Scp939Events; /// <summary> /// Represents the event arguments for when SCP-939 is mimicking the environment. /// </summary> -public class Scp939MimicingEnviromentEventArgs : EventArgs, IPlayerEvent, ICancellableEvent +public class Scp939MimickingEnvironmentEventArgs : EventArgs, IPlayerEvent, ICancellableEvent { /// <summary> - /// Initializes a new instance of the <see cref="Scp939MimicingEnviromentEventArgs"/> class. + /// Initializes a new instance of the <see cref="Scp939MimickingEnvironmentEventArgs"/> class. /// </summary> /// <param name="hub">The SCP-939 player instance.</param> /// <param name="selectedSequence">The selected environmental sequence to play.</param> /// <param name="cooldownTime">The cooldown for mimicking the environment.</param> - public Scp939MimicingEnviromentEventArgs(ReferenceHub hub, byte selectedSequence, float cooldownTime) + public Scp939MimickingEnvironmentEventArgs(ReferenceHub hub, byte selectedSequence, float cooldownTime) { Player = Player.Get(hub); SelectedSequence = selectedSequence; diff --git a/LabApi/Events/Handlers/Scp939Events.EventHandlers.cs b/LabApi/Events/Handlers/Scp939Events.EventHandlers.cs index 39606df3..ac815205 100644 --- a/LabApi/Events/Handlers/Scp939Events.EventHandlers.cs +++ b/LabApi/Events/Handlers/Scp939Events.EventHandlers.cs @@ -45,10 +45,10 @@ public static partial class Scp939Events /// <summary> /// Gets called when SCP-939 is mimicking the environment. /// </summary> - public static event LabEventHandler<Scp939MimicingEnviromentEventArgs>? MimicingEnviroment; + public static event LabEventHandler<Scp939MimickingEnvironmentEventArgs>? MimickingEnvironment; /// <summary> /// Gets called when SCP-939 has mimicked the environment. /// </summary> - public static event LabEventHandler<Scp939MimicedEnviromentEventArgs>? MimicedEnviroment; + public static event LabEventHandler<Scp939MimickedEnvironmentEventArgs>? MimickedEnvironment; } \ No newline at end of file From e5cbc83894ab2ae88a2b2892e963f4667c5a108a Mon Sep 17 00:00:00 2001 From: SlejmUr <slejmur@protonmail.com> Date: Sun, 19 Oct 2025 12:31:36 +0200 Subject: [PATCH 185/215] Fix event name in xml ReAdd events --- .../LogAll/LogPlugin/MyCustomEventsHandler.cs | 26 +++++++++++++++++++ .../ScpEvents/ScpHumeShieldBrokenEventArgs.cs | 2 +- .../AchievedMilestoneEventArgs.cs | 2 +- .../AchievingMilestoneEventArgs.cs | 2 +- .../ModifiedFactionInfluenceEventArgs.cs | 2 +- .../ModifyingFactionInfluenceEventArgs.cs | 2 +- 6 files changed, 31 insertions(+), 5 deletions(-) diff --git a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs index b9600bb3..3cd189b6 100644 --- a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs +++ b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs @@ -11,6 +11,7 @@ using LabApi.Events.Arguments.Scp3114Events; using LabApi.Events.Arguments.Scp914Events; using LabApi.Events.Arguments.Scp939Events; +using LabApi.Events.Arguments.ScpEvents; using LabApi.Events.Arguments.ServerEvents; using LabApi.Events.Arguments.WarheadEvents; using LabApi.Events.CustomHandlers; @@ -1680,6 +1681,31 @@ public override void OnPlayerSendingHitmarker(PlayerSendingHitmarkerEventArgs ev Logger.Info($"{nameof(OnPlayerSendingHitmarker)} triggered by {ev.Player} {ev.Size} {ev.PlayAudio}"); } + public override void OnScpHumeShieldBroken(ScpHumeShieldBrokenEventArgs ev) + { + Logger.Info($"{nameof(OnScpHumeShieldBroken)} triggered by {ev.Player}"); + } + + public override void OnServerAchievedMilestone(AchievedMilestoneEventArgs ev) + { + Logger.Info($"{nameof(OnServerAchievedMilestone)} triggered by {ev.Faction} {ev.Threshold} {ev.MilestoneIndex}"); + } + + public override void OnServerAchievingMilestone(AchievingMilestoneEventArgs ev) + { + Logger.Info($"{nameof(OnServerAchievingMilestone)} triggered by {ev.Faction} {ev.Threshold} {ev.MilestoneIndex}"); + } + + public override void OnServerModifiedFactionInfluence(ModifiedFactionInfluenceEventArgs ev) + { + Logger.Info($"{nameof(OnServerModifiedFactionInfluence)} triggered by {ev.Faction} {ev.Influence}"); + } + + public override void OnServerModifyingFactionInfluence(ModifyingFactionInfluenceEventArgs ev) + { + Logger.Info($"{nameof(OnServerModifyingFactionInfluence)} triggered by {ev.Faction} {ev.Influence}"); + } + #region Excluded Events // The following events spam the console and are therefore excluded from this example: diff --git a/LabApi/Events/Arguments/ScpEvents/ScpHumeShieldBrokenEventArgs.cs b/LabApi/Events/Arguments/ScpEvents/ScpHumeShieldBrokenEventArgs.cs index 51468085..0c3f14de 100644 --- a/LabApi/Events/Arguments/ScpEvents/ScpHumeShieldBrokenEventArgs.cs +++ b/LabApi/Events/Arguments/ScpEvents/ScpHumeShieldBrokenEventArgs.cs @@ -5,7 +5,7 @@ namespace LabApi.Events.Arguments.ScpEvents; /// <summary> -/// Represents the arguments for the <see cref="Handlers.ScpEvents.ScpHumeShieldBroken"/> event. +/// Represents the arguments for the <see cref="Handlers.ScpEvents.HumeShieldBroken"/> event. /// </summary> public class ScpHumeShieldBrokenEventArgs : EventArgs, IPlayerEvent { diff --git a/LabApi/Events/Arguments/ServerEvents/AchievedMilestoneEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/AchievedMilestoneEventArgs.cs index d98b73a9..1dd99dd7 100644 --- a/LabApi/Events/Arguments/ServerEvents/AchievedMilestoneEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/AchievedMilestoneEventArgs.cs @@ -4,7 +4,7 @@ namespace LabApi.Events.Arguments.ServerEvents; /// <summary> -/// Represents the arguments for the <see cref="Handlers.ServerEvents.MilestoneAchieved"/> event. +/// Represents the arguments for the <see cref="Handlers.ServerEvents.AchievedMilestone"/> event. /// </summary> public class AchievedMilestoneEventArgs : EventArgs { diff --git a/LabApi/Events/Arguments/ServerEvents/AchievingMilestoneEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/AchievingMilestoneEventArgs.cs index 9eb81e33..3a9992ee 100644 --- a/LabApi/Events/Arguments/ServerEvents/AchievingMilestoneEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/AchievingMilestoneEventArgs.cs @@ -5,7 +5,7 @@ namespace LabApi.Events.Arguments.ServerEvents; /// <summary> -/// Represents the arguments for the <see cref="Handlers.ServerEvents.MilestoneAchieving"/> event. +/// Represents the arguments for the <see cref="Handlers.ServerEvents.AchievingMilestone"/> event. /// </summary> public class AchievingMilestoneEventArgs : EventArgs, ICancellableEvent { diff --git a/LabApi/Events/Arguments/ServerEvents/ModifiedFactionInfluenceEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/ModifiedFactionInfluenceEventArgs.cs index 46351d12..b967e7eb 100644 --- a/LabApi/Events/Arguments/ServerEvents/ModifiedFactionInfluenceEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/ModifiedFactionInfluenceEventArgs.cs @@ -5,7 +5,7 @@ namespace LabApi.Events.Arguments.ServerEvents; /// <summary> -/// Represents the arguments for the <see cref="Handlers.ServerEvents.FactionInfluenceModified"/> event. +/// Represents the arguments for the <see cref="Handlers.ServerEvents.ModifiedFactionInfluence"/> event. /// </summary> public class ModifiedFactionInfluenceEventArgs : EventArgs { diff --git a/LabApi/Events/Arguments/ServerEvents/ModifyingFactionInfluenceEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/ModifyingFactionInfluenceEventArgs.cs index 55bdd025..66ea997a 100644 --- a/LabApi/Events/Arguments/ServerEvents/ModifyingFactionInfluenceEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/ModifyingFactionInfluenceEventArgs.cs @@ -6,7 +6,7 @@ namespace LabApi.Events.Arguments.ServerEvents; /// <summary> -/// Represents the arguments for the <see cref="Handlers.ServerEvents.FactionInfluenceModifying"/> event. +/// Represents the arguments for the <see cref="Handlers.ServerEvents.ModifyingFactionInfluence"/> event. /// </summary> public class ModifyingFactionInfluenceEventArgs : EventArgs, ICancellableEvent { From 56cfd0d10eb401487e3b8d321cd7aad97ddc38b4 Mon Sep 17 00:00:00 2001 From: SlejmUr <slejmur@protonmail.com> Date: Sun, 19 Oct 2025 23:07:50 +0000 Subject: [PATCH 186/215] Add Map events --- .../LogAll/LogPlugin/LogPlugin.csproj | 1 + .../LogAll/LogPlugin/MyCustomEventsHandler.cs | 55 +++++++++++++++++++ .../ServerEvents/BlastDoorChangedEventArgs.cs | 30 ++++++++++ .../BlastDoorChangingEventArgs.cs | 36 ++++++++++++ .../CheckpointDoorSequenceChangedEventArgs.cs | 32 +++++++++++ ...CheckpointDoorSequenceChangingEventArgs.cs | 45 +++++++++++++++ .../ServerEvents/DoorDamagedEventArgs.cs | 39 +++++++++++++ .../ServerEvents/DoorDamagingEventArgs.cs | 45 +++++++++++++++ .../ServerEvents/DoorLockChangedEventArgs.cs | 40 ++++++++++++++ .../ServerEvents/DoorRepairedEventArgs.cs | 32 +++++++++++ .../ServerEvents/DoorRepairingEventArgs.cs | 38 +++++++++++++ .../ServerEvents/RoomColorChangedEventArgs.cs | 33 +++++++++++ .../ServerEvents/RoomLightChangedEventArgs.cs | 32 +++++++++++ .../Handlers/ServerEvents.EventHandlers.cs | 55 +++++++++++++++++++ 14 files changed, 513 insertions(+) create mode 100644 LabApi/Events/Arguments/ServerEvents/BlastDoorChangedEventArgs.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/BlastDoorChangingEventArgs.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/CheckpointDoorSequenceChangedEventArgs.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/CheckpointDoorSequenceChangingEventArgs.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/DoorDamagedEventArgs.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/DoorDamagingEventArgs.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/DoorLockChangedEventArgs.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/DoorRepairedEventArgs.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/DoorRepairingEventArgs.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/RoomColorChangedEventArgs.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/RoomLightChangedEventArgs.cs diff --git a/LabApi.Examples/LogAll/LogPlugin/LogPlugin.csproj b/LabApi.Examples/LogAll/LogPlugin/LogPlugin.csproj index 2fd62420..d546ec6e 100644 --- a/LabApi.Examples/LogAll/LogPlugin/LogPlugin.csproj +++ b/LabApi.Examples/LogAll/LogPlugin/LogPlugin.csproj @@ -15,6 +15,7 @@ <ItemGroup> <Reference Include="Assembly-CSharp" HintPath="$(SL_REFERENCES)\Assembly-CSharp.dll" /> + <Reference Include="UnityEngine.CoreModule" HintPath="$(UNITY_REFERENCES)\UnityEngine.CoreModule.dll" /> </ItemGroup> <ItemGroup> diff --git a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs index 21df72f0..8c00e2d3 100644 --- a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs +++ b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs @@ -1726,6 +1726,61 @@ public override void OnServerModifyingFactionInfluence(ModifyingFactionInfluence Logger.Info($"{nameof(OnServerModifyingFactionInfluence)} triggered by {ev.Faction} {ev.Influence}"); } + public override void OnServerBlastDoorChanged(BlastDoorChangedEventArgs ev) + { + Logger.Info($"{nameof(OnServerBlastDoorChanged)} triggered by {ev.BlastDoor} {ev.NewState}"); + } + + public override void OnServerBlastDoorChanging(BlastDoorChangingEventArgs ev) + { + Logger.Info($"{nameof(OnServerBlastDoorChanging)} triggered by {ev.BlastDoor} {ev.NewState}"); + } + + public override void OnServerDoorDamaged(DoorDamagedEventArgs ev) + { + Logger.Info($"{nameof(OnServerDoorDamaged)} triggered by {ev.Door} {ev.Damage} {ev.DamageType}"); + } + + public override void OnServerDoorDamaging(DoorDamagingEventArgs ev) + { + Logger.Info($"{nameof(OnServerDoorDamaging)} triggered by {ev.Door} {ev.Damage} {ev.DamageType}"); + } + + public override void OnServerDoorLockChanged(DoorLockChangedEventArgs ev) + { + Logger.Info($"{nameof(OnServerDoorLockChanged)} triggered by {ev.Door} {ev.PrevLockReason} => {ev.LockReason}"); + } + + public override void OnServerDoorRepaired(DoorRepairedEventArgs ev) + { + Logger.Info($"{nameof(OnServerDoorRepaired)} triggered by {ev.Door} {ev.RemainingHealth}"); + } + + public override void OnServerDoorRepairing(DoorRepairingEventArgs ev) + { + Logger.Info($"{nameof(OnServerDoorRepairing)} triggered by {ev.Door} {ev.RemainingHealth}"); + } + + public override void OnServerCheckpointDoorSequenceChanged(CheckpointDoorSequenceChangedEventArgs ev) + { + Logger.Info($"{nameof(OnServerCheckpointDoorSequenceChanged)} triggered by {ev.CheckpointDoor} {ev.CurrentSequence}"); + } + + public override void OnServerCheckpointDoorSequenceChanging(CheckpointDoorSequenceChangingEventArgs ev) + { + Logger.Info($"{nameof(OnServerCheckpointDoorSequenceChanging)} triggered by {ev.CheckpointDoor} {ev.CurrentSequence} {ev.NewSequence}"); + } + + public override void OnServerRoomColorChanged(RoomColorChangedEventArgs ev) + { + Logger.Info($"{nameof(OnServerRoomColorChanged)} triggered by {ev.Room} {ev.NewState}"); + } + + public override void OnServerRoomLightChanged(RoomLightChangedEventArgs ev) + { + Logger.Info($"{nameof(OnServerRoomLightChanged)} triggered by {ev.Room} {ev.NewState}"); + } + #region Excluded Events // The following events spam the console and are therefore excluded from this example: diff --git a/LabApi/Events/Arguments/ServerEvents/BlastDoorChangedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/BlastDoorChangedEventArgs.cs new file mode 100644 index 00000000..9038df7d --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/BlastDoorChangedEventArgs.cs @@ -0,0 +1,30 @@ +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.BlastDoorChanged"/> event. +/// </summary> +public class BlastDoorChangedEventArgs : EventArgs +{ + /// <summary> + /// Initializes a new instance of the <see cref="BlastDoorChangedEventArgs"/> class. + /// </summary> + /// <param name="blastDoor">The door that is chaning it's state.</param> + /// <param name="newState">The <paramref name="blastDoor"/>'s new state.</param> + public BlastDoorChangedEventArgs(BlastDoor blastDoor, bool newState) + { + BlastDoor = blastDoor; + NewState = newState; + } + + /// <summary> + /// Gets the current Blast Door. + /// </summary> + public BlastDoor BlastDoor { get; } + + /// <summary> + /// Gets the <see cref="BlastDoor"/> new state. + /// </summary> + public bool NewState { get; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/BlastDoorChangingEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/BlastDoorChangingEventArgs.cs new file mode 100644 index 00000000..bd0e8f86 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/BlastDoorChangingEventArgs.cs @@ -0,0 +1,36 @@ +using LabApi.Events.Arguments.Interfaces; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.BlastDoorChanging"/> event. +/// </summary> +public class BlastDoorChangingEventArgs : EventArgs, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="BlastDoorChangingEventArgs"/> class. + /// </summary> + /// <param name="blastDoor">The door that is changing it's state.</param> + /// <param name="newState">The <paramref name="blastDoor"/>'s new state.</param> + public BlastDoorChangingEventArgs(BlastDoor blastDoor, bool newState) + { + BlastDoor = blastDoor; + NewState = newState; + + IsAllowed = true; + } + + /// <summary> + /// Gets the current Blast Door. + /// </summary> + public BlastDoor BlastDoor { get; } + + /// <summary> + /// Gets or sets the <see cref="BlastDoor"/> new state. + /// </summary> + public bool NewState { get; set; } + + /// <inheritdoc/> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/CheckpointDoorSequenceChangedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/CheckpointDoorSequenceChangedEventArgs.cs new file mode 100644 index 00000000..1d1261e0 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/CheckpointDoorSequenceChangedEventArgs.cs @@ -0,0 +1,32 @@ +using LabApi.Features.Wrappers; +using System; +using static Interactables.Interobjects.CheckpointDoor; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.CheckpointDoorSequenceChanged"/> event. +/// </summary> +public class CheckpointDoorSequenceChangedEventArgs : EventArgs +{ + /// <summary> + /// Initializes a new instance of the <see cref="DoorDamagingEventArgs"/> class. + /// </summary> + /// <param name="door">The current checkpoint door.</param> + /// <param name="sequenceState">The current state this checkpoint is.</param> + public CheckpointDoorSequenceChangedEventArgs(Interactables.Interobjects.CheckpointDoor door, SequenceState sequenceState) + { + CheckpointDoor = CheckpointDoor.Get(door); + CurrentSequence = sequenceState; + } + + /// <summary> + /// Gets the current Checkpoint Door. + /// </summary> + public CheckpointDoor CheckpointDoor { get; } + + /// <summary> + /// Gets the damage value. + /// </summary> + public SequenceState CurrentSequence { get; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/CheckpointDoorSequenceChangingEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/CheckpointDoorSequenceChangingEventArgs.cs new file mode 100644 index 00000000..2f436c79 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/CheckpointDoorSequenceChangingEventArgs.cs @@ -0,0 +1,45 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using static Interactables.Interobjects.CheckpointDoor; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.CheckpointDoorSequenceChanging"/> event. +/// </summary> +public class CheckpointDoorSequenceChangingEventArgs : EventArgs, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="CheckpointDoorSequenceChangingEventArgs"/> class. + /// </summary> + /// <param name="door">The current checkpoint door.</param> + /// <param name="oldState">The current state this checkpoint is.</param> + /// <param name="sequenceState">The new state this checkpoint changing.</param> + public CheckpointDoorSequenceChangingEventArgs(Interactables.Interobjects.CheckpointDoor door, SequenceState oldState, SequenceState sequenceState) + { + CheckpointDoor = CheckpointDoor.Get(door); + CurrentSequence = oldState; + NewSequence = sequenceState; + + IsAllowed = true; + } + + /// <summary> + /// Gets the current Checkpoint Door. + /// </summary> + public CheckpointDoor CheckpointDoor { get; } + + /// <summary> + /// Gets the current sequence state. + /// </summary> + public SequenceState CurrentSequence { get; } + + /// <summary> + /// Gets or sets the new sequence state. + /// </summary> + public SequenceState NewSequence { get; set; } + + /// <inheritdoc/> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/DoorDamagedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/DoorDamagedEventArgs.cs new file mode 100644 index 00000000..dc6ce212 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/DoorDamagedEventArgs.cs @@ -0,0 +1,39 @@ +using Interactables.Interobjects.DoorUtils; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.DoorDamaged"/> event. +/// </summary> +public class DoorDamagedEventArgs : EventArgs +{ + /// <summary> + /// Initializes a new instance of the <see cref="DoorDamagedEventArgs"/> class. + /// </summary> + /// <param name="door">The door that was damaged.</param> + /// <param name="hp">The damage to apply this door.</param> + /// <param name="type">The type of damage this door received.</param> + public DoorDamagedEventArgs(DoorVariant door, float hp, DoorDamageType type) + { + Door = Door.Get(door); + Damage = hp; + DamageType = type; + } + + /// <summary> + /// Gets the current Door. + /// </summary> + public Door Door { get; } + + /// <summary> + /// Gets the damage value. + /// </summary> + public float Damage { get; } + + /// <summary> + /// Gets the damage type. + /// </summary> + public DoorDamageType DamageType { get; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/DoorDamagingEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/DoorDamagingEventArgs.cs new file mode 100644 index 00000000..9114da41 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/DoorDamagingEventArgs.cs @@ -0,0 +1,45 @@ +using Interactables.Interobjects.DoorUtils; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.DoorDamaging"/> event. +/// </summary> +public class DoorDamagingEventArgs : EventArgs, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="DoorDamagingEventArgs"/> class. + /// </summary> + /// <param name="door">The door that is damaging.</param> + /// <param name="hp">The damage to apply this door.</param> + /// <param name="type">The type of damage this door received.</param> + public DoorDamagingEventArgs(DoorVariant door, float hp, DoorDamageType type) + { + Door = Door.Get(door); + Damage = hp; + DamageType = type; + + IsAllowed = true; + } + + /// <summary> + /// Gets the current Door. + /// </summary> + public Door Door { get; } + + /// <summary> + /// Gets or sets the damage value. + /// </summary> + public float Damage { get; set; } + + /// <summary> + /// Gets or sets the damage type. + /// </summary> + public DoorDamageType DamageType { get; set; } + + /// <inheritdoc/> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/DoorLockChangedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/DoorLockChangedEventArgs.cs new file mode 100644 index 00000000..a0f28ac4 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/DoorLockChangedEventArgs.cs @@ -0,0 +1,40 @@ +using Interactables.Interobjects.DoorUtils; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.DoorLockChanged"/> event. +/// </summary> +public class DoorLockChangedEventArgs : EventArgs +{ + /// <summary> + /// Initializes a new instance of the <see cref="DoorLockChangedEventArgs"/> class. + /// </summary> + /// <param name="door">The door whose lock reason changed.</param> + /// <param name="prevLockReason">The previous lock reason.</param> + /// <param name="activeLocks">The <paramref name="door"/>'s lock reason.</param> + public DoorLockChangedEventArgs(DoorVariant door, ushort prevLockReason, ushort activeLocks) + { + Door = Door.Get(door); + PrevLockReason = (DoorLockReason)prevLockReason; + LockReason = (DoorLockReason)activeLocks; + } + + /// <summary> + /// Gets the current Door. + /// </summary> + public Door Door { get; } + + /// <summary> + /// Gets the <see cref="Door"/> old lock reason. + /// </summary> + public DoorLockReason PrevLockReason { get; } + + /// <summary> + /// Gets the <see cref="Door"/> new lock reason. + /// </summary> + public DoorLockReason LockReason { get; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/DoorRepairedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/DoorRepairedEventArgs.cs new file mode 100644 index 00000000..27aa4d2c --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/DoorRepairedEventArgs.cs @@ -0,0 +1,32 @@ +using Interactables.Interobjects.DoorUtils; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.DoorRepaired"/> event. +/// </summary> +public class DoorRepairedEventArgs : EventArgs +{ + /// <summary> + /// Initializes a new instance of the <see cref="DoorRepairedEventArgs"/> class. + /// </summary> + /// <param name="door">The door that was repaired.</param> + /// <param name="remainingHealth">The remaining health for this door.</param> + public DoorRepairedEventArgs(DoorVariant door, float remainingHealth) + { + Door = Door.Get(door); + RemainingHealth = remainingHealth; + } + + /// <summary> + /// Gets the current Door. + /// </summary> + public Door Door { get; } + + /// <summary> + /// Gets the remaining health of the <see cref="Door"/>. + /// </summary> + public float RemainingHealth { get; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/DoorRepairingEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/DoorRepairingEventArgs.cs new file mode 100644 index 00000000..f9014b99 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/DoorRepairingEventArgs.cs @@ -0,0 +1,38 @@ +using Interactables.Interobjects.DoorUtils; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.DoorRepairing"/> event. +/// </summary> +public class DoorRepairingEventArgs : EventArgs, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="DoorRepairingEventArgs"/> class. + /// </summary> + /// <param name="door">The door that is repairing.</param> + /// <param name="remainingHealth">The remaining health for this door.</param> + public DoorRepairingEventArgs(DoorVariant door, float remainingHealth) + { + Door = Door.Get(door); + RemainingHealth = remainingHealth; + + IsAllowed = true; + } + + /// <summary> + /// Gets the current Door. + /// </summary> + public Door Door { get; } + + /// <summary> + /// Gets or sets the remaining health of the <see cref="Door"/>. + /// </summary> + public float RemainingHealth { get; set; } + + /// <inheritdoc/> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/RoomColorChangedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/RoomColorChangedEventArgs.cs new file mode 100644 index 00000000..2eac9d68 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/RoomColorChangedEventArgs.cs @@ -0,0 +1,33 @@ +using LabApi.Features.Wrappers; +using MapGeneration; +using System; +using UnityEngine; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.RoomColorChanged"/> event. +/// </summary> +public class RoomColorChangedEventArgs : EventArgs +{ + /// <summary> + /// Initializes a new instance of the <see cref="RoomColorChangedEventArgs"/> class. + /// </summary> + /// <param name="room">The room that is changing its color.</param> + /// <param name="newState">The <paramref name="room"/>'s new color.</param> + public RoomColorChangedEventArgs(RoomIdentifier room, Color newState) + { + Room = Room.Get(room); + NewState = newState; + } + + /// <summary> + /// Gets the current room. + /// </summary> + public Room Room { get; } + + /// <summary> + /// Gets the <see cref="Room"/> new color. + /// </summary> + public Color NewState { get; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/RoomLightChangedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/RoomLightChangedEventArgs.cs new file mode 100644 index 00000000..a8a6d4c4 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/RoomLightChangedEventArgs.cs @@ -0,0 +1,32 @@ +using LabApi.Features.Wrappers; +using MapGeneration; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.RoomLightChanged"/> event. +/// </summary> +public class RoomLightChangedEventArgs : EventArgs +{ + /// <summary> + /// Initializes a new instance of the <see cref="RoomLightChangedEventArgs"/> class. + /// </summary> + /// <param name="room">The room that is changing its light state.</param> + /// <param name="newState">The <paramref name="room"/>'s new light state.</param> + public RoomLightChangedEventArgs(RoomIdentifier room, bool newState) + { + Room = Room.Get(room); + NewState = newState; + } + + /// <summary> + /// Gets the current room. + /// </summary> + public Room Room { get; } + + /// <summary> + /// Gets the <see cref="Room"/> new light state. + /// </summary> + public bool NewState { get; } +} diff --git a/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs b/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs index 3c2181d5..22c977bc 100644 --- a/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs +++ b/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs @@ -246,4 +246,59 @@ public static partial class ServerEvents /// Gets called when a faction achieved a milestone. /// </summary> public static event LabEventHandler<AchievedMilestoneEventArgs>? AchievedMilestone; + + /// <summary> + /// Gets called when a blast door changes state. + /// </summary> + public static event LabEventHandler<BlastDoorChangingEventArgs>? BlastDoorChanging; + + /// <summary> + /// Gets called when a blast door is changed state. + /// </summary> + public static event LabEventHandler<BlastDoorChangedEventArgs>? BlastDoorChanged; + + /// <summary> + /// Gets called when a room's light is changed. + /// </summary> + public static event LabEventHandler<RoomLightChangedEventArgs>? RoomLightChanged; + + /// <summary> + /// Gets called when a room's color is changed. + /// </summary> + public static event LabEventHandler<RoomColorChangedEventArgs>? RoomColorChanged; + + /// <summary> + /// Gets called when a door's lock state is changed. + /// </summary> + public static event LabEventHandler<DoorLockChangedEventArgs>? DoorLockChanged; + + /// <summary> + /// Gets called when a door is repairing. + /// </summary> + public static event LabEventHandler<DoorRepairingEventArgs>? DoorRepairing; + + /// <summary> + /// Gets called when a door is repaired. + /// </summary> + public static event LabEventHandler<DoorRepairedEventArgs>? DoorRepaired; + + /// <summary> + /// Gets called when a door is damaging. + /// </summary> + public static event LabEventHandler<DoorDamagingEventArgs>? DoorDamaging; + + /// <summary> + /// Gets called when a door is damaged. + /// </summary> + public static event LabEventHandler<DoorDamagedEventArgs>? DoorDamaged; + + /// <summary> + /// Gets called when a checkpoint door sequence is changing. + /// </summary> + public static event LabEventHandler<CheckpointDoorSequenceChangingEventArgs>? CheckpointDoorSequenceChanging; + + /// <summary> + /// Gets called when a checkpoint door sequence is changed. + /// </summary> + public static event LabEventHandler<CheckpointDoorSequenceChangedEventArgs>? CheckpointDoorSequenceChanged; } \ No newline at end of file From 753368ee376059819aebba7c08e8ec92728b9c58 Mon Sep 17 00:00:00 2001 From: Evelyn <85962933+Misfiy@users.noreply.github.com> Date: Mon, 20 Oct 2025 01:13:58 +0200 Subject: [PATCH 187/215] Push changes (#282) --- LabApi/Features/Extensions/RoleExtensions.cs | 48 ++++++++++++++++++- .../Features/Wrappers/AdminToys/AdminToy.cs | 9 ++-- .../Features/Wrappers/AdminToys/CameraToy.cs | 9 ++-- .../Features/Wrappers/Items/JailbirdItem.cs | 13 ++++- 4 files changed, 66 insertions(+), 13 deletions(-) diff --git a/LabApi/Features/Extensions/RoleExtensions.cs b/LabApi/Features/Extensions/RoleExtensions.cs index 94dc7129..a3ec6e5f 100644 --- a/LabApi/Features/Extensions/RoleExtensions.cs +++ b/LabApi/Features/Extensions/RoleExtensions.cs @@ -1,4 +1,10 @@ -using PlayerRoles; +using System.Collections.Generic; +using PlayerRoles; +using System.Diagnostics.CodeAnalysis; +using InventorySystem; +using InventorySystem.Configs; +using PlayerRoles.FirstPersonControl; +using UnityEngine; namespace LabApi.Features.Extensions; @@ -7,6 +13,8 @@ namespace LabApi.Features.Extensions; /// </summary> public static class RoleExtensions { + private static readonly InventoryRoleInfo EmptyInventoryInfo = new([], []); // prevent creating this multiple time + /// <summary> /// Gets the <see cref="PlayerRoleBase"/> from a <see cref="RoleTypeId"/>. /// </summary> @@ -14,6 +22,15 @@ public static class RoleExtensions /// <returns>The <see cref="PlayerRoleBase"/>.</returns> public static PlayerRoleBase GetRoleBase(this RoleTypeId roleType) => PlayerRoleLoader.TryGetRoleTemplate(roleType, out PlayerRoleBase role) ? role : null!; + /// <summary> + /// Tries to get a role base from a <see cref="RoleTypeId"/>. + /// </summary> + /// <param name="roleTypeId">The <see cref="RoleTypeId"/> to get base of.</param> + /// <param name="role">The <see cref="PlayerRoleBase"/> found.</param> + /// <typeparam name="T">The <see cref="PlayerRoleBase"/>.</typeparam> + /// <returns>The role base found, else null.</returns> + public static bool TryGetRoleBase<T>(this RoleTypeId roleTypeId, [NotNullWhen(true)] out T? role) => PlayerRoleLoader.TryGetRoleTemplate(roleTypeId, out role); + /// <summary> /// Gets the human-readable version of a <see cref="RoleTypeId"/>'s name. /// </summary> @@ -21,6 +38,33 @@ public static class RoleExtensions /// <returns>The name of the role.</returns> public static string GetFullName(this RoleTypeId roleType) => roleType.GetRoleBase().RoleName; + /// <summary> + /// Tries to get a random spawn point from a <see cref="RoleTypeId"/>. + /// </summary> + /// <param name="role">The role to get spawn from.</param> + /// <param name="position">The position found.</param> + /// <param name="horizontalRotation">The rotation found.</param> + /// <returns>Whether a SpawnPoint was found.</returns> + public static bool TryGetRandomSpawnPoint(this RoleTypeId role, out Vector3 position, out float horizontalRotation) + { + if (TryGetRoleBase(role, out IFpcRole? fpcRole)) + { + return fpcRole.SpawnpointHandler.TryGetSpawnpoint(out position, out horizontalRotation); + } + + position = Vector3.zero; + horizontalRotation = 0f; + return false; + } + + /// <summary> + /// Gets the inventory of the specified <see cref="RoleTypeId"/>. + /// </summary> + /// <param name="roleTypeId">The <see cref="RoleTypeId"/> to get inventory of.</param> + /// <returns>The <see cref="InventoryRoleInfo"/> found.</returns> + public static InventoryRoleInfo GetInventory(this RoleTypeId roleTypeId) + => StartingInventories.DefinedInventories.GetValueOrDefault(roleTypeId, EmptyInventoryInfo); + /// <summary> /// Checks if the role is an SCP role. /// </summary> @@ -61,5 +105,5 @@ public static class RoleExtensions /// </summary> /// <param name="roleType">The <see cref="RoleTypeId"/>.</param> /// <returns>A boolean which is true when the role is a civilian role.</returns> - public static bool IsCivilian(this RoleTypeId roleType) => roleType == RoleTypeId.ClassD || roleType == RoleTypeId.Scientist; + public static bool IsCivilian(this RoleTypeId roleType) => roleType is RoleTypeId.ClassD or RoleTypeId.Scientist; } \ No newline at end of file diff --git a/LabApi/Features/Wrappers/AdminToys/AdminToy.cs b/LabApi/Features/Wrappers/AdminToys/AdminToy.cs index 831d4629..7e2c8e77 100644 --- a/LabApi/Features/Wrappers/AdminToys/AdminToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/AdminToy.cs @@ -134,7 +134,7 @@ protected static AdminToy CreateAdminToyWrapper(AdminToyBase adminToyBase) return new AdminToy(adminToyBase); } - return wrapper ?? new AdminToy(adminToyBase); + return wrapper; } /// <summary> @@ -164,9 +164,8 @@ private static void RemoveAdminToy(AdminToyBase adminToyBase) { try { - if (Dictionary.TryGetValue(adminToyBase, out AdminToy adminToy)) + if (Dictionary.Remove(adminToyBase, out AdminToy adminToy)) { - Dictionary.Remove(adminToyBase); adminToy.OnRemove(); } } @@ -299,7 +298,7 @@ public byte MovementSmoothing /// <summary> /// Gets or sets whether the admin toy is static. /// This should be enabled on as many toys possible to increase performance. - /// Static is only applies to the local transformations so parenting to something that moves will still causes it to move while retaining the performance boost. + /// Static is only applies to the local transformations so parenting to something that moves will still cause it to move while retaining the performance boost. /// </summary> /// <remarks> /// A static admin toy will not process <see cref="Position"/>, <see cref="Rotation"/> or <see cref="Scale"/> on both server and client drastically increasing performance. @@ -331,7 +330,7 @@ public float SyncInterval /// Spawns the toy on the client. /// </summary> /// <remarks> - /// Spawn wont cascade to children toy objects, so if they are not spawned you have to call spawn on all of them. + /// Spawn won't cascade to children toy objects, so if they are not spawned you have to call spawn on all of them. /// </remarks> public void Spawn() => NetworkServer.Spawn(GameObject); diff --git a/LabApi/Features/Wrappers/AdminToys/CameraToy.cs b/LabApi/Features/Wrappers/AdminToys/CameraToy.cs index 129a29ea..66050724 100644 --- a/LabApi/Features/Wrappers/AdminToys/CameraToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/CameraToy.cs @@ -101,11 +101,10 @@ internal CameraToy(Scp079CameraToy baseCameraToy) /// </summary> public new Scp079CameraToy Base { get; } - // Todo: reimplement when publicized - // /// <summary> - // /// The camera instance associated with this toy. - // /// </summary> - // public Camera Camera => Camera.Get(Base.Camera); + /// <summary> + /// The camera instance associated with this toy. + /// </summary> + public Camera Camera => Camera.Get(Base.Camera); /// <summary> /// Gets or sets the label of the camera displayed to SCP-079 on HUD. diff --git a/LabApi/Features/Wrappers/Items/JailbirdItem.cs b/LabApi/Features/Wrappers/Items/JailbirdItem.cs index a021dd94..f5248e2f 100644 --- a/LabApi/Features/Wrappers/Items/JailbirdItem.cs +++ b/LabApi/Features/Wrappers/Items/JailbirdItem.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using InventorySystem.Items.Jailbird; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using BaseJailbirdItem = InventorySystem.Items.Jailbird.JailbirdItem; @@ -55,6 +56,11 @@ internal JailbirdItem(BaseJailbirdItem baseJailbirdItem) /// </summary> public new BaseJailbirdItem Base { get; } + /// <summary> + /// Gets the current <see cref="JailbirdWearState"/>. + /// </summary> + public JailbirdWearState WearState => JailbirdDeteriorationTracker.ReceivedStates.GetValueOrDefault(Serial, JailbirdWearState.Healthy); + /// <summary> /// Gets the number of charges performed. /// </summary> @@ -65,6 +71,11 @@ internal JailbirdItem(BaseJailbirdItem baseJailbirdItem) /// </summary> public bool IsCharging => Base.MovementOverrideActive; + /// <summary> + /// Resets charges and damage dealt. + /// </summary> + public void Reset() => Base.ServerReset(); + /// <summary> /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> From 6c704cf9a5b4513ecc44e383ad9460553df82854 Mon Sep 17 00:00:00 2001 From: Axwabo <axwabo@gmail.com> Date: Tue, 21 Oct 2025 09:33:15 +0200 Subject: [PATCH 188/215] removed line breaks from the description of UnsupportedLoading in Properties --- LabApi/Loader/Features/Plugins/Configuration/Properties.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/LabApi/Loader/Features/Plugins/Configuration/Properties.cs b/LabApi/Loader/Features/Plugins/Configuration/Properties.cs index 938e5956..0e13acf9 100644 --- a/LabApi/Loader/Features/Plugins/Configuration/Properties.cs +++ b/LabApi/Loader/Features/Plugins/Configuration/Properties.cs @@ -23,11 +23,6 @@ public class Properties /// <summary> /// Whether to allow loading the plugin even if it was built for a different major version of LabAPI. /// </summary> - [Description(""" - Whether to allow loading the plugin even if it was built for a different major version of LabAPI. - Default = use port-specific config - True/Enabled = load if unsupported - False/Disabled = do not load if unsupported - """)] + [Description("""Whether to allow loading the plugin even if it was built for a different major version of LabAPI. "Default" = use port-specific config; "True"/"Enabled" = load if unsupported; "False"/"Disabled" = do not load if unsupported""")] public OptionalBoolean UnsupportedLoading { get; set; } = OptionalBoolean.Default; } From 96893d4ce0563c816f8aee11a7118a0d9c188331 Mon Sep 17 00:00:00 2001 From: jesusqc <contact@jesusqc.es> Date: Tue, 21 Oct 2025 10:30:00 +0200 Subject: [PATCH 189/215] Version null check --- LabApi/Loader/PluginLoader.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/LabApi/Loader/PluginLoader.cs b/LabApi/Loader/PluginLoader.cs index 545cfd64..e92bf193 100644 --- a/LabApi/Loader/PluginLoader.cs +++ b/LabApi/Loader/PluginLoader.cs @@ -370,6 +370,13 @@ private static void LogMissingDependencies(Assembly assembly) private static bool ValidateVersion(Plugin plugin) { Version required = plugin.RequiredApiVersion; + + // TODO: Delete (why.....) + if (required == null) + { + return true; + } + Version current = LabApiProperties.CurrentVersion; if (required.Major == current.Major) From cdfb52feb26a26ffebead611ee019dfbca5cf0c8 Mon Sep 17 00:00:00 2001 From: Axwabo <axwabo@gmail.com> Date: Wed, 22 Oct 2025 15:01:30 +0200 Subject: [PATCH 190/215] Fix build & revision comparing --- LabApi/Loader/PluginLoader.cs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/LabApi/Loader/PluginLoader.cs b/LabApi/Loader/PluginLoader.cs index e92bf193..0e86b10f 100644 --- a/LabApi/Loader/PluginLoader.cs +++ b/LabApi/Loader/PluginLoader.cs @@ -381,7 +381,7 @@ private static bool ValidateVersion(Plugin plugin) if (required.Major == current.Major) { - if (required <= current) + if (!IsGreaterVersion(required, current)) { return true; } @@ -452,4 +452,19 @@ private static void InstantiatePlugins(Type[] types, Assembly assembly, string f Logger.Info($"{LoggerPrefix} Successfully loaded {plugin.Name}"); } } + + private static bool IsGreaterVersion(Version required, Version current) + { + Version requiredVersion = new( + required.Major, + required.Minor, + required.Build == -1 ? 0 : required.Build, + required.Revision == -1 ? 0 : required.Revision); + Version currentVersion = new( + current.Major, + current.Minor, + current.Build == -1 ? 0 : current.Build, + current.Revision == -1 ? 0 : current.Revision); + return requiredVersion > currentVersion; + } } From e2008900c933aa9d6551e56708bb185f52cc73b7 Mon Sep 17 00:00:00 2001 From: Jesus QC <69375249+Jesus-QC@users.noreply.github.com> Date: Fri, 24 Oct 2025 21:12:45 +0200 Subject: [PATCH 191/215] 1.1.4 (#307) * Reference fix * Added EmotionPresetType wrapper * Replaced MaxSergeants and MaxCaptains with SergeantsPercentage and CaptainsPercentage * gitlab templates * README changes * feat: new events * docs: better spacing and langwording * fix: event args naming scheme * docs: fix inconsistencies * Scp173 Snap Events * Apply 1 suggestion(s) to 1 file(s) Co-authored-by: The Riptide <theriptideservers@gmail.com> * Add CheckedHitmarker event Add Send/ing Hitmarker event Add log for new events. * Fix docs. SendHitmarker to SentHitmarker * Add Scp049 Attacked / ing Add Scp049 Sense Lost/ Killed Target * Apply 4 suggestion(s) to 2 file(s) Co-authored-by: Lumi <me@jxtq.moe> * Apply 10 suggestion(s) to 5 file(s) Co-authored-by: Axwabo <axwabo@gmail.com> * fix IsAllowed not set in Attacking Added log of the new events * Apply suggestions * Rename PlayAudio to PlayedAudio Revert LogPlugin handlers tolog everything too * Add Wave event * Apply 5 suggestion(s) to 2 file(s) Co-authored-by: Jesus-QC <99-jesusqc@users.noreply.git.scpslgame.com> * Fix nullable target * basic required version check * allow force-loading unsupported versions + improve messages * Add Focuesd Add Mimiced/ing Enviroment * version bump just in case * Fix methods * per-port global LoadUnsupportedPlugins property * rename ForceUnsupportedMajorVersion * OutdatedLoadingBehavior * Adding support for multiple command handlers. * make OutdatedLoadingBehavior more generic & reorder its values * Apply 13 suggestion(s) to 4 file(s) Co-authored-by: Jesus-QC <99-jesusqc@users.noreply.git.scpslgame.com> * Rename Mimicing -> Mimicking Rename Enviroment -> Environment * Fix event name in xml ReAdd events * Add Map events * Push changes (#282) * removed line breaks from the description of UnsupportedLoading in Properties * Version null check * Fix build & revision comparing --------- Co-authored-by: davidsebesta1 <david.sebesta@post.cz> Co-authored-by: Jesus-QC <99-jesusqc@users.noreply.git.scpslgame.com> Co-authored-by: Lumi <me@jxtq.moe> Co-authored-by: The Riptide <theriptideservers@gmail.com> Co-authored-by: SlejmUr <slejmur@protonmail.com> Co-authored-by: Axwabo <axwabo@gmail.com> Co-authored-by: Evelyn <85962933+Misfiy@users.noreply.github.com> --- .github/README.md | 45 +++++++ .gitlab/issue_templates/New Bug.md | 34 +++++ .gitlab/issue_templates/New Idea.md | 18 +++ .gitlab/issue_templates/New Task - Docless.md | 17 +++ .gitlab/issue_templates/New Task.md | 27 ++++ .../MR Template - Docless.md | 20 +++ .../merge_request_templates/MR Template.md | 22 +++ .../LogAll/LogPlugin/LogPlugin.csproj | 1 + .../LogAll/LogPlugin/MyCustomEventsHandler.cs | 126 ++++++++++++++++++ .../PlayerCheckedHitmarkerEventArgs.cs | 47 +++++++ .../PlayerSendingHitmarkerEventArgs.cs | 44 ++++++ .../PlayerSentHitmarkerEventArgs.cs | 39 ++++++ .../Scp049Events/Scp049AttackedEventArgs.cs | 46 +++++++ .../Scp049Events/Scp049AttackingEventArgs.cs | 58 ++++++++ .../Scp049SenseKilledTargetEventArgs.cs | 32 +++++ .../Scp049SenseLostTargetEventArgs.cs | 32 +++++ .../Scp173Events/Scp173SnappedEventArgs.cs | 32 +++++ .../Scp173Events/Scp173SnappingEventArgs.cs | 38 ++++++ .../Scp939Events/Scp939FocusedEventArgs.cs | 32 +++++ .../Scp939MimickedEnvironmentEventArgs.cs | 32 +++++ .../Scp939MimickingEnvironmentEventArgs.cs | 44 ++++++ .../ScpEvents/ScpHumeShieldBrokenEventArgs.cs | 23 ++++ .../AchievedMilestoneEventArgs.cs | 38 ++++++ .../AchievingMilestoneEventArgs.cs | 44 ++++++ .../ServerEvents/BlastDoorChangedEventArgs.cs | 30 +++++ .../BlastDoorChangingEventArgs.cs | 36 +++++ .../CheckpointDoorSequenceChangedEventArgs.cs | 32 +++++ ...CheckpointDoorSequenceChangingEventArgs.cs | 45 +++++++ .../DeadmanSequenceActivatingEventArgs.cs | 14 ++ .../ServerEvents/DoorDamagedEventArgs.cs | 39 ++++++ .../ServerEvents/DoorDamagingEventArgs.cs | 45 +++++++ .../ServerEvents/DoorLockChangedEventArgs.cs | 40 ++++++ .../ServerEvents/DoorRepairedEventArgs.cs | 32 +++++ .../ServerEvents/DoorRepairingEventArgs.cs | 38 ++++++ .../ModifiedFactionInfluenceEventArgs.cs | 32 +++++ .../ModifyingFactionInfluenceEventArgs.cs | 38 ++++++ .../ServerEvents/RoomColorChangedEventArgs.cs | 33 +++++ .../ServerEvents/RoomLightChangedEventArgs.cs | 32 +++++ .../Handlers/PlayerEvents.EventHandlers.cs | 15 +++ .../Handlers/Scp049Events.EventHandlers.cs | 20 +++ .../Handlers/Scp173Events.EventHandlers.cs | 10 ++ .../Handlers/Scp939Events.EventHandlers.cs | 15 +++ .../Handlers/ScpEvents.EventHandlers.cs | 14 ++ .../Handlers/ServerEvents.EventHandlers.cs | 90 +++++++++++++ LabApi/Features/Extensions/RoleExtensions.cs | 48 ++++++- .../Features/Wrappers/AdminToys/AdminToy.cs | 9 +- .../Features/Wrappers/AdminToys/CameraToy.cs | 9 +- .../Facility/Respawning/Waves/MtfWave.cs | 32 ++++- .../Facility/Respawning/Waves/RespawnWave.cs | 19 ++- LabApi/Features/Wrappers/Facility/Warhead.cs | 3 +- .../Features/Wrappers/Items/JailbirdItem.cs | 13 +- .../Features/Wrappers/Items/MicroHIDItem.cs | 2 +- .../Wrappers/Items/Usable/UsableItem.cs | 2 +- LabApi/Features/Wrappers/Players/Player.cs | 10 ++ LabApi/Features/Wrappers/Server/Server.cs | 2 +- LabApi/LabApi.csproj | 2 +- LabApi/Loader/CommandLoader.cs | 62 ++++++--- .../Features/Configuration/LabApiConfig.cs | 9 +- .../Plugins/Configuration/Properties.cs | 9 +- .../Features/Plugins/Enums/OptionalBoolean.cs | 28 ++++ LabApi/Loader/PluginLoader.cs | 88 +++++++++++- LabApi/README.md | 1 + README.md | 34 ++++- 63 files changed, 1870 insertions(+), 53 deletions(-) create mode 100644 .github/README.md create mode 100644 .gitlab/issue_templates/New Bug.md create mode 100644 .gitlab/issue_templates/New Idea.md create mode 100644 .gitlab/issue_templates/New Task - Docless.md create mode 100644 .gitlab/issue_templates/New Task.md create mode 100644 .gitlab/merge_request_templates/MR Template - Docless.md create mode 100644 .gitlab/merge_request_templates/MR Template.md create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerCheckedHitmarkerEventArgs.cs create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerSendingHitmarkerEventArgs.cs create mode 100644 LabApi/Events/Arguments/PlayerEvents/PlayerSentHitmarkerEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp049Events/Scp049AttackedEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp049Events/Scp049AttackingEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp049Events/Scp049SenseKilledTargetEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp049Events/Scp049SenseLostTargetEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp173Events/Scp173SnappedEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp173Events/Scp173SnappingEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp939Events/Scp939FocusedEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp939Events/Scp939MimickedEnvironmentEventArgs.cs create mode 100644 LabApi/Events/Arguments/Scp939Events/Scp939MimickingEnvironmentEventArgs.cs create mode 100644 LabApi/Events/Arguments/ScpEvents/ScpHumeShieldBrokenEventArgs.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/AchievedMilestoneEventArgs.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/AchievingMilestoneEventArgs.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/BlastDoorChangedEventArgs.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/BlastDoorChangingEventArgs.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/CheckpointDoorSequenceChangedEventArgs.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/CheckpointDoorSequenceChangingEventArgs.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/DeadmanSequenceActivatingEventArgs.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/DoorDamagedEventArgs.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/DoorDamagingEventArgs.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/DoorLockChangedEventArgs.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/DoorRepairedEventArgs.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/DoorRepairingEventArgs.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/ModifiedFactionInfluenceEventArgs.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/ModifyingFactionInfluenceEventArgs.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/RoomColorChangedEventArgs.cs create mode 100644 LabApi/Events/Arguments/ServerEvents/RoomLightChangedEventArgs.cs create mode 100644 LabApi/Events/Handlers/ScpEvents.EventHandlers.cs create mode 100644 LabApi/Loader/Features/Plugins/Enums/OptionalBoolean.cs create mode 120000 LabApi/README.md diff --git a/.github/README.md b/.github/README.md new file mode 100644 index 00000000..8aaaa1b0 --- /dev/null +++ b/.github/README.md @@ -0,0 +1,45 @@ +<p align="center"> + <a href="https://scpslgame.com"> + <picture> + <source srcset="https://github.com/user-attachments/assets/04f437c8-7fa9-4da9-bf71-fa39db141cf2" media="(prefers-color-scheme: dark)"> + <img src="https://github.com/user-attachments/assets/aa811a11-2b8e-4397-972d-27c7305318d7" width="125" alt="NW logo"> + </picture> + </a> +</p> + +<h1 align="center">LabAPI</h1> +<h6 align="center"><a href="https://store.steampowered.com/app/700330/SCP_Secret_Laboratory/">SCP: Secret Laboratory</a>'s official server-side modding framework.</h6> +<div align="center"> + <a href="https://plugins.scpslgame.com">Plugins</a> + <span> - </span> + <a href="https://github.com/northwood-studios/LabAPI/wiki">Docs</a> + <span> - </span> + <a href="https://github.com/northwood-studios/LabAPI/issues">Report Bug</a> + <span> - </span> + <a href="https://discord.gg/scpsl">Discord</a> + <p></p> +</div> + +<div align="center"> + +[![Version](https://img.shields.io/github/v/release/northwood-studios/LabAPI?sort=semver&style=flat-square&color=8DBBE9&label=Version)]() +[![License](https://img.shields.io/github/license/northwood-studios/LabAPI?style=flat-square&label=License&color=df967f)]() +[![Contributors](https://img.shields.io/github/contributors-anon/northwood-studios/LabAPI?color=90E59A&style=flat-square&label=Contributors)]() +[![GitHub Issues](https://img.shields.io/github/issues/northwood-studios/LabAPI.svg?style=flat-square&label=Issues&color=d77982)](https://github.com/northwood-studios/LabAPI/issues) +[![Discord](https://img.shields.io/discord/330432627649544202?color=738adb&label=Discord&logo=discord&logoColor=white&style=flat-square)](https://discord.gg/scpsl) + +</div> + +The LabAPI project is **[SCP: Secret Laboratory](https://store.steampowered.com/app/700330/SCP_Secret_Laboratory/)**'s official server-side plugin loader and framework. It facilitates development of plugins by providing wrappers and events around various game mechanics found throughout the game. + +## Documentation +Code should have self-explanatory documentation, but there's only so much you can explain through comments! +- For guides, tips and tricks, our main source of documentation can be found [here](https://github.com/northwood-studios/LabAPI/wiki). +- For a more practical approach, examples can be found [here](https://github.com/northwood-studios/LabAPI/tree/master/LabApi.Examples). + +## Installation +All **SCP: SL Dedicated Server** builds are bundled with a compiled **`LabAPI.dll`**, so you don't need to install it if you are hosting a server. + +However, [releases](https://github.com/northwood-studios/LabAPI/releases) may occasionally occur *before* the dedicated server is updated, while we advice you wait for an official update, you can always apply the updated release manually. + +To do so, you should update the **`LabAPI.dll`** file located within: `%DEDICATED_SERVER_PATH%/SCPSL_Data/Managed/`. \ No newline at end of file diff --git a/.gitlab/issue_templates/New Bug.md b/.gitlab/issue_templates/New Bug.md new file mode 100644 index 00000000..a1b4ffcd --- /dev/null +++ b/.gitlab/issue_templates/New Bug.md @@ -0,0 +1,34 @@ +> **New Issue Guidelines:** (For you! The writer :writing_hand: ) +> - Make sure to only choose one priority level, the bottom of this template has all labels you'll need. Delete the ones you don't need! +> - Mention the affected system in this issue's title. Something like `[RA] Using X throws an exception` or `[Intercom] Talking blows your computer up`. +> - In some cases, remember to verify with the team in charge of this kind of feature. (Examples: Art, Programming, Game Design) + +> **Choose one task priority level:** *(You can delete this line as well)* +/label ~"P1 - Critical" +/label ~"P2 - Priority Issue" +/label ~"P3 - Regular Priority" +/label ~"P4 - Low Priority" + +## Description +> A description about what the issue / bug is. How it affects players. And finally, how it's supposed to function. + +## Replication Steps & Requirements + +### Requirements: +- Have 2 or more players online, they'll be called Hubert & You. (Example) +- Before entering the game, change your Graphic Settings to **Low**. (Example) + +### Replication Steps: +- You must join the server first, without Hubert in it. +- Hubert must then join after you. +- When Hubert spawns, he will appear as a giant pink-textured role. + +## Attachments +> Any sort of video, image, client/server logs, just proof of the reported issue. For example: +- Related issues: #244 #123 #21 #50 +- Replication video: https://www.youtube.com/watch?v=2Q_ZzBGPdqE + +/label ~bug +/label ~todo + +/cc @jesusqc \ No newline at end of file diff --git a/.gitlab/issue_templates/New Idea.md b/.gitlab/issue_templates/New Idea.md new file mode 100644 index 00000000..dc6854b1 --- /dev/null +++ b/.gitlab/issue_templates/New Idea.md @@ -0,0 +1,18 @@ +> **New Issue Guidelines:** (For you! The writer :writing_hand: ) +> - Mention the affected system in this issue's title. Something like `[RA] Custom Menus Idea` or `[Map] New Map Generation Algorithm Ideas`. + +## Description +> A description of what you would like to see implemented, and perhaps how. Can be as vague and informal as you want. However, being descriptive is always appreciated. 😉 + +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + +## Notes +> These should serve as a guide of different ideas or concerns you may have regarding task, providing some insight of your vision to the programmer that may work on it. +- Example1. +- Example2. + +# Status +- [ ] **Approved for implementation by LabAPI's Management.** + +/label ~experimental +/confidential \ No newline at end of file diff --git a/.gitlab/issue_templates/New Task - Docless.md b/.gitlab/issue_templates/New Task - Docless.md new file mode 100644 index 00000000..55f021e0 --- /dev/null +++ b/.gitlab/issue_templates/New Task - Docless.md @@ -0,0 +1,17 @@ +/label ~"P1 - Critical" +/label ~"P2 - Priority Issue" +/label ~"P3 - Regular Priority" +/label ~"P4 - Low Priority" + +## Description + + +## Task Expectations/Check-list +- [ ] + +## Assets +- Design Document: + +/label ~"Task / Bounty" +/label ~todo +/confidential \ No newline at end of file diff --git a/.gitlab/issue_templates/New Task.md b/.gitlab/issue_templates/New Task.md new file mode 100644 index 00000000..18ac27d6 --- /dev/null +++ b/.gitlab/issue_templates/New Task.md @@ -0,0 +1,27 @@ +> **New Issue Guidelines:** (For you! The writer :writing_hand: ) +> - Make sure to only choose one priority level, the bottom of this template has all labels you'll need. Delete the ones you don't need! +> - Mention the affected system in this issue's title. Something like `[RA] Using X throws an exception` or `[Intercom] Talking blows your computer up`. + +> **Choose one task priority level:** *(You can delete this line as well)* +/label ~"P1 - Critical" +/label ~"P2 - Priority Issue" +/label ~"P3 - Regular Priority" +/label ~"P4 - Low Priority" + +## Description +> A description about what the task is and possibly an idea of how to implement if possible. + +## Task Expectations/Check-list +> **As always,** read the design document before starting work on it (if one was attached), the check-list below is merely done to help assignees follow some steps and not get lost. :smile: +- [ ] Text. +- [ ] Text2. +- [ ] Text3. + +## Assets +> Any assets that the assignee will need to complete this task / implement this feature. Make sure to include the **Design Document** here. +- Asset1. +- Asset2. + +/label ~"Task / Bounty" +/label ~todo +/confidential \ No newline at end of file diff --git a/.gitlab/merge_request_templates/MR Template - Docless.md b/.gitlab/merge_request_templates/MR Template - Docless.md new file mode 100644 index 00000000..3de19d68 --- /dev/null +++ b/.gitlab/merge_request_templates/MR Template - Docless.md @@ -0,0 +1,20 @@ +## Changes + +### Changelog +```yml +- +``` + +## Relevant Issues / Tasks + +Resolves #X + +## Notes (Optional) + + + +# **Status** +- [ ] **Approved by QA.** + +/ready +/done \ No newline at end of file diff --git a/.gitlab/merge_request_templates/MR Template.md b/.gitlab/merge_request_templates/MR Template.md new file mode 100644 index 00000000..a75c866a --- /dev/null +++ b/.gitlab/merge_request_templates/MR Template.md @@ -0,0 +1,22 @@ +## Changes + +### Changelog +> These should stay technical, you don't have to mention exactly what you did step-by-step, but providing something for other programmers to check on later is preferred. Studio Staff in charge of public announcements will use this changelog to create a simplified version of it. +```yml +- Text +``` + +## Relevant Issues / Tasks (Optional) + +> Replace the `X` with the issue ID you wish to automatically close when this is merged. +Resolves #X + +## Notes (Optional) + +> Write down any additional related notes programmers or the current lead programmer should be aware of regarding this merge request. + +# **Status** +- [ ] **Approved by QA.** + +/ready +/done \ No newline at end of file diff --git a/LabApi.Examples/LogAll/LogPlugin/LogPlugin.csproj b/LabApi.Examples/LogAll/LogPlugin/LogPlugin.csproj index 2fd62420..d546ec6e 100644 --- a/LabApi.Examples/LogAll/LogPlugin/LogPlugin.csproj +++ b/LabApi.Examples/LogAll/LogPlugin/LogPlugin.csproj @@ -15,6 +15,7 @@ <ItemGroup> <Reference Include="Assembly-CSharp" HintPath="$(SL_REFERENCES)\Assembly-CSharp.dll" /> + <Reference Include="UnityEngine.CoreModule" HintPath="$(UNITY_REFERENCES)\UnityEngine.CoreModule.dll" /> </ItemGroup> <ItemGroup> diff --git a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs index 8cc52f5b..8c00e2d3 100644 --- a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs +++ b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs @@ -11,6 +11,7 @@ using LabApi.Events.Arguments.Scp3114Events; using LabApi.Events.Arguments.Scp914Events; using LabApi.Events.Arguments.Scp939Events; +using LabApi.Events.Arguments.ScpEvents; using LabApi.Events.Arguments.ServerEvents; using LabApi.Events.Arguments.WarheadEvents; using LabApi.Events.CustomHandlers; @@ -815,6 +816,26 @@ public override void OnPlayerLeftHazard(PlayerLeftHazardEventArgs ev) Logger.Info($"{nameof(OnPlayerLeftHazard)} triggered by {ev.Player.UserId}"); } + public override void OnScp049Attacking(Scp049AttackingEventArgs ev) + { + Logger.Info($"{nameof(OnScp049Attacking)} triggered by {ev.Player} {ev.Target} {ev.InstantKill} {ev.IsSenseTarget} {ev.CooldownTime}"); + } + + public override void OnScp049Attacked(Scp049AttackedEventArgs ev) + { + Logger.Info($"{nameof(OnScp049Attacked)} triggered by {ev.Player} {ev.Target} {ev.InstantKill} {ev.IsSenseTarget}"); + } + + public override void OnScp049SenseKilledTarget(Scp049SenseKilledTargetEventArgs ev) + { + Logger.Info($"{nameof(OnScp049SenseKilledTarget)} triggered by {ev.Player} {ev.Target}"); + } + + public override void OnScp049SenseLostTarget(Scp049SenseLostTargetEventArgs ev) + { + Logger.Info($"{nameof(OnScp049SenseLostTarget)} triggered by {ev.Player} {ev.Target}"); + } + public override void OnScp049StartingResurrection(Scp049StartingResurrectionEventArgs ev) { Logger.Info($"{nameof(OnScp049StartingResurrection)} triggered by {ev.Player.UserId}"); @@ -1150,6 +1171,16 @@ public override void OnScp173PlayedSound(Scp173PlayedSoundEventArgs ev) Logger.Info($"{nameof(OnScp173PlayedSound)} triggered by {ev.Player.UserId}"); } + public override void OnScp173Snapped(Scp173SnappedEventArgs ev) + { + Logger.Info($"{nameof(OnScp173Snapped)} triggered by {ev.Player.UserId} targeting {ev.Target.UserId}"); + } + + public override void OnScp173Snapping(Scp173SnappingEventArgs ev) + { + Logger.Info($"{nameof(OnScp173Snapping)} triggered by {ev.Player.UserId} targeting {ev.Target.UserId}"); + } + public override void OnScp3114StrangleAborting(Scp3114StrangleAbortingEventArgs ev) { Logger.Info($"{nameof(OnScp3114StrangleAborting)} triggered by {ev.Player.UserId}"); @@ -1654,6 +1685,101 @@ public override void OnScp127Talked(Scp127TalkedEventArgs ev) { Logger.Info($"{nameof(OnScp127Talked)} triggered by {ev.Scp127Item.CurrentOwner}"); } + + public override void OnPlayerCheckedHitmarker(PlayerCheckedHitmarkerEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerCheckedHitmarker)} triggered by {ev.Player} {ev.Victim} {ev.Result}"); + } + + public override void OnPlayerSentHitmarker(PlayerSentHitmarkerEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerSentHitmarker)} triggered by {ev.Player} {ev.Size} {ev.PlayedAudio}"); + } + + public override void OnPlayerSendingHitmarker(PlayerSendingHitmarkerEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerSendingHitmarker)} triggered by {ev.Player} {ev.Size} {ev.PlayAudio}"); + } + + public override void OnScpHumeShieldBroken(ScpHumeShieldBrokenEventArgs ev) + { + Logger.Info($"{nameof(OnScpHumeShieldBroken)} triggered by {ev.Player}"); + } + + public override void OnServerAchievedMilestone(AchievedMilestoneEventArgs ev) + { + Logger.Info($"{nameof(OnServerAchievedMilestone)} triggered by {ev.Faction} {ev.Threshold} {ev.MilestoneIndex}"); + } + + public override void OnServerAchievingMilestone(AchievingMilestoneEventArgs ev) + { + Logger.Info($"{nameof(OnServerAchievingMilestone)} triggered by {ev.Faction} {ev.Threshold} {ev.MilestoneIndex}"); + } + + public override void OnServerModifiedFactionInfluence(ModifiedFactionInfluenceEventArgs ev) + { + Logger.Info($"{nameof(OnServerModifiedFactionInfluence)} triggered by {ev.Faction} {ev.Influence}"); + } + + public override void OnServerModifyingFactionInfluence(ModifyingFactionInfluenceEventArgs ev) + { + Logger.Info($"{nameof(OnServerModifyingFactionInfluence)} triggered by {ev.Faction} {ev.Influence}"); + } + + public override void OnServerBlastDoorChanged(BlastDoorChangedEventArgs ev) + { + Logger.Info($"{nameof(OnServerBlastDoorChanged)} triggered by {ev.BlastDoor} {ev.NewState}"); + } + + public override void OnServerBlastDoorChanging(BlastDoorChangingEventArgs ev) + { + Logger.Info($"{nameof(OnServerBlastDoorChanging)} triggered by {ev.BlastDoor} {ev.NewState}"); + } + + public override void OnServerDoorDamaged(DoorDamagedEventArgs ev) + { + Logger.Info($"{nameof(OnServerDoorDamaged)} triggered by {ev.Door} {ev.Damage} {ev.DamageType}"); + } + + public override void OnServerDoorDamaging(DoorDamagingEventArgs ev) + { + Logger.Info($"{nameof(OnServerDoorDamaging)} triggered by {ev.Door} {ev.Damage} {ev.DamageType}"); + } + + public override void OnServerDoorLockChanged(DoorLockChangedEventArgs ev) + { + Logger.Info($"{nameof(OnServerDoorLockChanged)} triggered by {ev.Door} {ev.PrevLockReason} => {ev.LockReason}"); + } + + public override void OnServerDoorRepaired(DoorRepairedEventArgs ev) + { + Logger.Info($"{nameof(OnServerDoorRepaired)} triggered by {ev.Door} {ev.RemainingHealth}"); + } + + public override void OnServerDoorRepairing(DoorRepairingEventArgs ev) + { + Logger.Info($"{nameof(OnServerDoorRepairing)} triggered by {ev.Door} {ev.RemainingHealth}"); + } + + public override void OnServerCheckpointDoorSequenceChanged(CheckpointDoorSequenceChangedEventArgs ev) + { + Logger.Info($"{nameof(OnServerCheckpointDoorSequenceChanged)} triggered by {ev.CheckpointDoor} {ev.CurrentSequence}"); + } + + public override void OnServerCheckpointDoorSequenceChanging(CheckpointDoorSequenceChangingEventArgs ev) + { + Logger.Info($"{nameof(OnServerCheckpointDoorSequenceChanging)} triggered by {ev.CheckpointDoor} {ev.CurrentSequence} {ev.NewSequence}"); + } + + public override void OnServerRoomColorChanged(RoomColorChangedEventArgs ev) + { + Logger.Info($"{nameof(OnServerRoomColorChanged)} triggered by {ev.Room} {ev.NewState}"); + } + + public override void OnServerRoomLightChanged(RoomLightChangedEventArgs ev) + { + Logger.Info($"{nameof(OnServerRoomLightChanged)} triggered by {ev.Room} {ev.NewState}"); + } #region Excluded Events diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerCheckedHitmarkerEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerCheckedHitmarkerEventArgs.cs new file mode 100644 index 00000000..9291f616 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerCheckedHitmarkerEventArgs.cs @@ -0,0 +1,47 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using PlayerStatsSystem; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.CheckedHitmarker"/> event. +/// </summary> +public class PlayerCheckedHitmarkerEventArgs : EventArgs, IPlayerEvent +{ + /// <summary> + /// Initializes a new instance for the <see cref="PlayerCheckedHitmarkerEventArgs"/> class. + /// </summary> + /// <param name="hub">The player that hitmarker should send.</param> + /// <param name="adh">The damage dealt to the <paramref name="victim"/>.</param> + /// <param name="victim">The player who got hurt by <paramref name="hub"/>.</param> + /// <param name="result">The result of the check.</param> + public PlayerCheckedHitmarkerEventArgs(ReferenceHub hub, AttackerDamageHandler adh, ReferenceHub victim, bool result) + { + Player = Player.Get(hub); + DamageHandler = adh; + Victim = Player.Get(victim); + Result = result; + } + + /// <summary> + /// Gets the player that the hitmarker is being sent to. + /// </summary> + public Player Player { get; } + + /// <summary> + /// Gets the player that was hit. + /// </summary> + public Player Victim { get; } + + /// <summary> + /// Gets the damage handler. + /// </summary> + public AttackerDamageHandler DamageHandler { get; } + + /// <summary> + /// Gets the check result. + /// </summary> + public bool Result { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSendingHitmarkerEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSendingHitmarkerEventArgs.cs new file mode 100644 index 00000000..cfca9f8f --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSendingHitmarkerEventArgs.cs @@ -0,0 +1,44 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.SendingHitmarker"/> event. +/// </summary> +public class PlayerSendingHitmarkerEventArgs : EventArgs, IPlayerEvent, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance for the <see cref="PlayerSendingHitmarkerEventArgs"/> class. + /// </summary> + /// <param name="hub">The player that is sending the hitmarker.</param> + /// <param name="size">The target size multiplier.</param> + /// <param name="playAudio">Whether the hitmarker sound effect should play.</param> + public PlayerSendingHitmarkerEventArgs(ReferenceHub hub, float size, bool playAudio) + { + Player = Player.Get(hub); + Size = size; + PlayAudio = playAudio; + + IsAllowed = true; + } + + /// <summary> + /// Gets or sets the player that the hitmarker is being sent to. + /// </summary> + public Player Player { get; set; } + + /// <summary> + /// Gets or sets the target size multiplier. + /// </summary> + public float Size { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether the hitmarker sound effect should play. + /// </summary> + public bool PlayAudio { get; set; } + + /// <inheritdoc/> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSentHitmarkerEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSentHitmarkerEventArgs.cs new file mode 100644 index 00000000..0532502b --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSentHitmarkerEventArgs.cs @@ -0,0 +1,39 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.PlayerEvents.SentHitmarker"/> event. +/// </summary> +public class PlayerSentHitmarkerEventArgs : EventArgs, IPlayerEvent +{ + /// <summary> + /// Initializes a new instance for the <see cref="PlayerSentHitmarkerEventArgs"/> class. + /// </summary> + /// <param name="hub">The player that sent the hitmarker.</param> + /// <param name="size">The target size multiplier.</param> + /// <param name="playedAudio">Whether the hitmarker sound effect was played.</param> + public PlayerSentHitmarkerEventArgs(ReferenceHub hub, float size, bool playedAudio) + { + Player = Player.Get(hub); + Size = size; + PlayedAudio = playedAudio; + } + + /// <summary> + /// Gets the player that the hitmarker was sent to. + /// </summary> + public Player Player { get; } + + /// <summary> + /// Gets the target size multiplier. + /// </summary> + public float Size { get; } + + /// <summary> + /// Gets a value indicating whether the hitmarker sound effect was played. + /// </summary> + public bool PlayedAudio { get; } +} diff --git a/LabApi/Events/Arguments/Scp049Events/Scp049AttackedEventArgs.cs b/LabApi/Events/Arguments/Scp049Events/Scp049AttackedEventArgs.cs new file mode 100644 index 00000000..0a227784 --- /dev/null +++ b/LabApi/Events/Arguments/Scp049Events/Scp049AttackedEventArgs.cs @@ -0,0 +1,46 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp049Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp049Events.Attacked"/> event. +/// </summary> +public class Scp049AttackedEventArgs : EventArgs, IPlayerEvent, ITargetEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp049AttackedEventArgs"/> class. + /// </summary> + /// <param name="hub">The SCP-049 player instance.</param> + /// <param name="target">The player that SCP-049 has attacked.</param> + /// <param name="instantKill">The attack was an instant kill.</param> + /// <param name="isSenseTarget">The <paramref name="target"/> was a sense target.</param> + public Scp049AttackedEventArgs(ReferenceHub hub, ReferenceHub target, bool instantKill, bool isSenseTarget) + { + Player = Player.Get(hub); + Target = Player.Get(target); + InstantKill = instantKill; + IsSenseTarget = isSenseTarget; + } + + /// <summary> + /// The SCP-049 player instance. + /// </summary> + public Player Player { get; } + + /// <summary> + /// The player that SCP-049 has attacked. + /// </summary> + public Player Target { get; } + + /// <summary> + /// Gets whether the attack was an instant kill. + /// </summary> + public bool InstantKill { get; } + + /// <summary> + /// Gets whether the <see cref="Target"/> is a sense target. + /// </summary> + public bool IsSenseTarget { get; } +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/Scp049Events/Scp049AttackingEventArgs.cs b/LabApi/Events/Arguments/Scp049Events/Scp049AttackingEventArgs.cs new file mode 100644 index 00000000..8568470b --- /dev/null +++ b/LabApi/Events/Arguments/Scp049Events/Scp049AttackingEventArgs.cs @@ -0,0 +1,58 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp049Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp049Events.Attacking"/> event. +/// </summary> +public class Scp049AttackingEventArgs : EventArgs, IPlayerEvent, ITargetEvent, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp049AttackingEventArgs"/> class. + /// </summary> + /// <param name="hub">The SCP-049 player instance.</param> + /// <param name="target">The player that SCP-049 is attacking.</param> + /// <param name="instantKill">The attack is an instant kill.</param> + /// <param name="isSenseTarget">The <paramref name="target"/> is a sense target.</param> + /// <param name="cooldownTime">The attack cooldown.</param> + public Scp049AttackingEventArgs(ReferenceHub hub, ReferenceHub target, bool instantKill, bool isSenseTarget, float cooldownTime) + { + Player = Player.Get(hub); + Target = Player.Get(target); + InstantKill = instantKill; + IsSenseTarget = isSenseTarget; + CooldownTime = cooldownTime; + + IsAllowed = true; + } + + /// <summary> + /// The SCP-049 player instance. + /// </summary> + public Player Player { get; } + + /// <summary> + /// The player that SCP-049 is attacking. + /// </summary> + public Player Target { get; } + + /// <summary> + /// Gets or sets whether the attack is an instant kill. + /// </summary> + public bool InstantKill { get; set; } + + /// <summary> + /// Gets or sets whether the <see cref="Target"/> is a sense target. + /// </summary> + public bool IsSenseTarget { get; set; } + + /// <summary> + /// Gets or sets the cooldown for the attack ability. + /// </summary> + public float CooldownTime { get; set; } + + /// <inheritdoc/> + public bool IsAllowed { get; set; } +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/Scp049Events/Scp049SenseKilledTargetEventArgs.cs b/LabApi/Events/Arguments/Scp049Events/Scp049SenseKilledTargetEventArgs.cs new file mode 100644 index 00000000..96e557ad --- /dev/null +++ b/LabApi/Events/Arguments/Scp049Events/Scp049SenseKilledTargetEventArgs.cs @@ -0,0 +1,32 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp049Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp049Events.SenseKilledTarget"/> event. +/// </summary> +public class Scp049SenseKilledTargetEventArgs : EventArgs, IPlayerEvent, ITargetEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp049SenseKilledTargetEventArgs"/> class. + /// </summary> + /// <param name="hub">The SCP-049 player instance.</param> + /// <param name="target">The player that SCP-049 killed.</param> + public Scp049SenseKilledTargetEventArgs(ReferenceHub hub, ReferenceHub target) + { + Player = Player.Get(hub); + Target = Player.Get(target); + } + + /// <summary> + /// The SCP-049 player instance. + /// </summary> + public Player Player { get; } + + /// <summary> + /// The player that SCP-049 has killed. + /// </summary> + public Player Target { get; } +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/Scp049Events/Scp049SenseLostTargetEventArgs.cs b/LabApi/Events/Arguments/Scp049Events/Scp049SenseLostTargetEventArgs.cs new file mode 100644 index 00000000..89b564e3 --- /dev/null +++ b/LabApi/Events/Arguments/Scp049Events/Scp049SenseLostTargetEventArgs.cs @@ -0,0 +1,32 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp049Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp049Events.SenseLostTarget"/> event. +/// </summary> +public class Scp049SenseLostTargetEventArgs : EventArgs, IPlayerEvent, ITargetEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp049SenseLostTargetEventArgs"/> class. + /// </summary> + /// <param name="hub">The SCP-049 player instance.</param> + /// <param name="target">The player that SCP-049 has targeted.</param> + public Scp049SenseLostTargetEventArgs(ReferenceHub hub, ReferenceHub target) + { + Player = Player.Get(hub); + Target = Player.Get(target); + } + + /// <summary> + /// The SCP-049 player instance. + /// </summary> + public Player Player { get; } + + /// <summary> + /// The player that SCP-049 has targeted. + /// </summary> + public Player? Target { get; } +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173SnappedEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173SnappedEventArgs.cs new file mode 100644 index 00000000..bc97f889 --- /dev/null +++ b/LabApi/Events/Arguments/Scp173Events/Scp173SnappedEventArgs.cs @@ -0,0 +1,32 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp173Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp173Events.Snapped"/> event. +/// </summary> +public class Scp173SnappedEventArgs : EventArgs, IPlayerEvent, ITargetEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp173SnappedEventArgs"/> class. + /// </summary> + /// <param name="hub">The SCP-173 player.</param> + /// <param name="target">The player that has been snapped.</param> + public Scp173SnappedEventArgs(ReferenceHub hub, ReferenceHub target) + { + Player = Player.Get(hub); + Target = Player.Get(target); + } + + /// <summary> + /// Gets the SCP-173 player instance. + /// </summary> + public Player Player { get; } + + /// <summary> + /// Gets the player that has been snapped. + /// </summary> + public Player Target { get; } +} diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173SnappingEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173SnappingEventArgs.cs new file mode 100644 index 00000000..d05edee4 --- /dev/null +++ b/LabApi/Events/Arguments/Scp173Events/Scp173SnappingEventArgs.cs @@ -0,0 +1,38 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp173Events; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.Scp173Events.Snapping"/> event. +/// </summary> +public class Scp173SnappingEventArgs : EventArgs, IPlayerEvent, ITargetEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp173SnappingEventArgs"/> class. + /// </summary> + /// <param name="hub">The SCP-173 player.</param> + /// <param name="target">The player to snap.</param> + public Scp173SnappingEventArgs(ReferenceHub hub, ReferenceHub target) + { + IsAllowed = true; + Player = Player.Get(hub); + Target = Player.Get(target); + } + + /// <summary> + /// Gets the SCP-173 player instance. + /// </summary> + public Player Player { get; } + + /// <summary> + /// Gets or sets the player to snap. + /// </summary> + public Player Target { get; set; } + + /// <summary> + /// Gets or sets whether the SCP-173 player can snap the target.<para/> + /// </summary> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/Scp939Events/Scp939FocusedEventArgs.cs b/LabApi/Events/Arguments/Scp939Events/Scp939FocusedEventArgs.cs new file mode 100644 index 00000000..67400b06 --- /dev/null +++ b/LabApi/Events/Arguments/Scp939Events/Scp939FocusedEventArgs.cs @@ -0,0 +1,32 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp939Events; + +/// <summary> +/// Represents the event arguments for when SCP-939 has focused. +/// </summary> +public class Scp939FocusedEventArgs : EventArgs, IPlayerEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp939FocusedEventArgs"/> class. + /// </summary> + /// <param name="hub">The SCP-939 player instance.</param> + /// <param name="focusState">A value indicating whether SCP-939 is in the focus state.</param> + public Scp939FocusedEventArgs(ReferenceHub hub, bool focusState) + { + Player = Player.Get(hub); + FocusState = focusState; + } + + /// <summary> + /// Gets the 939 player instance. + /// </summary> + public Player Player { get; } + + /// <summary> + /// Gets the current state of the SCP-939 focus ability. + /// </summary> + public bool FocusState { get; } +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/Scp939Events/Scp939MimickedEnvironmentEventArgs.cs b/LabApi/Events/Arguments/Scp939Events/Scp939MimickedEnvironmentEventArgs.cs new file mode 100644 index 00000000..cb49c1e2 --- /dev/null +++ b/LabApi/Events/Arguments/Scp939Events/Scp939MimickedEnvironmentEventArgs.cs @@ -0,0 +1,32 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp939Events; + +/// <summary> +/// Represents the event arguments for when SCP-939 has mimicked the environment. +/// </summary> +public class Scp939MimickedEnvironmentEventArgs : EventArgs, IPlayerEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp939MimickedEnvironmentEventArgs"/> class. + /// </summary> + /// <param name="hub">The SCP-939 player instance.</param> + /// <param name="playedSequence">The played environmental sequence.</param> + public Scp939MimickedEnvironmentEventArgs(ReferenceHub hub, byte playedSequence) + { + Player = Player.Get(hub); + PlayedSequence = playedSequence; + } + + /// <summary> + /// Gets the 939 player instance. + /// </summary> + public Player Player { get; } + + /// <summary> + /// Gets the played environmental sequence. + /// </summary> + public byte PlayedSequence { get; } +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/Scp939Events/Scp939MimickingEnvironmentEventArgs.cs b/LabApi/Events/Arguments/Scp939Events/Scp939MimickingEnvironmentEventArgs.cs new file mode 100644 index 00000000..c2381769 --- /dev/null +++ b/LabApi/Events/Arguments/Scp939Events/Scp939MimickingEnvironmentEventArgs.cs @@ -0,0 +1,44 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp939Events; + +/// <summary> +/// Represents the event arguments for when SCP-939 is mimicking the environment. +/// </summary> +public class Scp939MimickingEnvironmentEventArgs : EventArgs, IPlayerEvent, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="Scp939MimickingEnvironmentEventArgs"/> class. + /// </summary> + /// <param name="hub">The SCP-939 player instance.</param> + /// <param name="selectedSequence">The selected environmental sequence to play.</param> + /// <param name="cooldownTime">The cooldown for mimicking the environment.</param> + public Scp939MimickingEnvironmentEventArgs(ReferenceHub hub, byte selectedSequence, float cooldownTime) + { + Player = Player.Get(hub); + SelectedSequence = selectedSequence; + CooldownTime = cooldownTime; + + IsAllowed = true; + } + + /// <summary> + /// Gets the 939 player instance. + /// </summary> + public Player Player { get; } + + /// <summary> + /// Gets or sets the selected sequence to play. + /// </summary> + public byte SelectedSequence { get; set; } + + /// <summary> + /// Gets or sets the cooldown for mimicking the environment. + /// </summary> + public float CooldownTime { get; set; } + + /// <inheritdoc/> + public bool IsAllowed { get; set; } +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/ScpEvents/ScpHumeShieldBrokenEventArgs.cs b/LabApi/Events/Arguments/ScpEvents/ScpHumeShieldBrokenEventArgs.cs new file mode 100644 index 00000000..0c3f14de --- /dev/null +++ b/LabApi/Events/Arguments/ScpEvents/ScpHumeShieldBrokenEventArgs.cs @@ -0,0 +1,23 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.ScpEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ScpEvents.HumeShieldBroken"/> event. +/// </summary> +public class ScpHumeShieldBrokenEventArgs : EventArgs, IPlayerEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="ScpHumeShieldBrokenEventArgs"/> class. + /// </summary> + /// <param name="player">The player SCP whom hume shield broke.</param> + public ScpHumeShieldBrokenEventArgs(ReferenceHub player) + { + Player = Player.Get(player); + } + + /// <inheritdoc/> + public Player Player { get; } +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/ServerEvents/AchievedMilestoneEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/AchievedMilestoneEventArgs.cs new file mode 100644 index 00000000..1dd99dd7 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/AchievedMilestoneEventArgs.cs @@ -0,0 +1,38 @@ +using PlayerRoles; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.AchievedMilestone"/> event. +/// </summary> +public class AchievedMilestoneEventArgs : EventArgs +{ + /// <summary> + /// Initializes a new instance of the <see cref="AchievedMilestoneEventArgs"/> class. + /// </summary> + /// <param name="faction">The faction that achieved this milestone.</param> + /// <param name="threshold">The influence threshold for this milestone.</param> + /// <param name="milestoneIndex">The index of the achieved milestone.</param> + public AchievedMilestoneEventArgs(Faction faction, int threshold, int milestoneIndex) + { + Faction = faction; + Threshold = threshold; + MilestoneIndex = milestoneIndex; + } + + /// <summary> + /// Gets the faction that achieved this milestone. + /// </summary> + public Faction Faction { get; } + + /// <summary> + /// Gets the influence threshold for this milestone. + /// </summary> + public int Threshold { get; } + + /// <summary> + /// Gets the index of the achieved milestone. + /// </summary> + public int MilestoneIndex { get; } +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/ServerEvents/AchievingMilestoneEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/AchievingMilestoneEventArgs.cs new file mode 100644 index 00000000..3a9992ee --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/AchievingMilestoneEventArgs.cs @@ -0,0 +1,44 @@ +using LabApi.Events.Arguments.Interfaces; +using PlayerRoles; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.AchievingMilestone"/> event. +/// </summary> +public class AchievingMilestoneEventArgs : EventArgs, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="AchievingMilestoneEventArgs"/> class. + /// </summary> + /// <param name="faction">The faction that achieved this milestone.</param> + /// <param name="threshold">The influence threshold for this milestone.</param> + /// <param name="milestoneIndex">The index of the achieved milestone.</param> + public AchievingMilestoneEventArgs(Faction faction, int threshold, int milestoneIndex) + { + Faction = faction; + Threshold = threshold; + MilestoneIndex = milestoneIndex; + + IsAllowed = true; + } + + /// <summary> + /// Gets the faction that achieved this milestone. + /// </summary> + public Faction Faction { get; } + + /// <summary> + /// Gets the influence threshold for this milestone. + /// </summary> + public int Threshold { get; } + + /// <summary> + /// Gets the index of the achieved milestone. + /// </summary> + public int MilestoneIndex { get; } + + /// <inheritdoc/> + public bool IsAllowed { get; set; } +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/ServerEvents/BlastDoorChangedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/BlastDoorChangedEventArgs.cs new file mode 100644 index 00000000..9038df7d --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/BlastDoorChangedEventArgs.cs @@ -0,0 +1,30 @@ +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.BlastDoorChanged"/> event. +/// </summary> +public class BlastDoorChangedEventArgs : EventArgs +{ + /// <summary> + /// Initializes a new instance of the <see cref="BlastDoorChangedEventArgs"/> class. + /// </summary> + /// <param name="blastDoor">The door that is chaning it's state.</param> + /// <param name="newState">The <paramref name="blastDoor"/>'s new state.</param> + public BlastDoorChangedEventArgs(BlastDoor blastDoor, bool newState) + { + BlastDoor = blastDoor; + NewState = newState; + } + + /// <summary> + /// Gets the current Blast Door. + /// </summary> + public BlastDoor BlastDoor { get; } + + /// <summary> + /// Gets the <see cref="BlastDoor"/> new state. + /// </summary> + public bool NewState { get; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/BlastDoorChangingEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/BlastDoorChangingEventArgs.cs new file mode 100644 index 00000000..bd0e8f86 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/BlastDoorChangingEventArgs.cs @@ -0,0 +1,36 @@ +using LabApi.Events.Arguments.Interfaces; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.BlastDoorChanging"/> event. +/// </summary> +public class BlastDoorChangingEventArgs : EventArgs, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="BlastDoorChangingEventArgs"/> class. + /// </summary> + /// <param name="blastDoor">The door that is changing it's state.</param> + /// <param name="newState">The <paramref name="blastDoor"/>'s new state.</param> + public BlastDoorChangingEventArgs(BlastDoor blastDoor, bool newState) + { + BlastDoor = blastDoor; + NewState = newState; + + IsAllowed = true; + } + + /// <summary> + /// Gets the current Blast Door. + /// </summary> + public BlastDoor BlastDoor { get; } + + /// <summary> + /// Gets or sets the <see cref="BlastDoor"/> new state. + /// </summary> + public bool NewState { get; set; } + + /// <inheritdoc/> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/CheckpointDoorSequenceChangedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/CheckpointDoorSequenceChangedEventArgs.cs new file mode 100644 index 00000000..1d1261e0 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/CheckpointDoorSequenceChangedEventArgs.cs @@ -0,0 +1,32 @@ +using LabApi.Features.Wrappers; +using System; +using static Interactables.Interobjects.CheckpointDoor; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.CheckpointDoorSequenceChanged"/> event. +/// </summary> +public class CheckpointDoorSequenceChangedEventArgs : EventArgs +{ + /// <summary> + /// Initializes a new instance of the <see cref="DoorDamagingEventArgs"/> class. + /// </summary> + /// <param name="door">The current checkpoint door.</param> + /// <param name="sequenceState">The current state this checkpoint is.</param> + public CheckpointDoorSequenceChangedEventArgs(Interactables.Interobjects.CheckpointDoor door, SequenceState sequenceState) + { + CheckpointDoor = CheckpointDoor.Get(door); + CurrentSequence = sequenceState; + } + + /// <summary> + /// Gets the current Checkpoint Door. + /// </summary> + public CheckpointDoor CheckpointDoor { get; } + + /// <summary> + /// Gets the damage value. + /// </summary> + public SequenceState CurrentSequence { get; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/CheckpointDoorSequenceChangingEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/CheckpointDoorSequenceChangingEventArgs.cs new file mode 100644 index 00000000..2f436c79 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/CheckpointDoorSequenceChangingEventArgs.cs @@ -0,0 +1,45 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using static Interactables.Interobjects.CheckpointDoor; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.CheckpointDoorSequenceChanging"/> event. +/// </summary> +public class CheckpointDoorSequenceChangingEventArgs : EventArgs, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="CheckpointDoorSequenceChangingEventArgs"/> class. + /// </summary> + /// <param name="door">The current checkpoint door.</param> + /// <param name="oldState">The current state this checkpoint is.</param> + /// <param name="sequenceState">The new state this checkpoint changing.</param> + public CheckpointDoorSequenceChangingEventArgs(Interactables.Interobjects.CheckpointDoor door, SequenceState oldState, SequenceState sequenceState) + { + CheckpointDoor = CheckpointDoor.Get(door); + CurrentSequence = oldState; + NewSequence = sequenceState; + + IsAllowed = true; + } + + /// <summary> + /// Gets the current Checkpoint Door. + /// </summary> + public CheckpointDoor CheckpointDoor { get; } + + /// <summary> + /// Gets the current sequence state. + /// </summary> + public SequenceState CurrentSequence { get; } + + /// <summary> + /// Gets or sets the new sequence state. + /// </summary> + public SequenceState NewSequence { get; set; } + + /// <inheritdoc/> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/DeadmanSequenceActivatingEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/DeadmanSequenceActivatingEventArgs.cs new file mode 100644 index 00000000..446482a0 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/DeadmanSequenceActivatingEventArgs.cs @@ -0,0 +1,14 @@ +using LabApi.Events.Arguments.Interfaces; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.DeadmanSequenceActivating"/> event. +/// </summary> +public class DeadmanSequenceActivatingEventArgs : EventArgs, ICancellableEvent +{ + /// <inheritdoc /> + /// <remarks>Will reset Deadman Sequence timer back to 0 if <see langword="false"/>.</remarks> + public bool IsAllowed { get; set; } = true; +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/ServerEvents/DoorDamagedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/DoorDamagedEventArgs.cs new file mode 100644 index 00000000..dc6ce212 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/DoorDamagedEventArgs.cs @@ -0,0 +1,39 @@ +using Interactables.Interobjects.DoorUtils; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.DoorDamaged"/> event. +/// </summary> +public class DoorDamagedEventArgs : EventArgs +{ + /// <summary> + /// Initializes a new instance of the <see cref="DoorDamagedEventArgs"/> class. + /// </summary> + /// <param name="door">The door that was damaged.</param> + /// <param name="hp">The damage to apply this door.</param> + /// <param name="type">The type of damage this door received.</param> + public DoorDamagedEventArgs(DoorVariant door, float hp, DoorDamageType type) + { + Door = Door.Get(door); + Damage = hp; + DamageType = type; + } + + /// <summary> + /// Gets the current Door. + /// </summary> + public Door Door { get; } + + /// <summary> + /// Gets the damage value. + /// </summary> + public float Damage { get; } + + /// <summary> + /// Gets the damage type. + /// </summary> + public DoorDamageType DamageType { get; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/DoorDamagingEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/DoorDamagingEventArgs.cs new file mode 100644 index 00000000..9114da41 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/DoorDamagingEventArgs.cs @@ -0,0 +1,45 @@ +using Interactables.Interobjects.DoorUtils; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.DoorDamaging"/> event. +/// </summary> +public class DoorDamagingEventArgs : EventArgs, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="DoorDamagingEventArgs"/> class. + /// </summary> + /// <param name="door">The door that is damaging.</param> + /// <param name="hp">The damage to apply this door.</param> + /// <param name="type">The type of damage this door received.</param> + public DoorDamagingEventArgs(DoorVariant door, float hp, DoorDamageType type) + { + Door = Door.Get(door); + Damage = hp; + DamageType = type; + + IsAllowed = true; + } + + /// <summary> + /// Gets the current Door. + /// </summary> + public Door Door { get; } + + /// <summary> + /// Gets or sets the damage value. + /// </summary> + public float Damage { get; set; } + + /// <summary> + /// Gets or sets the damage type. + /// </summary> + public DoorDamageType DamageType { get; set; } + + /// <inheritdoc/> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/DoorLockChangedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/DoorLockChangedEventArgs.cs new file mode 100644 index 00000000..a0f28ac4 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/DoorLockChangedEventArgs.cs @@ -0,0 +1,40 @@ +using Interactables.Interobjects.DoorUtils; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.DoorLockChanged"/> event. +/// </summary> +public class DoorLockChangedEventArgs : EventArgs +{ + /// <summary> + /// Initializes a new instance of the <see cref="DoorLockChangedEventArgs"/> class. + /// </summary> + /// <param name="door">The door whose lock reason changed.</param> + /// <param name="prevLockReason">The previous lock reason.</param> + /// <param name="activeLocks">The <paramref name="door"/>'s lock reason.</param> + public DoorLockChangedEventArgs(DoorVariant door, ushort prevLockReason, ushort activeLocks) + { + Door = Door.Get(door); + PrevLockReason = (DoorLockReason)prevLockReason; + LockReason = (DoorLockReason)activeLocks; + } + + /// <summary> + /// Gets the current Door. + /// </summary> + public Door Door { get; } + + /// <summary> + /// Gets the <see cref="Door"/> old lock reason. + /// </summary> + public DoorLockReason PrevLockReason { get; } + + /// <summary> + /// Gets the <see cref="Door"/> new lock reason. + /// </summary> + public DoorLockReason LockReason { get; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/DoorRepairedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/DoorRepairedEventArgs.cs new file mode 100644 index 00000000..27aa4d2c --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/DoorRepairedEventArgs.cs @@ -0,0 +1,32 @@ +using Interactables.Interobjects.DoorUtils; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.DoorRepaired"/> event. +/// </summary> +public class DoorRepairedEventArgs : EventArgs +{ + /// <summary> + /// Initializes a new instance of the <see cref="DoorRepairedEventArgs"/> class. + /// </summary> + /// <param name="door">The door that was repaired.</param> + /// <param name="remainingHealth">The remaining health for this door.</param> + public DoorRepairedEventArgs(DoorVariant door, float remainingHealth) + { + Door = Door.Get(door); + RemainingHealth = remainingHealth; + } + + /// <summary> + /// Gets the current Door. + /// </summary> + public Door Door { get; } + + /// <summary> + /// Gets the remaining health of the <see cref="Door"/>. + /// </summary> + public float RemainingHealth { get; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/DoorRepairingEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/DoorRepairingEventArgs.cs new file mode 100644 index 00000000..f9014b99 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/DoorRepairingEventArgs.cs @@ -0,0 +1,38 @@ +using Interactables.Interobjects.DoorUtils; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.DoorRepairing"/> event. +/// </summary> +public class DoorRepairingEventArgs : EventArgs, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="DoorRepairingEventArgs"/> class. + /// </summary> + /// <param name="door">The door that is repairing.</param> + /// <param name="remainingHealth">The remaining health for this door.</param> + public DoorRepairingEventArgs(DoorVariant door, float remainingHealth) + { + Door = Door.Get(door); + RemainingHealth = remainingHealth; + + IsAllowed = true; + } + + /// <summary> + /// Gets the current Door. + /// </summary> + public Door Door { get; } + + /// <summary> + /// Gets or sets the remaining health of the <see cref="Door"/>. + /// </summary> + public float RemainingHealth { get; set; } + + /// <inheritdoc/> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/ModifiedFactionInfluenceEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/ModifiedFactionInfluenceEventArgs.cs new file mode 100644 index 00000000..b967e7eb --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/ModifiedFactionInfluenceEventArgs.cs @@ -0,0 +1,32 @@ +using PlayerRoles; +using Respawning; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.ModifiedFactionInfluence"/> event. +/// </summary> +public class ModifiedFactionInfluenceEventArgs : EventArgs +{ + /// <summary> + /// Initializes a new instance of the <see cref="ModifiedFactionInfluenceEventArgs"/> class. + /// </summary> + /// <param name="faction">The faction whose influence is modified.</param> + /// <param name="influence">The <see cref="FactionInfluenceManager.Influence">influence</see> amount the <paramref name="faction"/> has now.</param> + public ModifiedFactionInfluenceEventArgs(Faction faction, float influence) + { + Faction = faction; + Influence = influence; + } + + /// <summary> + /// Gets the faction whose influence is modified. + /// </summary> + public Faction Faction { get; } + + /// <summary> + /// Gets the new influence of the <see cref="Faction"/>. + /// </summary> + public float Influence { get; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/ModifyingFactionInfluenceEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/ModifyingFactionInfluenceEventArgs.cs new file mode 100644 index 00000000..66ea997a --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/ModifyingFactionInfluenceEventArgs.cs @@ -0,0 +1,38 @@ +using LabApi.Events.Arguments.Interfaces; +using PlayerRoles; +using Respawning; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.ModifyingFactionInfluence"/> event. +/// </summary> +public class ModifyingFactionInfluenceEventArgs : EventArgs, ICancellableEvent +{ + /// <summary> + /// Initializes a new instance of the <see cref="ModifyingFactionInfluenceEventArgs"/> class. + /// </summary> + /// <param name="faction">The faction whose influence is being modified.</param> + /// <param name="influence">The <see cref="FactionInfluenceManager.Influence">influence</see> amount the <paramref name="faction"/> has now.</param> + public ModifyingFactionInfluenceEventArgs(Faction faction, float influence) + { + Faction = faction; + Influence = influence; + + IsAllowed = true; + } + + /// <summary> + /// Gets or sets the faction whose influence is being modified. + /// </summary> + public Faction Faction { get; set; } + + /// <summary> + /// Gets or sets the new influence of the <see cref="Faction"/>. + /// </summary> + public float Influence { get; set; } + + /// <inheritdoc/> + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/RoomColorChangedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/RoomColorChangedEventArgs.cs new file mode 100644 index 00000000..2eac9d68 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/RoomColorChangedEventArgs.cs @@ -0,0 +1,33 @@ +using LabApi.Features.Wrappers; +using MapGeneration; +using System; +using UnityEngine; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.RoomColorChanged"/> event. +/// </summary> +public class RoomColorChangedEventArgs : EventArgs +{ + /// <summary> + /// Initializes a new instance of the <see cref="RoomColorChangedEventArgs"/> class. + /// </summary> + /// <param name="room">The room that is changing its color.</param> + /// <param name="newState">The <paramref name="room"/>'s new color.</param> + public RoomColorChangedEventArgs(RoomIdentifier room, Color newState) + { + Room = Room.Get(room); + NewState = newState; + } + + /// <summary> + /// Gets the current room. + /// </summary> + public Room Room { get; } + + /// <summary> + /// Gets the <see cref="Room"/> new color. + /// </summary> + public Color NewState { get; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/RoomLightChangedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/RoomLightChangedEventArgs.cs new file mode 100644 index 00000000..a8a6d4c4 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/RoomLightChangedEventArgs.cs @@ -0,0 +1,32 @@ +using LabApi.Features.Wrappers; +using MapGeneration; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// <summary> +/// Represents the arguments for the <see cref="Handlers.ServerEvents.RoomLightChanged"/> event. +/// </summary> +public class RoomLightChangedEventArgs : EventArgs +{ + /// <summary> + /// Initializes a new instance of the <see cref="RoomLightChangedEventArgs"/> class. + /// </summary> + /// <param name="room">The room that is changing its light state.</param> + /// <param name="newState">The <paramref name="room"/>'s new light state.</param> + public RoomLightChangedEventArgs(RoomIdentifier room, bool newState) + { + Room = Room.Get(room); + NewState = newState; + } + + /// <summary> + /// Gets the current room. + /// </summary> + public Room Room { get; } + + /// <summary> + /// Gets the <see cref="Room"/> new light state. + /// </summary> + public bool NewState { get; } +} diff --git a/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs b/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs index b06c0de5..bd9e2ac2 100644 --- a/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs +++ b/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs @@ -883,6 +883,21 @@ public static partial class PlayerEvents /// </summary> public static event LabEventHandler<PlayerInteractedWarheadLeverEventArgs>? InteractedWarheadLever; + /// <summary> + /// Gets called when a hitmarker is being sent to a player. + /// </summary> + public static event LabEventHandler<PlayerSendingHitmarkerEventArgs>? SendingHitmarker; + + /// <summary> + /// Gets called when a hitmarker is sent to a player. + /// </summary> + public static event LabEventHandler<PlayerSentHitmarkerEventArgs>? SentHitmarker; + + /// <summary> + /// Gets called when a hitmarker permission is checked for a player. + /// </summary> + public static event LabEventHandler<PlayerCheckedHitmarkerEventArgs>? CheckedHitmarker; + #endregion #region Spectating diff --git a/LabApi/Events/Handlers/Scp049Events.EventHandlers.cs b/LabApi/Events/Handlers/Scp049Events.EventHandlers.cs index cc92149d..7e632c77 100644 --- a/LabApi/Events/Handlers/Scp049Events.EventHandlers.cs +++ b/LabApi/Events/Handlers/Scp049Events.EventHandlers.cs @@ -41,4 +41,24 @@ public static partial class Scp049Events /// Gets called when SCP-049 has used its sense ability. /// </summary> public static event LabEventHandler<Scp049UsedSenseEventArgs>? UsedSense; + + /// <summary> + /// Gets called when SCP-049 is using its attack ability. + /// </summary> + public static event LabEventHandler<Scp049AttackingEventArgs>? Attacking; + + /// <summary> + /// Gets called when SCP-049 has used its attack ability. + /// </summary> + public static event LabEventHandler<Scp049AttackedEventArgs>? Attacked; + + /// <summary> + /// Gets called when SCP-049 has lost a target. + /// </summary> + public static event LabEventHandler<Scp049SenseLostTargetEventArgs>? SenseLostTarget; + + /// <summary> + /// Gets called when SCP-049 has killed a target. + /// </summary> + public static event LabEventHandler<Scp049SenseKilledTargetEventArgs>? SenseKilledTarget; } \ No newline at end of file diff --git a/LabApi/Events/Handlers/Scp173Events.EventHandlers.cs b/LabApi/Events/Handlers/Scp173Events.EventHandlers.cs index fef62eb3..a6886da6 100644 --- a/LabApi/Events/Handlers/Scp173Events.EventHandlers.cs +++ b/LabApi/Events/Handlers/Scp173Events.EventHandlers.cs @@ -66,4 +66,14 @@ public static partial class Scp173Events /// Gets called when SCP-173 has teleported. /// </summary> public static event LabEventHandler<Scp173TeleportedEventArgs>? Teleported; + + /// <summary> + /// Gets called when SCP-173 is attempting to snap a target. + /// </summary> + public static event LabEventHandler<Scp173SnappingEventArgs>? Snapping; + + /// <summary> + /// Gets called when SCP-173 has snapped a target. + /// </summary> + public static event LabEventHandler<Scp173SnappedEventArgs>? Snapped; } \ No newline at end of file diff --git a/LabApi/Events/Handlers/Scp939Events.EventHandlers.cs b/LabApi/Events/Handlers/Scp939Events.EventHandlers.cs index b322067f..ac815205 100644 --- a/LabApi/Events/Handlers/Scp939Events.EventHandlers.cs +++ b/LabApi/Events/Handlers/Scp939Events.EventHandlers.cs @@ -36,4 +36,19 @@ public static partial class Scp939Events /// Gets called when SCP-939 has lunged. /// </summary> public static event LabEventHandler<Scp939LungedEventArgs>? Lunged; + + /// <summary> + /// Gets called when SCP-939 has focused. + /// </summary> + public static event LabEventHandler<Scp939FocusedEventArgs>? Focused; + + /// <summary> + /// Gets called when SCP-939 is mimicking the environment. + /// </summary> + public static event LabEventHandler<Scp939MimickingEnvironmentEventArgs>? MimickingEnvironment; + + /// <summary> + /// Gets called when SCP-939 has mimicked the environment. + /// </summary> + public static event LabEventHandler<Scp939MimickedEnvironmentEventArgs>? MimickedEnvironment; } \ No newline at end of file diff --git a/LabApi/Events/Handlers/ScpEvents.EventHandlers.cs b/LabApi/Events/Handlers/ScpEvents.EventHandlers.cs new file mode 100644 index 00000000..1e1acac2 --- /dev/null +++ b/LabApi/Events/Handlers/ScpEvents.EventHandlers.cs @@ -0,0 +1,14 @@ +using LabApi.Events.Arguments.ScpEvents; + +namespace LabApi.Events.Handlers; + +/// <summary> +/// Handles all events related to SCPs. +/// </summary> +public static partial class ScpEvents +{ + /// <summary> + /// Gets called when an SCP has their hume shield broken. + /// </summary> + public static event LabEventHandler<ScpHumeShieldBrokenEventArgs>? HumeShieldBroken; +} \ No newline at end of file diff --git a/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs b/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs index 4ffb37d9..22c977bc 100644 --- a/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs +++ b/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs @@ -17,6 +17,21 @@ public static partial class ServerEvents /// </summary> public static event LabEventHandler? RoundRestarted; + /// <summary> + /// Gets called when the server shuts down. + /// </summary> + public static event LabEventHandler? Shutdown; + + /// <summary> + /// Gets called when Deadman Sequence is activated. + /// </summary> + public static event LabEventHandler? DeadmanSequenceActivated; + + /// <summary> + /// Gets called when Deadman Sequence is activating. + /// </summary> + public static event LabEventHandler<DeadmanSequenceActivatingEventArgs>? DeadmanSequenceActivating; + /// <summary> /// Gets called when round end conditions are checked. /// </summary> @@ -211,4 +226,79 @@ public static partial class ServerEvents /// Gets called when elevator's sequence has changed. /// </summary> public static event LabEventHandler<ElevatorSequenceChangedEventArgs>? ElevatorSequenceChanged; + + /// <summary> + /// Gets called when a faction's influence is changing. + /// </summary> + public static event LabEventHandler<ModifyingFactionInfluenceEventArgs>? ModifyingFactionInfluence; + + /// <summary> + /// Gets called when a faction's influence has changed. + /// </summary> + public static event LabEventHandler<ModifiedFactionInfluenceEventArgs>? ModifiedFactionInfluence; + + /// <summary> + /// Gets called when a faction is achieving a milestone. + /// </summary> + public static event LabEventHandler<AchievingMilestoneEventArgs>? AchievingMilestone; + + /// <summary> + /// Gets called when a faction achieved a milestone. + /// </summary> + public static event LabEventHandler<AchievedMilestoneEventArgs>? AchievedMilestone; + + /// <summary> + /// Gets called when a blast door changes state. + /// </summary> + public static event LabEventHandler<BlastDoorChangingEventArgs>? BlastDoorChanging; + + /// <summary> + /// Gets called when a blast door is changed state. + /// </summary> + public static event LabEventHandler<BlastDoorChangedEventArgs>? BlastDoorChanged; + + /// <summary> + /// Gets called when a room's light is changed. + /// </summary> + public static event LabEventHandler<RoomLightChangedEventArgs>? RoomLightChanged; + + /// <summary> + /// Gets called when a room's color is changed. + /// </summary> + public static event LabEventHandler<RoomColorChangedEventArgs>? RoomColorChanged; + + /// <summary> + /// Gets called when a door's lock state is changed. + /// </summary> + public static event LabEventHandler<DoorLockChangedEventArgs>? DoorLockChanged; + + /// <summary> + /// Gets called when a door is repairing. + /// </summary> + public static event LabEventHandler<DoorRepairingEventArgs>? DoorRepairing; + + /// <summary> + /// Gets called when a door is repaired. + /// </summary> + public static event LabEventHandler<DoorRepairedEventArgs>? DoorRepaired; + + /// <summary> + /// Gets called when a door is damaging. + /// </summary> + public static event LabEventHandler<DoorDamagingEventArgs>? DoorDamaging; + + /// <summary> + /// Gets called when a door is damaged. + /// </summary> + public static event LabEventHandler<DoorDamagedEventArgs>? DoorDamaged; + + /// <summary> + /// Gets called when a checkpoint door sequence is changing. + /// </summary> + public static event LabEventHandler<CheckpointDoorSequenceChangingEventArgs>? CheckpointDoorSequenceChanging; + + /// <summary> + /// Gets called when a checkpoint door sequence is changed. + /// </summary> + public static event LabEventHandler<CheckpointDoorSequenceChangedEventArgs>? CheckpointDoorSequenceChanged; } \ No newline at end of file diff --git a/LabApi/Features/Extensions/RoleExtensions.cs b/LabApi/Features/Extensions/RoleExtensions.cs index 94dc7129..a3ec6e5f 100644 --- a/LabApi/Features/Extensions/RoleExtensions.cs +++ b/LabApi/Features/Extensions/RoleExtensions.cs @@ -1,4 +1,10 @@ -using PlayerRoles; +using System.Collections.Generic; +using PlayerRoles; +using System.Diagnostics.CodeAnalysis; +using InventorySystem; +using InventorySystem.Configs; +using PlayerRoles.FirstPersonControl; +using UnityEngine; namespace LabApi.Features.Extensions; @@ -7,6 +13,8 @@ namespace LabApi.Features.Extensions; /// </summary> public static class RoleExtensions { + private static readonly InventoryRoleInfo EmptyInventoryInfo = new([], []); // prevent creating this multiple time + /// <summary> /// Gets the <see cref="PlayerRoleBase"/> from a <see cref="RoleTypeId"/>. /// </summary> @@ -14,6 +22,15 @@ public static class RoleExtensions /// <returns>The <see cref="PlayerRoleBase"/>.</returns> public static PlayerRoleBase GetRoleBase(this RoleTypeId roleType) => PlayerRoleLoader.TryGetRoleTemplate(roleType, out PlayerRoleBase role) ? role : null!; + /// <summary> + /// Tries to get a role base from a <see cref="RoleTypeId"/>. + /// </summary> + /// <param name="roleTypeId">The <see cref="RoleTypeId"/> to get base of.</param> + /// <param name="role">The <see cref="PlayerRoleBase"/> found.</param> + /// <typeparam name="T">The <see cref="PlayerRoleBase"/>.</typeparam> + /// <returns>The role base found, else null.</returns> + public static bool TryGetRoleBase<T>(this RoleTypeId roleTypeId, [NotNullWhen(true)] out T? role) => PlayerRoleLoader.TryGetRoleTemplate(roleTypeId, out role); + /// <summary> /// Gets the human-readable version of a <see cref="RoleTypeId"/>'s name. /// </summary> @@ -21,6 +38,33 @@ public static class RoleExtensions /// <returns>The name of the role.</returns> public static string GetFullName(this RoleTypeId roleType) => roleType.GetRoleBase().RoleName; + /// <summary> + /// Tries to get a random spawn point from a <see cref="RoleTypeId"/>. + /// </summary> + /// <param name="role">The role to get spawn from.</param> + /// <param name="position">The position found.</param> + /// <param name="horizontalRotation">The rotation found.</param> + /// <returns>Whether a SpawnPoint was found.</returns> + public static bool TryGetRandomSpawnPoint(this RoleTypeId role, out Vector3 position, out float horizontalRotation) + { + if (TryGetRoleBase(role, out IFpcRole? fpcRole)) + { + return fpcRole.SpawnpointHandler.TryGetSpawnpoint(out position, out horizontalRotation); + } + + position = Vector3.zero; + horizontalRotation = 0f; + return false; + } + + /// <summary> + /// Gets the inventory of the specified <see cref="RoleTypeId"/>. + /// </summary> + /// <param name="roleTypeId">The <see cref="RoleTypeId"/> to get inventory of.</param> + /// <returns>The <see cref="InventoryRoleInfo"/> found.</returns> + public static InventoryRoleInfo GetInventory(this RoleTypeId roleTypeId) + => StartingInventories.DefinedInventories.GetValueOrDefault(roleTypeId, EmptyInventoryInfo); + /// <summary> /// Checks if the role is an SCP role. /// </summary> @@ -61,5 +105,5 @@ public static class RoleExtensions /// </summary> /// <param name="roleType">The <see cref="RoleTypeId"/>.</param> /// <returns>A boolean which is true when the role is a civilian role.</returns> - public static bool IsCivilian(this RoleTypeId roleType) => roleType == RoleTypeId.ClassD || roleType == RoleTypeId.Scientist; + public static bool IsCivilian(this RoleTypeId roleType) => roleType is RoleTypeId.ClassD or RoleTypeId.Scientist; } \ No newline at end of file diff --git a/LabApi/Features/Wrappers/AdminToys/AdminToy.cs b/LabApi/Features/Wrappers/AdminToys/AdminToy.cs index 831d4629..7e2c8e77 100644 --- a/LabApi/Features/Wrappers/AdminToys/AdminToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/AdminToy.cs @@ -134,7 +134,7 @@ protected static AdminToy CreateAdminToyWrapper(AdminToyBase adminToyBase) return new AdminToy(adminToyBase); } - return wrapper ?? new AdminToy(adminToyBase); + return wrapper; } /// <summary> @@ -164,9 +164,8 @@ private static void RemoveAdminToy(AdminToyBase adminToyBase) { try { - if (Dictionary.TryGetValue(adminToyBase, out AdminToy adminToy)) + if (Dictionary.Remove(adminToyBase, out AdminToy adminToy)) { - Dictionary.Remove(adminToyBase); adminToy.OnRemove(); } } @@ -299,7 +298,7 @@ public byte MovementSmoothing /// <summary> /// Gets or sets whether the admin toy is static. /// This should be enabled on as many toys possible to increase performance. - /// Static is only applies to the local transformations so parenting to something that moves will still causes it to move while retaining the performance boost. + /// Static is only applies to the local transformations so parenting to something that moves will still cause it to move while retaining the performance boost. /// </summary> /// <remarks> /// A static admin toy will not process <see cref="Position"/>, <see cref="Rotation"/> or <see cref="Scale"/> on both server and client drastically increasing performance. @@ -331,7 +330,7 @@ public float SyncInterval /// Spawns the toy on the client. /// </summary> /// <remarks> - /// Spawn wont cascade to children toy objects, so if they are not spawned you have to call spawn on all of them. + /// Spawn won't cascade to children toy objects, so if they are not spawned you have to call spawn on all of them. /// </remarks> public void Spawn() => NetworkServer.Spawn(GameObject); diff --git a/LabApi/Features/Wrappers/AdminToys/CameraToy.cs b/LabApi/Features/Wrappers/AdminToys/CameraToy.cs index 129a29ea..66050724 100644 --- a/LabApi/Features/Wrappers/AdminToys/CameraToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/CameraToy.cs @@ -101,11 +101,10 @@ internal CameraToy(Scp079CameraToy baseCameraToy) /// </summary> public new Scp079CameraToy Base { get; } - // Todo: reimplement when publicized - // /// <summary> - // /// The camera instance associated with this toy. - // /// </summary> - // public Camera Camera => Camera.Get(Base.Camera); + /// <summary> + /// The camera instance associated with this toy. + /// </summary> + public Camera Camera => Camera.Get(Base.Camera); /// <summary> /// Gets or sets the label of the camera displayed to SCP-079 on HUD. diff --git a/LabApi/Features/Wrappers/Facility/Respawning/Waves/MtfWave.cs b/LabApi/Features/Wrappers/Facility/Respawning/Waves/MtfWave.cs index cfc94fbb..2d461d61 100644 --- a/LabApi/Features/Wrappers/Facility/Respawning/Waves/MtfWave.cs +++ b/LabApi/Features/Wrappers/Facility/Respawning/Waves/MtfWave.cs @@ -1,5 +1,7 @@ -using Respawning.Config; +using LabApi.Features.Console; +using Respawning.Config; using Respawning.Waves; +using System; namespace LabApi.Features.Wrappers; @@ -23,19 +25,39 @@ internal MtfWave(NtfSpawnWave wave) /// <summary> /// Gets or sets the amount of sergeants that can spawn with the wave. /// </summary> + [Obsolete("Use SergeantsPercentage instead", true)] public int MaxSergeants { - get => Base.MaxSergeants; - set => Base.MaxSergeants = value; + get => 0; + set => Logger.Error("Plugin Error. Cannot set MaxSergeants, use SergeantsPercentage instead."); + } + + /// <summary> + /// Gets the percentage of sergeants that can spawn with the wave. + /// </summary> + public float SergeantsPercentage + { + get => Base.SergeantPercent; + set => Base.SergeantPercent = value; } /// <summary> /// Gets or sets the amount of captains that can spawn with the wave. /// </summary> + [Obsolete("Use CaptainsPercentage instead", true)] public int MaxCaptains { - get => Base.MaxCaptains; - set => Base.MaxCaptains = value; + get => 0; + set => Logger.Error("Plugin Error. Cannot set MaxCaptains, use CaptainsPercentage instead."); + } + + /// <summary> + /// Gets the percentage of captains that can spawn with the wave. + /// </summary> + public float CaptainsPercentage + { + get => Base.CaptainPercent; + set => Base.CaptainPercent = value; } /// <inheritdoc/> diff --git a/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs b/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs index 5118ee4f..c5eb647a 100644 --- a/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs +++ b/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs @@ -1,4 +1,7 @@ -using PlayerRoles; +using System; +using System.Collections.Generic; +using System.Linq; +using PlayerRoles; using Respawning; using Respawning.Config; using Respawning.Waves; @@ -144,11 +147,21 @@ public float PausedTime /// <summary> /// Plays the respawn announcement. /// </summary> + [Obsolete("Use PlayAnnouncement(IEnumerable<Player>) instead.", true)] public void PlayAnnouncement() + { + PlayAnnouncement([]); + } + + /// <summary> + /// Plays the respawn announcement. + /// </summary> + /// <param name="spawnedPlayers">The players that have spawned to take into account for the announcement.</param> + public void PlayAnnouncement(IEnumerable<Player> spawnedPlayers) { if (Base is IAnnouncedWave wave) { - wave.Announcement.PlayAnnouncement(); + wave.Announcement.PlayAnnouncement(spawnedPlayers.Select(p => p.ReferenceHub).ToList()); } } @@ -158,7 +171,9 @@ public void PlayAnnouncement() public void PlayRespawnEffect() { if (Base is not IAnimatedWave) + { return; + } WaveUpdateMessage.ServerSendUpdate(Base, UpdateMessageFlags.Trigger); } diff --git a/LabApi/Features/Wrappers/Facility/Warhead.cs b/LabApi/Features/Wrappers/Facility/Warhead.cs index fdc3557e..3ef016a2 100644 --- a/LabApi/Features/Wrappers/Facility/Warhead.cs +++ b/LabApi/Features/Wrappers/Facility/Warhead.cs @@ -347,7 +347,8 @@ public readonly struct DetonationScenario internal DetonationScenario(AlphaWarheadController.DetonationScenario detonationScenario, byte id, WarheadScenarioType type) { TimeToDetonate = detonationScenario.TimeToDetonate; - AdditionalTime = detonationScenario.AdditionalTime; + // TODO: Remove the cast on 2.0.0 and change additional time to float + AdditionalTime = (int)detonationScenario.AdditionalTime; Type = type; Id = id; } diff --git a/LabApi/Features/Wrappers/Items/JailbirdItem.cs b/LabApi/Features/Wrappers/Items/JailbirdItem.cs index a021dd94..f5248e2f 100644 --- a/LabApi/Features/Wrappers/Items/JailbirdItem.cs +++ b/LabApi/Features/Wrappers/Items/JailbirdItem.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using InventorySystem.Items.Jailbird; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using BaseJailbirdItem = InventorySystem.Items.Jailbird.JailbirdItem; @@ -55,6 +56,11 @@ internal JailbirdItem(BaseJailbirdItem baseJailbirdItem) /// </summary> public new BaseJailbirdItem Base { get; } + /// <summary> + /// Gets the current <see cref="JailbirdWearState"/>. + /// </summary> + public JailbirdWearState WearState => JailbirdDeteriorationTracker.ReceivedStates.GetValueOrDefault(Serial, JailbirdWearState.Healthy); + /// <summary> /// Gets the number of charges performed. /// </summary> @@ -65,6 +71,11 @@ internal JailbirdItem(BaseJailbirdItem baseJailbirdItem) /// </summary> public bool IsCharging => Base.MovementOverrideActive; + /// <summary> + /// Resets charges and damage dealt. + /// </summary> + public void Reset() => Base.ServerReset(); + /// <summary> /// An internal method to remove itself from the cache when the base object is destroyed. /// </summary> diff --git a/LabApi/Features/Wrappers/Items/MicroHIDItem.cs b/LabApi/Features/Wrappers/Items/MicroHIDItem.cs index 840fe279..0afe1d0d 100644 --- a/LabApi/Features/Wrappers/Items/MicroHIDItem.cs +++ b/LabApi/Features/Wrappers/Items/MicroHIDItem.cs @@ -139,7 +139,7 @@ public MicroHidFiringMode FiringMode /// </summary> /// <param name="range">The sounds range in meters.</param> /// <returns>Returns true if the micro is emitting sound, otherwise false.</returns> - public bool TryGetSoundEmissionRange(out float range) => Base.ServerTryGetSoundEmissionRange(out range); + public bool TryGetSoundEmissionRange(out float range) => Base.TryGetSoundEmissionRange(out range); /// <summary> /// An internal method to remove itself from the cache when the base object is destroyed. diff --git a/LabApi/Features/Wrappers/Items/Usable/UsableItem.cs b/LabApi/Features/Wrappers/Items/Usable/UsableItem.cs index 717d0ab0..6c3debac 100644 --- a/LabApi/Features/Wrappers/Items/Usable/UsableItem.cs +++ b/LabApi/Features/Wrappers/Items/Usable/UsableItem.cs @@ -141,7 +141,7 @@ public float PersonalCooldownDuration /// </summary> /// <param name="range">The sounds range in meters.</param> /// <returns>Returns true if item is being used, otherwise false.</returns> - public bool TryGetSoundEmissionRange(out float range) => Base.ServerTryGetSoundEmissionRange(out range); + public bool TryGetSoundEmissionRange(out float range) => Base.TryGetSoundEmissionRange(out range); /// <summary> /// An internal method to remove itself from the cache when the base object is destroyed. diff --git a/LabApi/Features/Wrappers/Players/Player.cs b/LabApi/Features/Wrappers/Players/Player.cs index f3cddbf6..6f000473 100644 --- a/LabApi/Features/Wrappers/Players/Player.cs +++ b/LabApi/Features/Wrappers/Players/Player.cs @@ -18,6 +18,7 @@ using PlayerRoles; using PlayerRoles.FirstPersonControl; using PlayerRoles.FirstPersonControl.NetworkMessages; +using PlayerRoles.FirstPersonControl.Thirdperson.Subcontrollers; using PlayerRoles.PlayableScps.HumeShield; using PlayerRoles.Spectating; using PlayerRoles.Voice; @@ -1299,6 +1300,15 @@ public float StaminaRemaining set => ReferenceHub.playerStats.GetModule<StaminaStat>().CurValue = value; } + /// <summary> + /// Gets or sets the current player's emotion. + /// </summary> + public EmotionPresetType Emotion + { + get => EmotionSync.GetEmotionPreset(ReferenceHub); + set => EmotionSync.ServerSetEmotionPreset(ReferenceHub, value); + } + /// <summary> /// Teleports the player by the delta location. /// </summary> diff --git a/LabApi/Features/Wrappers/Server/Server.cs b/LabApi/Features/Wrappers/Server/Server.cs index 9a3d69c6..f24e69ea 100644 --- a/LabApi/Features/Wrappers/Server/Server.cs +++ b/LabApi/Features/Wrappers/Server/Server.cs @@ -209,7 +209,7 @@ public static float PlayerListNameRefreshRate /// <summary> /// Gets the <see cref="CommandSystem.GameConsoleCommandHandler"/> instance. /// </summary> - public static GameConsoleCommandHandler GameConsoleCommandHandler => GameCore.Console.singleton.ConsoleCommandHandler; + public static GameConsoleCommandHandler GameConsoleCommandHandler => GameCore.Console.ConsoleCommandHandler; /// <summary> /// Gets the <see cref="ServerShutdown.ServerShutdownState"/> of the server. diff --git a/LabApi/LabApi.csproj b/LabApi/LabApi.csproj index eb703f50..edd29d88 100644 --- a/LabApi/LabApi.csproj +++ b/LabApi/LabApi.csproj @@ -6,7 +6,7 @@ <PlatformTarget>x64</PlatformTarget> <LangVersion>12.0</LangVersion> - <Version>1.1.3</Version> + <Version>1.1.4</Version> <AssemblyName>LabApi</AssemblyName> <PackageId>Northwood.LabAPI</PackageId> diff --git a/LabApi/Loader/CommandLoader.cs b/LabApi/Loader/CommandLoader.cs index 4bcf35b1..57fc35fb 100644 --- a/LabApi/Loader/CommandLoader.cs +++ b/LabApi/Loader/CommandLoader.cs @@ -22,16 +22,16 @@ public static class CommandLoader /// <summary> /// The dictionary of command handlers. /// </summary> - public static Dictionary<Type, CommandHandler> CommandHandlers { get; } = new() + public static Dictionary<Type, List<CommandHandler>> CommandHandlers { get; } = new() { // The server console command handler. - [typeof(GameConsoleCommandHandler)] = GameCore.Console.singleton.ConsoleCommandHandler, + [typeof(GameConsoleCommandHandler)] = [GameCore.Console.ConsoleCommandHandler], // The remote admin command handler. - [typeof(RemoteAdminCommandHandler)] = CommandProcessor.RemoteAdminCommandHandler, + [typeof(RemoteAdminCommandHandler)] = [CommandProcessor.RemoteAdminCommandHandler], // The client console command handler. - [typeof(ClientCommandHandler)] = QueryProcessor.DotCommandHandler, + [typeof(ClientCommandHandler)] = [QueryProcessor.DotCommandHandler], }; /// <summary> @@ -148,14 +148,8 @@ public static bool TryRegisterCommand(Type commandType, Type commandHandlerType, { command = null; - if (CommandHandlers.ContainsKey(commandType)) - { - // This parent command was already registered. - return false; - } - // We try to get the command handler from the dictionary of command handlers. - if (!CommandHandlers.TryGetValue(commandHandlerType, out CommandHandler commandHandler)) + if (!CommandHandlers.TryGetValue(commandHandlerType, out List<CommandHandler> commandHandlers)) { Logger.Error($"{LoggerPrefix} Unable to register command '{commandType.Name}' from '{logName}'. CommandHandler '{commandHandlerType}' not found."); return false; @@ -180,8 +174,17 @@ public static bool TryRegisterCommand(Type commandType, Type commandHandlerType, throw; } - // We finally try to register the command in the command handler. - return TryRegisterCommand(command, commandHandler, logName); + // We iterate through all command handlers (including subcommand that has multiple handler). + foreach (CommandHandler commandHandler in commandHandlers) + { + // We finally try to register the command in the command handler. + if (!TryRegisterCommand(command, commandHandler, logName)) + { + return false; + } + } + + return true; } /// <summary> @@ -195,6 +198,12 @@ public static bool TryRegisterCommand(ICommand command, CommandHandler commandHa { try { + // We check if the command already registered (might happen) and just return. + if (commandHandler.AllCommands.Any(x => string.Equals(x.Command, command.Command, StringComparison.OrdinalIgnoreCase))) + { + return true; + } + // We try to register the command. commandHandler.RegisterCommand(command); @@ -208,10 +217,16 @@ public static bool TryRegisterCommand(ICommand command, CommandHandler commandHa // This allows us to register subcommands to the parent command by just using the CommandHandlerAttribute. // [CommandHandler(typeof(MyParentCommand))] Type commandType = command.GetType(); + if (!CommandHandlers.ContainsKey(commandType)) { // We add the command type to the dictionary of command handlers. - CommandHandlers.Add(commandType, parentCommand); + CommandHandlers[commandType] = []; + } + + if (!CommandHandlers[commandType].Contains(parentCommand)) + { + CommandHandlers[commandType].Add(parentCommand); } // We can finally return true. @@ -262,16 +277,19 @@ public static void UnregisterCommands(this Plugin plugin) public static void UnregisterCommand(ICommand command) { // We iterate through all command handlers. - foreach (CommandHandler commandHandler in CommandHandlers.Values) + foreach (List<CommandHandler> commandHandlers in CommandHandlers.Values) { - // If the command handler does not contain the command, we continue. - if (!commandHandler.AllCommands.Contains(command)) + foreach (CommandHandler commandHandler in commandHandlers) { - continue; - } + // If the command handler does not contain the command, we continue. + if (!commandHandler.AllCommands.Contains(command)) + { + continue; + } - // We manually unregister the command from the command handler. - commandHandler.UnregisterCommand(command); + // We manually unregister the command from the command handler. + commandHandler.UnregisterCommand(command); + } } // We check if the command is a parent command. @@ -292,6 +310,6 @@ internal static void RegisterCommands() { // We register all commands in the LabAPI assembly. // We convert it to an array since IEnumerable are lazy and need to be iterated through to be executed. - LabApiCommands = RegisterCommands(Assembly.GetExecutingAssembly(), "LabApi").ToArray(); + LabApiCommands = RegisterCommands(Assembly.GetExecutingAssembly(), "LabApi").ToArray(); } } \ No newline at end of file diff --git a/LabApi/Loader/Features/Configuration/LabApiConfig.cs b/LabApi/Loader/Features/Configuration/LabApiConfig.cs index db52086d..47bea231 100644 --- a/LabApi/Loader/Features/Configuration/LabApiConfig.cs +++ b/LabApi/Loader/Features/Configuration/LabApiConfig.cs @@ -20,4 +20,11 @@ public class LabApiConfig /// </summary> [Description("List of plugin paths relative to the Plugins folder to load from. Use $port to load from the server port's folder.")] public List<string> PluginPaths { get; set; } = ["global", "$port"]; -} \ No newline at end of file + + /// <summary> + /// Whether to allow loading plugins even if they were built for a different major version of LabAPI. + /// </summary> + /// <seealso cref="LabApi.Loader.Features.Plugins.Configuration.Properties.UnsupportedLoading"/> + [Description("Whether to allow loading plugins even if they were built for a different major version of LabAPI.")] + public bool LoadUnsupportedPlugins { get; set; } +} diff --git a/LabApi/Loader/Features/Plugins/Configuration/Properties.cs b/LabApi/Loader/Features/Plugins/Configuration/Properties.cs index 5706fb11..0e13acf9 100644 --- a/LabApi/Loader/Features/Plugins/Configuration/Properties.cs +++ b/LabApi/Loader/Features/Plugins/Configuration/Properties.cs @@ -1,3 +1,4 @@ +using LabApi.Loader.Features.Plugins.Enums; using System.ComponentModel; namespace LabApi.Loader.Features.Plugins.Configuration; @@ -18,4 +19,10 @@ public class Properties /// </summary> [Description("Whether or not the plugin is enabled.")] public bool IsEnabled { get; set; } = true; -} \ No newline at end of file + + /// <summary> + /// Whether to allow loading the plugin even if it was built for a different major version of LabAPI. + /// </summary> + [Description("""Whether to allow loading the plugin even if it was built for a different major version of LabAPI. "Default" = use port-specific config; "True"/"Enabled" = load if unsupported; "False"/"Disabled" = do not load if unsupported""")] + public OptionalBoolean UnsupportedLoading { get; set; } = OptionalBoolean.Default; +} diff --git a/LabApi/Loader/Features/Plugins/Enums/OptionalBoolean.cs b/LabApi/Loader/Features/Plugins/Enums/OptionalBoolean.cs new file mode 100644 index 00000000..3295ab49 --- /dev/null +++ b/LabApi/Loader/Features/Plugins/Enums/OptionalBoolean.cs @@ -0,0 +1,28 @@ +namespace LabApi.Loader.Features.Plugins.Enums; + +/// <summary> +/// Represents values that specify whether a feature should be activated. +/// </summary> +public enum OptionalBoolean +{ + /// <summary> + /// Uses default behavior, specified in the feature's implementation or in a broader scope. + /// </summary> + Default = -1, + + /// <summary> + /// Overrides default behavior to disable the feature. + /// </summary> + False = 0, + + /// <summary> + /// Overrides default behavior to enable the feature. + /// </summary> + True = 1, + + /// <inheritdoc cref="True" /> + Enabled = True, + + /// <inheritdoc cref="False" /> + Disabled = False, +} diff --git a/LabApi/Loader/PluginLoader.cs b/LabApi/Loader/PluginLoader.cs index 7563818a..0e86b10f 100644 --- a/LabApi/Loader/PluginLoader.cs +++ b/LabApi/Loader/PluginLoader.cs @@ -1,3 +1,4 @@ +using LabApi.Features; using LabApi.Features.Console; using LabApi.Features.Permissions; using LabApi.Features.Permissions.Providers; @@ -6,12 +7,13 @@ using LabApi.Loader.Features.Misc; using LabApi.Loader.Features.Paths; using LabApi.Loader.Features.Plugins; +using LabApi.Loader.Features.Plugins.Enums; +using LabApi.Loader.Features.Yaml; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; -using LabApi.Loader.Features.Yaml; namespace LabApi.Loader; @@ -245,6 +247,12 @@ public static void EnablePlugins(IEnumerable<Plugin> plugins) continue; } + // We check if the required version is compatible with the installed LabAPI version + if (!ValidateVersion(plugin)) + { + continue; + } + // We finally enable the plugin EnablePlugin(plugin); } @@ -359,6 +367,67 @@ private static void LogMissingDependencies(Assembly assembly) } } + private static bool ValidateVersion(Plugin plugin) + { + Version required = plugin.RequiredApiVersion; + + // TODO: Delete (why.....) + if (required == null) + { + return true; + } + + Version current = LabApiProperties.CurrentVersion; + + if (required.Major == current.Major) + { + if (!IsGreaterVersion(required, current)) + { + return true; + } + + Logger.Warn($""" + {LoggerPrefix} Potential issue with plugin {plugin} + It was built for a newer minor/patch version of LabAPI, and might not be able to access some features it depends on. + Are you running an older version of the server? + Current LabAPI version: {LabApiProperties.CompiledVersion} + Required by plugin: {required} + """); + + return true; + } + + string difference = required.Major < current.Major ? "an outdated major version" : "a newer major version"; + + bool shouldLoad = plugin.Properties?.UnsupportedLoading switch + { + OptionalBoolean.True => true, + OptionalBoolean.False => false, + _ => Config.LoadUnsupportedPlugins, + }; + + if (shouldLoad) + { + Logger.Warn($""" + {LoggerPrefix} Forcefully loading unsupported plugin {plugin} + It was built for {difference} of LabAPI, and will likely have degraded functionality. + Current LabAPI version: {LabApiProperties.CompiledVersion} + Required by plugin: {required} + """); + return true; + } + + Logger.Error($""" + {LoggerPrefix} Couldn't enable the plugin {plugin} + It was built for {difference} of LabAPI, and would likely have degraded functionality. + To forcefully load it, set the appropriate property in the plugins's properties.yml file. + To forcefully load all unsupported plugins, set the appropriate property in the LabAPI configuration for the current port (LabApi-{Server.Port}.yml). + Current LabAPI version: {LabApiProperties.CompiledVersion} + Required by plugin: {required} + """); + return false; + } + private static void InstantiatePlugins(Type[] types, Assembly assembly, string filePath) { foreach (Type type in types) @@ -383,4 +452,19 @@ private static void InstantiatePlugins(Type[] types, Assembly assembly, string f Logger.Info($"{LoggerPrefix} Successfully loaded {plugin.Name}"); } } -} \ No newline at end of file + + private static bool IsGreaterVersion(Version required, Version current) + { + Version requiredVersion = new( + required.Major, + required.Minor, + required.Build == -1 ? 0 : required.Build, + required.Revision == -1 ? 0 : required.Revision); + Version currentVersion = new( + current.Major, + current.Minor, + current.Build == -1 ? 0 : current.Build, + current.Revision == -1 ? 0 : current.Revision); + return requiredVersion > currentVersion; + } +} diff --git a/LabApi/README.md b/LabApi/README.md new file mode 120000 index 00000000..457d2fe8 --- /dev/null +++ b/LabApi/README.md @@ -0,0 +1 @@ +C:/Users/jesusqc/RiderProjects/LabAPI-Internal/.github/README.md \ No newline at end of file diff --git a/README.md b/README.md index be23938e..8aaaa1b0 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,35 @@ -[![GitHub release](https://flat.badgen.net/github/release/northwood-studios/LabAPI/)](https://github.com/northwood-studios/NwPluginAPI/releases/) [![NuGet](https://flat.badgen.net/nuget/v/Northwood.LabAPI/latest)](https://www.nuget.org/packages/Northwood.LabAPI/) [![License](https://flat.badgen.net/github/license/northwood-studios/LabAPI)](https://github.com/northwood-studios/LabAPI/blob/master/LICENSE) [![Discord Invitation](https://flat.badgen.net/discord/members/scpsl?icon=discord)](https://discord.gg/scpsl) -# LabAPI +<p align="center"> + <a href="https://scpslgame.com"> + <picture> + <source srcset="https://github.com/user-attachments/assets/04f437c8-7fa9-4da9-bf71-fa39db141cf2" media="(prefers-color-scheme: dark)"> + <img src="https://github.com/user-attachments/assets/aa811a11-2b8e-4397-972d-27c7305318d7" width="125" alt="NW logo"> + </picture> + </a> +</p> + +<h1 align="center">LabAPI</h1> +<h6 align="center"><a href="https://store.steampowered.com/app/700330/SCP_Secret_Laboratory/">SCP: Secret Laboratory</a>'s official server-side modding framework.</h6> +<div align="center"> + <a href="https://plugins.scpslgame.com">Plugins</a> + <span> - </span> + <a href="https://github.com/northwood-studios/LabAPI/wiki">Docs</a> + <span> - </span> + <a href="https://github.com/northwood-studios/LabAPI/issues">Report Bug</a> + <span> - </span> + <a href="https://discord.gg/scpsl">Discord</a> + <p></p> +</div> + +<div align="center"> + +[![Version](https://img.shields.io/github/v/release/northwood-studios/LabAPI?sort=semver&style=flat-square&color=8DBBE9&label=Version)]() +[![License](https://img.shields.io/github/license/northwood-studios/LabAPI?style=flat-square&label=License&color=df967f)]() +[![Contributors](https://img.shields.io/github/contributors-anon/northwood-studios/LabAPI?color=90E59A&style=flat-square&label=Contributors)]() +[![GitHub Issues](https://img.shields.io/github/issues/northwood-studios/LabAPI.svg?style=flat-square&label=Issues&color=d77982)](https://github.com/northwood-studios/LabAPI/issues) +[![Discord](https://img.shields.io/discord/330432627649544202?color=738adb&label=Discord&logo=discord&logoColor=white&style=flat-square)](https://discord.gg/scpsl) + +</div> + The LabAPI project is **[SCP: Secret Laboratory](https://store.steampowered.com/app/700330/SCP_Secret_Laboratory/)**'s official server-side plugin loader and framework. It facilitates development of plugins by providing wrappers and events around various game mechanics found throughout the game. ## Documentation From 9bf4847588379250561d4e0aa2d2f1ecf1bf9367 Mon Sep 17 00:00:00 2001 From: jesusqc <contact@jesusqc.es> Date: Thu, 30 Oct 2025 20:08:44 +0100 Subject: [PATCH 192/215] version bump --- LabApi/LabApi.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LabApi/LabApi.csproj b/LabApi/LabApi.csproj index edd29d88..8390ec1b 100644 --- a/LabApi/LabApi.csproj +++ b/LabApi/LabApi.csproj @@ -6,7 +6,7 @@ <PlatformTarget>x64</PlatformTarget> <LangVersion>12.0</LangVersion> - <Version>1.1.4</Version> + <Version>1.1.4.1</Version> <AssemblyName>LabApi</AssemblyName> <PackageId>Northwood.LabAPI</PackageId> From 7411426cc4583617b99a77c69bfa8a54182f50c8 Mon Sep 17 00:00:00 2001 From: jesusqc <contact@jesusqc.es> Date: Fri, 31 Oct 2025 18:53:25 +0100 Subject: [PATCH 193/215] WorldSpaceBounds --- LabApi/Features/Wrappers/Facility/Elevator.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Elevator.cs b/LabApi/Features/Wrappers/Facility/Elevator.cs index 05888144..7a329a66 100644 --- a/LabApi/Features/Wrappers/Facility/Elevator.cs +++ b/LabApi/Features/Wrappers/Facility/Elevator.cs @@ -1,10 +1,12 @@ -using Generators; +using System; +using Generators; using Interactables.Interobjects; using Interactables.Interobjects.DoorUtils; using MapGeneration.Distributors; using System.Collections.Generic; using System.Linq; using UnityEngine; +using Utils; using BaseElevatorDoor = Interactables.Interobjects.ElevatorDoor; namespace LabApi.Features.Wrappers; @@ -146,7 +148,15 @@ public ElevatorGroup Group /// Gets the current world space bounds of this elevator. /// <para>World space bounds are cached and recalculated if not valid after elevator movement.</para> /// </summary> - public Bounds WorldSpaceBounds => Base.WorldspaceBounds; + // Rename WorldSpaceRelativeBounds to WorldSpaceBounds in the next major. + [Obsolete("Use WorldSpaceRelativeBounds.Bounds instead.")] + public Bounds WorldSpaceBounds => Base.WorldspaceBounds.Bounds; + + /// <summary> + /// Gets the current world space bounds of this elevator. + /// <para>World space bounds are cached and recalculated if not valid after elevator movement.</para> + /// </summary> + public RelativeBounds WorldSpaceRelativeBounds => Base.WorldspaceBounds; /// <summary> /// Gets the reason why is ANY elevator door locked. From 6b7fff7a42cd2d2c9976f71a27a128727d95c4d7 Mon Sep 17 00:00:00 2001 From: Jesus-QC <69375249+Jesus-QC@users.noreply.github.com> Date: Sat, 1 Nov 2025 00:44:48 +0100 Subject: [PATCH 194/215] Remove obsolete README.md symlink --- LabApi/README.md | 1 - 1 file changed, 1 deletion(-) delete mode 120000 LabApi/README.md diff --git a/LabApi/README.md b/LabApi/README.md deleted file mode 120000 index 457d2fe8..00000000 --- a/LabApi/README.md +++ /dev/null @@ -1 +0,0 @@ -C:/Users/jesusqc/RiderProjects/LabAPI-Internal/.github/README.md \ No newline at end of file From abce3a5753a927de4d747c6c36032693626ba805 Mon Sep 17 00:00:00 2001 From: Jesus-QC <69375249+Jesus-QC@users.noreply.github.com> Date: Sat, 1 Nov 2025 00:47:03 +0100 Subject: [PATCH 195/215] Add initial NuGet.config file with package source configuration --- NuGet.config | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 NuGet.config diff --git a/NuGet.config b/NuGet.config new file mode 100644 index 00000000..4d736c19 --- /dev/null +++ b/NuGet.config @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<configuration> + <packageSources> + <clear /> + <add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" /> + </packageSources> +</configuration> From 2509dab2a501b61db7964b51476e2903875f85a9 Mon Sep 17 00:00:00 2001 From: jesusqc <contact@jesusqc.es> Date: Thu, 30 Oct 2025 20:08:44 +0100 Subject: [PATCH 196/215] version bump --- LabApi/LabApi.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LabApi/LabApi.csproj b/LabApi/LabApi.csproj index edd29d88..8390ec1b 100644 --- a/LabApi/LabApi.csproj +++ b/LabApi/LabApi.csproj @@ -6,7 +6,7 @@ <PlatformTarget>x64</PlatformTarget> <LangVersion>12.0</LangVersion> - <Version>1.1.4</Version> + <Version>1.1.4.1</Version> <AssemblyName>LabApi</AssemblyName> <PackageId>Northwood.LabAPI</PackageId> From e99f39e217c9e5cdfb7755c27cbd0605695120bd Mon Sep 17 00:00:00 2001 From: jesusqc <contact@jesusqc.es> Date: Fri, 31 Oct 2025 18:53:25 +0100 Subject: [PATCH 197/215] WorldSpaceBounds --- LabApi/Features/Wrappers/Facility/Elevator.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Elevator.cs b/LabApi/Features/Wrappers/Facility/Elevator.cs index 05888144..7a329a66 100644 --- a/LabApi/Features/Wrappers/Facility/Elevator.cs +++ b/LabApi/Features/Wrappers/Facility/Elevator.cs @@ -1,10 +1,12 @@ -using Generators; +using System; +using Generators; using Interactables.Interobjects; using Interactables.Interobjects.DoorUtils; using MapGeneration.Distributors; using System.Collections.Generic; using System.Linq; using UnityEngine; +using Utils; using BaseElevatorDoor = Interactables.Interobjects.ElevatorDoor; namespace LabApi.Features.Wrappers; @@ -146,7 +148,15 @@ public ElevatorGroup Group /// Gets the current world space bounds of this elevator. /// <para>World space bounds are cached and recalculated if not valid after elevator movement.</para> /// </summary> - public Bounds WorldSpaceBounds => Base.WorldspaceBounds; + // Rename WorldSpaceRelativeBounds to WorldSpaceBounds in the next major. + [Obsolete("Use WorldSpaceRelativeBounds.Bounds instead.")] + public Bounds WorldSpaceBounds => Base.WorldspaceBounds.Bounds; + + /// <summary> + /// Gets the current world space bounds of this elevator. + /// <para>World space bounds are cached and recalculated if not valid after elevator movement.</para> + /// </summary> + public RelativeBounds WorldSpaceRelativeBounds => Base.WorldspaceBounds; /// <summary> /// Gets the reason why is ANY elevator door locked. From 79785d10781de79ec91086ed81c1cfb1f23982c1 Mon Sep 17 00:00:00 2001 From: SlejmUr <slejmur@protonmail.com> Date: Sat, 1 Nov 2025 13:02:01 +0000 Subject: [PATCH 198/215] Fix TimeGreande SpawnActive RemainingTime --- .../Pickups/Projectiles/Grenades/TimedGrenadeProjectile.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/TimedGrenadeProjectile.cs b/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/TimedGrenadeProjectile.cs index 3594b358..c8fda8e8 100644 --- a/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/TimedGrenadeProjectile.cs +++ b/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/TimedGrenadeProjectile.cs @@ -81,7 +81,11 @@ public class TimedGrenadeProjectile : Projectile newPickup.ServerActivate(); TimedGrenadeProjectile wrapper = (TimedGrenadeProjectile)Pickup.Get(newPickup); - wrapper.RemainingTime = timeOverride; + + if (timeOverride >= 0) + { + wrapper.RemainingTime = timeOverride; + } return wrapper; } From 23368358b2f5a4b0f3d80940ced443f696770f5d Mon Sep 17 00:00:00 2001 From: SlejmUr <slejmur@protonmail.com> Date: Sat, 1 Nov 2025 18:28:47 +0000 Subject: [PATCH 199/215] Fix ragdoll serials --- LabApi/Features/Wrappers/Players/Ragdoll.cs | 26 +++++++++++++++------ 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/LabApi/Features/Wrappers/Players/Ragdoll.cs b/LabApi/Features/Wrappers/Players/Ragdoll.cs index b5dea6d0..2c7e5910 100644 --- a/LabApi/Features/Wrappers/Players/Ragdoll.cs +++ b/LabApi/Features/Wrappers/Players/Ragdoll.cs @@ -6,6 +6,7 @@ using PlayerRoles.Ragdolls; using PlayerStatsSystem; using RelativePositioning; +using System; using System.Collections.Generic; using UnityEngine; @@ -119,7 +120,8 @@ public RoleTypeId Role Base.Info.StartRelativePosition, Base.Info.StartRelativeRotation, Base.Info.Nickname, - Base.Info.CreationTime); + Base.Info.CreationTime, + Base.Info.Serial); } /// <summary> @@ -135,7 +137,8 @@ public string Nickname Base.Info.StartRelativePosition, Base.Info.StartRelativeRotation, value, - Base.Info.CreationTime); + Base.Info.CreationTime, + Base.Info.Serial); } /// <summary> @@ -152,7 +155,8 @@ public DamageHandlerBase DamageHandler Base.Info.StartRelativePosition, Base.Info.StartRelativeRotation, Base.Info.Nickname, - Base.Info.CreationTime); + Base.Info.CreationTime, + Base.Info.Serial); } /// <summary> @@ -170,11 +174,12 @@ public Vector3 Position Base.Info.OwnerHub, Base.Info.Handler, Base.Info.RoleType, - relPos, + relPos, relRot, Base.Info.Scale, Base.Info.Nickname, - Base.Info.CreationTime); + Base.Info.CreationTime, + Base.Info.Serial); } } @@ -196,7 +201,8 @@ public Quaternion Rotation relRot, Base.Info.Scale, Base.Info.Nickname, - Base.Info.CreationTime); + Base.Info.CreationTime, + Base.Info.Serial); } } @@ -218,10 +224,16 @@ public Vector3 Scale Base.Info.StartRelativeRotation, Vector3.Scale(value, RagdollManager.GetDefaultScale(Role)), Base.Info.Nickname, - Base.Info.CreationTime); + Base.Info.CreationTime, + Base.Info.Serial); } } + /// <summary> + /// Gets the serial number of the ragdoll. + /// </summary> + public ushort Serial => Base.NetworkInfo.Serial; + /// <summary> /// Gets or sets whether the corpse is consumed. /// </summary> From db0f7d41a12544a150db4864256b0598008d1a23 Mon Sep 17 00:00:00 2001 From: TtroubleTT <ttroublett2@gmail.com> Date: Sun, 23 Nov 2025 09:23:55 -0800 Subject: [PATCH 200/215] Add sendToPlayers Argument --- .../ObjectiveEvents/EnemyKillingObjectiveEventArgs.cs | 5 +++-- .../Arguments/ObjectiveEvents/EscapingObjectiveEventArgs.cs | 5 +++-- .../ObjectiveEvents/GeneratorActivatingObjectiveEventArgs.cs | 5 +++-- .../ObjectiveEvents/ObjectiveCompletingBaseEventArgs.cs | 5 +++-- .../ObjectiveEvents/ScpDamagingObjectiveEventArgs.cs | 5 +++-- .../ObjectiveEvents/ScpItemPickingObjectiveEventArgs.cs | 5 +++-- 6 files changed, 18 insertions(+), 12 deletions(-) diff --git a/LabApi/Events/Arguments/ObjectiveEvents/EnemyKillingObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/EnemyKillingObjectiveEventArgs.cs index fde1bb89..d1b636ca 100644 --- a/LabApi/Events/Arguments/ObjectiveEvents/EnemyKillingObjectiveEventArgs.cs +++ b/LabApi/Events/Arguments/ObjectiveEvents/EnemyKillingObjectiveEventArgs.cs @@ -16,8 +16,9 @@ public class EnemyKillingObjectiveEventArgs : ObjectiveCompletingBaseEventArgs /// <param name="influenceToGrant">The influence points to grant to the <paramref name="faction"/>.</param> /// <param name="timeToGrant">The time to reduce from the <paramref name="faction"/>.</param> /// <param name="targetHub">The player that has been killed.</param> - public EnemyKillingObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, ReferenceHub targetHub) - : base(hub, faction, influenceToGrant, timeToGrant) + /// <param name="sendToPlayers">Whether the objective completion will be sent to players.</param> + public EnemyKillingObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, ReferenceHub targetHub, bool sendToPlayers) + : base(hub, faction, influenceToGrant, timeToGrant, sendToPlayers) { Target = Player.Get(targetHub); } diff --git a/LabApi/Events/Arguments/ObjectiveEvents/EscapingObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/EscapingObjectiveEventArgs.cs index 1b87beaa..245a7aae 100644 --- a/LabApi/Events/Arguments/ObjectiveEvents/EscapingObjectiveEventArgs.cs +++ b/LabApi/Events/Arguments/ObjectiveEvents/EscapingObjectiveEventArgs.cs @@ -16,8 +16,9 @@ public class EscapingObjectiveEventArgs : ObjectiveCompletingBaseEventArgs /// <param name="timeToGrant">The time to reduce from the <paramref name="faction"/>.</param> /// <param name="newRole">The new role the player gets after escaping.</param> /// <param name="oldRole">The old role of the player.</param> - public EscapingObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, RoleTypeId oldRole, RoleTypeId newRole) - : base(hub, faction, influenceToGrant, timeToGrant) + /// <param name="sendToPlayers">Whether the objective completion will be sent to players.</param> + public EscapingObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, RoleTypeId oldRole, RoleTypeId newRole, bool sendToPlayers) + : base(hub, faction, influenceToGrant, timeToGrant, sendToPlayers) { OldRole = oldRole; NewRole = newRole; diff --git a/LabApi/Events/Arguments/ObjectiveEvents/GeneratorActivatingObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/GeneratorActivatingObjectiveEventArgs.cs index 08eee63a..43bb7e5f 100644 --- a/LabApi/Events/Arguments/ObjectiveEvents/GeneratorActivatingObjectiveEventArgs.cs +++ b/LabApi/Events/Arguments/ObjectiveEvents/GeneratorActivatingObjectiveEventArgs.cs @@ -17,8 +17,9 @@ public class GeneratorActivatingObjectiveEventArgs : ObjectiveCompletingBaseEven /// <param name="influenceToGrant">The influence points to grant to the <paramref name="faction"/>.</param> /// <param name="timeToGrant">The time to reduce from the <paramref name="faction"/>.</param> /// <param name="generator">The generator that has been activated.</param> - public GeneratorActivatingObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, Scp079Generator generator) - : base(hub, faction, influenceToGrant, timeToGrant) + /// <param name="sendToPlayers">Whether the objective completion will be sent to players.</param> + public GeneratorActivatingObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, Scp079Generator generator, bool sendToPlayers) + : base(hub, faction, influenceToGrant, timeToGrant, sendToPlayers) { Generator = Generator.Get(generator); } diff --git a/LabApi/Events/Arguments/ObjectiveEvents/ObjectiveCompletingBaseEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/ObjectiveCompletingBaseEventArgs.cs index 31e6d633..de9a335e 100644 --- a/LabApi/Events/Arguments/ObjectiveEvents/ObjectiveCompletingBaseEventArgs.cs +++ b/LabApi/Events/Arguments/ObjectiveEvents/ObjectiveCompletingBaseEventArgs.cs @@ -17,13 +17,14 @@ public abstract class ObjectiveCompletingBaseEventArgs : EventArgs, ICancellable /// <param name="faction">The Faction to grant the influence to.</param> /// <param name="influenceToGrant">The influence points to grant to the <paramref name="faction"/>.</param> /// <param name="timeToGrant">The time to reduce from the <paramref name="faction"/>.</param> - public ObjectiveCompletingBaseEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant) + /// <param name="sendToPlayers">Whether the objective completion will be sent to players.</param> + public ObjectiveCompletingBaseEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, bool sendToPlayers) { Player = Player.Get(hub); Faction = faction; InfluenceToGrant = influenceToGrant; TimeToGrant = timeToGrant; - SendToPlayers = true; + SendToPlayers = sendToPlayers; IsAllowed = true; } diff --git a/LabApi/Events/Arguments/ObjectiveEvents/ScpDamagingObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/ScpDamagingObjectiveEventArgs.cs index ba9b4cfa..8a66f8a4 100644 --- a/LabApi/Events/Arguments/ObjectiveEvents/ScpDamagingObjectiveEventArgs.cs +++ b/LabApi/Events/Arguments/ObjectiveEvents/ScpDamagingObjectiveEventArgs.cs @@ -16,8 +16,9 @@ public class ScpDamagingObjectiveEventArgs : ObjectiveCompletingBaseEventArgs /// <param name="influenceToGrant">The influence points to grant to the <paramref name="faction"/>.</param> /// <param name="timeToGrant">The time to reduce from the <paramref name="faction"/>.</param> /// <param name="targetHub">The hub of the player SCP that has been damaged.</param> - public ScpDamagingObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, ReferenceHub targetHub) - : base(hub, faction, influenceToGrant, timeToGrant) + /// <param name="sendToPlayers">Whether the objective completion will be sent to players.</param> + public ScpDamagingObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, ReferenceHub targetHub, bool sendToPlayers) + : base(hub, faction, influenceToGrant, timeToGrant, sendToPlayers) { Target = Player.Get(targetHub); } diff --git a/LabApi/Events/Arguments/ObjectiveEvents/ScpItemPickingObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/ScpItemPickingObjectiveEventArgs.cs index 63efff01..e241b906 100644 --- a/LabApi/Events/Arguments/ObjectiveEvents/ScpItemPickingObjectiveEventArgs.cs +++ b/LabApi/Events/Arguments/ObjectiveEvents/ScpItemPickingObjectiveEventArgs.cs @@ -17,8 +17,9 @@ public class ScpItemPickingObjectiveEventArgs : ObjectiveCompletingBaseEventArgs /// <param name="influenceToGrant">The influence points to grant to the <paramref name="faction"/>.</param> /// <param name="timeToGrant">The time to reduce from the <paramref name="faction"/>.</param> /// <param name="item">The item that has been picked up.</param> - public ScpItemPickingObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, ItemBase item) - : base(hub, faction, influenceToGrant, timeToGrant) + /// <param name="sendToPlayers">Whether the objective completion will be sent to players.</param> + public ScpItemPickingObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, ItemBase item, bool sendToPlayers) + : base(hub, faction, influenceToGrant, timeToGrant, sendToPlayers) { Item = Item.Get(item); } From 97f3578aeb6852635823f10aff91acb11aa98ba2 Mon Sep 17 00:00:00 2001 From: Jesus-QC <69375249+Jesus-QC@users.noreply.github.com> Date: Mon, 24 Nov 2025 16:14:50 +0100 Subject: [PATCH 201/215] Version bump --- LabApi/LabApi.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LabApi/LabApi.csproj b/LabApi/LabApi.csproj index 8390ec1b..24a0b84d 100644 --- a/LabApi/LabApi.csproj +++ b/LabApi/LabApi.csproj @@ -6,7 +6,7 @@ <PlatformTarget>x64</PlatformTarget> <LangVersion>12.0</LangVersion> - <Version>1.1.4.1</Version> + <Version>1.1.4.2</Version> <AssemblyName>LabApi</AssemblyName> <PackageId>Northwood.LabAPI</PackageId> From 59baf81b79702f5b33c2c6e95bb3029c5e1237d9 Mon Sep 17 00:00:00 2001 From: Jesus-QC <99-jesusqc@users.noreply.git.scpslgame.com> Date: Mon, 24 Nov 2025 16:32:10 +0100 Subject: [PATCH 202/215] Cassie Refactor --- LabApi/Features/Wrappers/Facility/Cassie.cs | 178 ++++++++++++++++-- .../Facility/Respawning/Waves/RespawnWave.cs | 2 +- 2 files changed, 163 insertions(+), 17 deletions(-) diff --git a/LabApi/Features/Wrappers/Facility/Cassie.cs b/LabApi/Features/Wrappers/Facility/Cassie.cs index a19dc24b..9e724c2e 100644 --- a/LabApi/Features/Wrappers/Facility/Cassie.cs +++ b/LabApi/Features/Wrappers/Facility/Cassie.cs @@ -1,9 +1,12 @@ -using PlayerRoles; +using Cassie; +using Cassie.Interpreters; +using PlayerRoles; using PlayerStatsSystem; -using Respawning; +using Respawning.NamingRules; using System; +using System.Collections.Generic; using System.Linq; -using static NineTailedFoxAnnouncer; +using System.Text; namespace LabApi.Features.Wrappers; @@ -15,17 +18,22 @@ public static class Cassie /// <summary> /// Gets whether CASSIE is currently speaking. /// </summary> - public static bool IsSpeaking => singleton.queue.Count != 0; + public static bool IsSpeaking => CassieAnnouncementDispatcher.CurrentAnnouncement != null; /// <summary> /// Gets all available voice lines for CASSIE. /// </summary> - public static VoiceLine[] AllLines => singleton.voiceLines; + public static CassieLine[] AllLines => !CassieTtsAnnouncer.TryGetDatabase(out CassieLineDatabase db) ? [] : db.AllLines; + + /// <summary> + /// Gets the line database for CASSIE. + /// </summary> + public static CassieLineDatabase? LineDatabase => !CassieTtsAnnouncer.TryGetDatabase(out CassieLineDatabase db) ? null : db; /// <summary> /// Gets all collection names in which voice lines are in. /// </summary> - public static string[] CollectionNames => singleton.voiceLines.Select(n => n.collection).Distinct().ToArray(); + public static string[] CollectionNames => AllLines.Select(n => n.ApiName).Distinct().ToArray(); /// <summary> /// Checks whether a specified word is valid for CASSIE. @@ -33,7 +41,7 @@ public static class Cassie /// </summary> /// <param name="word">The word to check.</param> /// <returns>Whether the word is valid.</returns> - public static bool IsValid(string word) => singleton.voiceLines.Any(line => line.apiName.Equals(word, StringComparison.InvariantCultureIgnoreCase)); + public static bool IsValid(string word) => CollectionNames.Any(line => line.Equals(word, StringComparison.InvariantCultureIgnoreCase)); /// <summary> /// Calculates duration of specific message. @@ -42,17 +50,66 @@ public static class Cassie /// <param name="rawNumber">Raw numbers.</param> /// <param name="speed">The speed of the cassie talking.</param> /// <returns>Duration of the specific message in seconds.</returns> - public static float CalculateDuration(string message, bool rawNumber = false, float speed = 1f) => singleton.CalculateDuration(message, rawNumber, speed); + [Obsolete("Use CalculateDuration(string message, CassiePlaybackModifiers playbackModifiers) instead.", true)] + public static float CalculateDuration(string message, bool rawNumber = false, float speed = 1f) + { + CassiePlaybackModifiers playbackModifiers = new() + { + Pitch = speed, + }; + return (float)CalculateDuration(message, playbackModifiers); + } + + /// <summary> + /// Calculates duration of specific message. + /// </summary> + /// <param name="message">The message.</param> + /// <param name="playbackModifiers">The playback modifier.</param> + /// <returns>Duration of the specific message in seconds.</returns> + public static double CalculateDuration(string message, CassiePlaybackModifiers playbackModifiers) + { + CalculateDuration(message, playbackModifiers, out var time); + return time; + } /// <summary> /// Plays a custom announcement. + /// Queues a custom announcement. /// </summary> /// <param name="message">The sentence CASSIE is supposed to say.</param> /// <param name="isHeld">Sets a minimal 3-second moment of silence before the announcement. For most cases you wanna keep it true.</param> /// <param name="isNoisy">Whether the background noises play.</param> /// <param name="isSubtitles">Show subtitles.</param> /// <param name="customSubtitles">Custom subtitles to appear instead of the actual message.</param> - public static void Message(string message, bool isHeld = false, bool isNoisy = true, bool isSubtitles = true, string customSubtitles = "") => RespawnEffectsController.PlayCassieAnnouncement(message, isHeld, isNoisy, isSubtitles, customSubtitles); + [Obsolete("Use Message(string message, string customSubtitles = \"\", bool playBackground = true, float priority = 0f, float glitchScale = 1f) instead.", true)] + public static void Message(string message, bool isHeld = false, bool isNoisy = true, bool isSubtitles = true, string customSubtitles = "") + => Message(message, customSubtitles); + + /// <summary> + /// Queues a custom announcement. + /// </summary> + /// <param name="message">The sentence CASSIE is supposed to say.</param> + /// <param name="customSubtitles">Custom subtitles to play.</param> + /// <param name="playBackground">Should play the background track (bells, noise).</param> + /// <param name="priority">The priority of this message.</param> + /// <param name="glitchScale">Intensity of glitches and stutters added before sending to clients.</param> + public static void Message(string message, string customSubtitles = "", bool playBackground = true, float priority = 0f, float glitchScale = 1f) + { + CassieTtsPayload payload = new(message, customSubtitles, playBackground); + Message(payload, priority, glitchScale); + } + + /// <summary> + /// Queues an cassie payload announcement. + /// </summary> + /// <param name="payload">The payload to sent.</param> + /// <param name="priority">The priority of this message.</param> + /// <param name="glitchScale">Intensity of glitches and stutters added before sending to clients.</param> + public static void Message(CassieTtsPayload payload, float priority = 0f, float glitchScale = 1f) + { + CassieAnnouncement announcement = new(payload, priority, glitchScale); + CassieAnnouncementDispatcher.AddToQueue(announcement); + } /// <summary> /// Plays the custom announcement with chance of 0f to 1f of adding a glitch or jam before each word. Values closer to 1f are higher chances. @@ -60,19 +117,19 @@ public static class Cassie /// <param name="message">The sentence CASSIE is supposed to say.</param> /// <param name="glitchChance">The chance for glitch sound to be added before each word. Range from 0f to 1f.</param> /// <param name="jamChance">The chance for jam sound to be added before each word. Range from 0f to 1f.</param> - public static void GlitchyMessage(string message, float glitchChance, float jamChance) => singleton.ServerOnlyAddGlitchyPhrase(message, glitchChance, jamChance); + public static void GlitchyMessage(string message, float glitchChance, float jamChance) => CassieGlitchifier.Glitchify(message, glitchChance, jamChance); /// <summary> /// Plays the termination announcement of a SCP player. If the specified player does not have an SCP role then nothing is played. /// </summary> /// <param name="player">The player who is being terminated as an SCP.</param> /// <param name="info">Damage handler causing the death of the player.</param> - public static void ScpTermination(Player player, DamageHandlerBase info) => AnnounceScpTermination(player.ReferenceHub, info); + public static void ScpTermination(Player player, DamageHandlerBase info) => CassieScpTerminationAnnouncement.AnnounceScpTermination(player.ReferenceHub, info); /// <summary> /// Clears the CASSIE announcements queue. /// </summary> - public static void Clear() => RespawnEffectsController.ClearQueue(); + public static void Clear() => CassieAnnouncementDispatcher.ClearAll(); /// <summary> /// Converts player's team into CASSIE-able word. Unit names are converted into NATO_X words, followed by a number. For example "Alpha-5" is converted to "NATO_A 5". @@ -80,14 +137,59 @@ public static class Cassie /// <param name="team">Target team.</param> /// <param name="unitName">MTF Unit name (for team <see cref="Team.FoundationForces"/>).</param> /// <returns>Converted name.</returns> - public static string ConvertTeam(Team team, string unitName) => NineTailedFoxAnnouncer.ConvertTeam(team, unitName); + public static string ConvertTeam(Team team, string unitName) + { + string text = "CONTAINMENTUNIT UNKNOWN"; + switch (team) + { + case Team.FoundationForces: + { + if (!NamingRulesManager.TryGetNamingRule(team, out UnitNamingRule unitNamingRule)) + { + return text; + } + + string text2 = unitNamingRule.TranslateToCassie(unitName); + return "CONTAINMENTUNIT " + text2; + } + + case Team.ChaosInsurgency: + return "BY CHAOSINSURGENCY"; + case Team.Scientists: + return "BY SCIENCE PERSONNEL"; + case Team.ClassD: + return "BY CLASSD PERSONNEL"; + default: + return text; + } + } /// <summary> /// Converts number into string. /// </summary> /// <param name="num">The number.</param> /// <returns>Number converted to string.</returns> - public static string ConvertNumber(int num) => NineTailedFoxAnnouncer.ConvertNumber(num); + public static string ConvertNumber(int num) + { + if (LineDatabase == null) + { + return string.Empty; + } + + NumberInterpreter? numberInterpreter = (NumberInterpreter?)CassieTtsAnnouncer.Interpreters.FirstOrDefault(x => x is NumberInterpreter); + if (numberInterpreter == null) + { + return string.Empty; + } + + string word = num.ToString(); + + CassiePlaybackModifiers cassiePlaybackModifiers = default; + StringBuilder sb = new(); + numberInterpreter.GetResults(LineDatabase, ref cassiePlaybackModifiers, word, sb, out bool halt); + + return sb.ToString(); + } /// <summary> /// Converts player's <see cref="RoleTypeId"/> into an SCP <b>number</b> identifier. @@ -95,7 +197,7 @@ public static class Cassie /// <param name="role">The target <see cref="RoleTypeId"/>.</param> /// <param name="withoutSpace">The SCP number without spaces between. Used by CASSIE.</param> /// <param name="withSpace">The SCP number with spaces between. Used by Subtitles.</param> - public static void ConvertScp(RoleTypeId role, out string withoutSpace, out string withSpace) => NineTailedFoxAnnouncer.ConvertSCP(role, out withoutSpace, out withSpace); + public static void ConvertScp(RoleTypeId role, out string withoutSpace, out string withSpace) => CassieScpTerminationAnnouncement.ConvertSCP(role, out withoutSpace, out withSpace); /// <summary> /// Converts player's role name into an SCP <b>number</b> identifier. @@ -103,5 +205,49 @@ public static class Cassie /// <param name="roleName">The targets role name.</param> /// <param name="withoutSpace">The SCP number without spaces between. Used by CASSIE.</param> /// <param name="withSpace">The SCP number with spaces between. Used by Subtitles.</param> - public static void ConvertScp(string roleName, out string withoutSpace, out string withSpace) => NineTailedFoxAnnouncer.ConvertSCP(roleName, out withoutSpace, out withSpace); + public static void ConvertScp(string roleName, out string withoutSpace, out string withSpace) => CassieScpTerminationAnnouncement.ConvertSCP(roleName, out withoutSpace, out withSpace); + + /// <summary> + /// Calculates duration of message. + /// </summary> + /// <param name="remaining">The remaining message.</param> + /// <param name="modifiers">The playback modifier.</param> + /// <param name="time">The duration of the message.</param> + public static void CalculateDuration(ReadOnlySpan<char> remaining, CassiePlaybackModifiers modifiers, out double time) + { + time = 0; + + if (LineDatabase == null) + { + return; + } + + int index = remaining.IndexOf(' '); + + StringBuilder sb = new(); + + ReadOnlySpan<char> word = index < 0 ? remaining : remaining[..index]; + + foreach (CassieInterpreter inter in CassieTtsAnnouncer.Interpreters) + { + List<CassieInterpreter.Result> results = inter.GetResults(LineDatabase, ref modifiers, word, sb, out bool jobDone); + + time += results.Sum(result => result.Modifiers.GetTimeUntilNextWord(result.Line)); + + if (jobDone) + { + // The interpreter claims there's no need to process the word by other interpreters. + break; + } + } + + if (index < 0) + { + return; + } + + remaining = remaining[(index + 1)..]; + CalculateDuration(remaining, modifiers, out double timeOut); + time += timeOut; + } } \ No newline at end of file diff --git a/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs b/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs index c5eb647a..62a5f027 100644 --- a/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs +++ b/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs @@ -161,7 +161,7 @@ public void PlayAnnouncement(IEnumerable<Player> spawnedPlayers) { if (Base is IAnnouncedWave wave) { - wave.Announcement.PlayAnnouncement(spawnedPlayers.Select(p => p.ReferenceHub).ToList()); + wave.Announcement.PlayAnnouncement(spawnedPlayers.Select(p => p.ReferenceHub).ToList(), wave); } } From c917e2f857565495df9316e7d6eb9c8a7a4f861f Mon Sep 17 00:00:00 2001 From: SlejmUr <slejmur@protonmail.com> Date: Tue, 2 Dec 2025 17:30:54 +0000 Subject: [PATCH 203/215] Add Projectile wrappers --- LabApi/Features/Wrappers/Items/Item.cs | 9 ++- .../Features/Wrappers/Items/SnowballItem.cs | 65 ++++++++++++++++++ LabApi/Features/Wrappers/Pickups/Pickup.cs | 10 +++ .../Projectiles/FlybyDetectorProjectile.cs | 65 ++++++++++++++++++ .../Pickups/Projectiles/Scp2536Projectile.cs | 66 +++++++++++++++++++ .../Projectiles/SingleTrajectoryProjectile.cs | 66 +++++++++++++++++++ .../Pickups/Projectiles/SnowballProjectile.cs | 65 ++++++++++++++++++ 7 files changed, 345 insertions(+), 1 deletion(-) create mode 100644 LabApi/Features/Wrappers/Items/SnowballItem.cs create mode 100644 LabApi/Features/Wrappers/Pickups/Projectiles/FlybyDetectorProjectile.cs create mode 100644 LabApi/Features/Wrappers/Pickups/Projectiles/Scp2536Projectile.cs create mode 100644 LabApi/Features/Wrappers/Pickups/Projectiles/SingleTrajectoryProjectile.cs create mode 100644 LabApi/Features/Wrappers/Pickups/Projectiles/SnowballProjectile.cs diff --git a/LabApi/Features/Wrappers/Items/Item.cs b/LabApi/Features/Wrappers/Items/Item.cs index 50fcf76e..56281c6d 100644 --- a/LabApi/Features/Wrappers/Items/Item.cs +++ b/LabApi/Features/Wrappers/Items/Item.cs @@ -168,6 +168,7 @@ internal static void Initialize() Register<InventorySystem.Items.Firearms.Ammo.AmmoItem>(x => new AmmoItem(x)); Register<BodyArmor>(x => new BodyArmorItem(x)); Register<InventorySystem.Items.ThrowableProjectiles.ThrowableItem>(x => new ThrowableItem(x)); + Register<InventorySystem.Items.ThrowableProjectiles.SnowballItem>(x => new SnowballItem(x)); Register<InventorySystem.Items.Keycards.KeycardItem>(x => new KeycardItem(x)); Register<InventorySystem.Items.Keycards.ChaosKeycardItem>(x => new KeycardItem(x)); Register<InventorySystem.Items.Keycards.SingleUseKeycardItem>(x => new KeycardItem(x)); @@ -255,7 +256,13 @@ protected Item(ItemBase itemBase) if (CanCache) { - Dictionary.Add(itemBase, this); + if (Dictionary.ContainsKey(itemBase)) + { + Console.Logger.InternalError($"Failed to create an item for base: {itemBase}"); + return; + } + + Dictionary[itemBase] = this; SerialsCache[itemBase.ItemSerial] = this; } } diff --git a/LabApi/Features/Wrappers/Items/SnowballItem.cs b/LabApi/Features/Wrappers/Items/SnowballItem.cs new file mode 100644 index 00000000..7d452430 --- /dev/null +++ b/LabApi/Features/Wrappers/Items/SnowballItem.cs @@ -0,0 +1,65 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using BaseSnowballItem = InventorySystem.Items.ThrowableProjectiles.SnowballItem; + +namespace LabApi.Features.Wrappers; + +/// <summary> +/// The wrapper representing <see cref="BaseSnowballItem"/>. +/// </summary> +public class SnowballItem : ThrowableItem +{ + /// <summary> + /// Contains all the cached snowball items, accessible through their <see cref="BaseSnowballItem"/>. + /// </summary> + public static new Dictionary<BaseSnowballItem, SnowballItem> Dictionary { get; } = []; + + /// <summary> + /// A reference to all instances of <see cref="SnowballItem"/>. + /// </summary> + public static new IReadOnlyCollection<SnowballItem> List => Dictionary.Values; + + /// <summary> + /// Gets the snowball item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseSnowballItem"/> was not null. + /// </summary> + /// <param name="baseSnowballItem">The <see cref="Base"/> of the item.</param> + /// <returns>The requested item or null.</returns> + [return: NotNullIfNotNull(nameof(baseSnowballItem))] + public static SnowballItem? Get(BaseSnowballItem? baseSnowballItem) + { + if (baseSnowballItem == null) + { + return null; + } + + return Dictionary.TryGetValue(baseSnowballItem, out SnowballItem item) ? item : (SnowballItem)CreateItemWrapper(baseSnowballItem); + } + + /// <summary> + /// An internal constructor to prevent external instantiation. + /// </summary> + /// <param name="baseThrowableItem">The base <see cref="BaseSnowballItem"/> object.</param> + internal SnowballItem(BaseSnowballItem baseThrowableItem) + : base(baseThrowableItem) + { + Base = baseThrowableItem; + + if (CanCache) + { + Dictionary.Add(baseThrowableItem, this); + } + } + + /// <summary> + /// The base <see cref="BaseSnowballItem"/> object. + /// </summary> + public new BaseSnowballItem Base { get; } + + /// <inheritdoc/> + internal override void OnRemove() + { + base.OnRemove(); + + Dictionary.Remove(Base); + } +} diff --git a/LabApi/Features/Wrappers/Pickups/Pickup.cs b/LabApi/Features/Wrappers/Pickups/Pickup.cs index 814b1435..2d178b79 100644 --- a/LabApi/Features/Wrappers/Pickups/Pickup.cs +++ b/LabApi/Features/Wrappers/Pickups/Pickup.cs @@ -133,6 +133,10 @@ internal static void Initialize() Register<ExplosionGrenade>(n => new ExplosiveGrenadeProjectile(n)); Register((InventorySystem.Items.ThrowableProjectiles.Scp018Projectile n) => new Scp018Projectile(n)); Register((InventorySystem.Items.ThrowableProjectiles.Scp2176Projectile n) => new Scp2176Projectile(n)); + Register((InventorySystem.Items.ThrowableProjectiles.SingleTrajectoryProjectile n) => new SingleTrajectoryProjectile(n)); + Register((InventorySystem.Items.ThrowableProjectiles.FlybyDetectorProjectile n) => new FlybyDetectorProjectile(n)); + Register((InventorySystem.Items.ThrowableProjectiles.Scp2536Projectile n) => new Scp2536Projectile(n)); + Register((InventorySystem.Items.ThrowableProjectiles.SnowballProjectile n) => new SnowballProjectile(n)); Register<InventorySystem.Items.Firearms.Ammo.AmmoPickup>(x => new AmmoPickup(x)); Register<InventorySystem.Items.Armor.BodyArmorPickup>(x => new BodyArmorPickup(x)); @@ -229,6 +233,12 @@ protected Pickup(ItemPickupBase itemPickupBase) if (CanCache) { + if (Dictionary.ContainsKey(itemPickupBase)) + { + Console.Logger.InternalError($"Failed to create a pickup for base: {itemPickupBase}"); + return; + } + Dictionary.Add(itemPickupBase, this); if (itemPickupBase.Info.Serial != 0) diff --git a/LabApi/Features/Wrappers/Pickups/Projectiles/FlybyDetectorProjectile.cs b/LabApi/Features/Wrappers/Pickups/Projectiles/FlybyDetectorProjectile.cs new file mode 100644 index 00000000..3c012784 --- /dev/null +++ b/LabApi/Features/Wrappers/Pickups/Projectiles/FlybyDetectorProjectile.cs @@ -0,0 +1,65 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using BaseFlybyDetectorProjectile = InventorySystem.Items.ThrowableProjectiles.FlybyDetectorProjectile; + +namespace LabApi.Features.Wrappers; + +/// <summary> +/// The wrapper representing <see cref="BaseFlybyDetectorProjectile">pre-calculated player detector trajectory</see>. +/// </summary> +public class FlybyDetectorProjectile : SingleTrajectoryProjectile +{ + /// <summary> + /// Contains all the cached projectiles, accessible through their <see cref="BaseFlybyDetectorProjectile"/>. + /// </summary> + public static new Dictionary<BaseFlybyDetectorProjectile, FlybyDetectorProjectile> Dictionary { get; } = []; + + /// <summary> + /// A reference to all instances of <see cref="Projectile"/>. + /// </summary> + public static new IReadOnlyCollection<FlybyDetectorProjectile> List => Dictionary.Values; + + /// <summary> + /// Gets the projectile wrapper from the <see cref="Dictionary"/> or creates a new if it doesn't exist and the provided <see cref="FlybyDetectorProjectile"/> was not <see langword="null"/>. + /// </summary> + /// <param name="projectile">The <see cref="Base"/> if the projectile.</param> + /// <returns>The requested wrapper or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(projectile))] + public static FlybyDetectorProjectile? Get(BaseFlybyDetectorProjectile? projectile) + { + if (projectile == null) + { + return null; + } + + return Dictionary.TryGetValue(projectile, out FlybyDetectorProjectile wrapper) ? wrapper : (FlybyDetectorProjectile)CreateItemWrapper(projectile); + } + + /// <summary> + /// A protected constructor to prevent external instantiation. + /// </summary> + /// <param name="projectilePickup">The <see cref="BaseFlybyDetectorProjectile"/> of the pickup.</param> + internal FlybyDetectorProjectile(BaseFlybyDetectorProjectile projectilePickup) + : base(projectilePickup) + { + Base = projectilePickup; + + if (CanCache) + { + Dictionary.Add(projectilePickup, this); + } + } + + /// <summary> + /// The <see cref="BaseFlybyDetectorProjectile"/> of the pickup. + /// </summary> + public new BaseFlybyDetectorProjectile Base { get; } + + /// <inheritdoc /> + internal override void OnRemove() + { + base.OnRemove(); + + Dictionary.Remove(Base); + } +} diff --git a/LabApi/Features/Wrappers/Pickups/Projectiles/Scp2536Projectile.cs b/LabApi/Features/Wrappers/Pickups/Projectiles/Scp2536Projectile.cs new file mode 100644 index 00000000..e653ad9c --- /dev/null +++ b/LabApi/Features/Wrappers/Pickups/Projectiles/Scp2536Projectile.cs @@ -0,0 +1,66 @@ +using InventorySystem.Items.ThrowableProjectiles; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using BaseScp2536Projectile = InventorySystem.Items.ThrowableProjectiles.Scp2536Projectile; + +namespace LabApi.Features.Wrappers; + +/// <summary> +/// The wrapper representing <see cref="BaseScp2536Projectile">Scp-2536</see>. +/// </summary> +public class Scp2536Projectile : FlybyDetectorProjectile +{ + /// <summary> + /// Contains all the cached projectiles, accessible through their <see cref="BaseScp2536Projectile"/>. + /// </summary> + public static new Dictionary<BaseScp2536Projectile, Scp2536Projectile> Dictionary { get; } = []; + + /// <summary> + /// A reference to all instances of <see cref="Projectile"/>. + /// </summary> + public static new IReadOnlyCollection<Scp2536Projectile> List => Dictionary.Values; + + /// <summary> + /// Gets the projectile wrapper from the <see cref="Dictionary"/> or creates a new if it doesn't exist and the provided <see cref="Scp2536Projectile"/> was not <see langword="null"/>. + /// </summary> + /// <param name="projectile">The <see cref="Base"/> if the projectile.</param> + /// <returns>The requested wrapper or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(projectile))] + public static Scp2536Projectile? Get(BaseScp2536Projectile? projectile) + { + if (projectile == null) + { + return null; + } + + return Dictionary.TryGetValue(projectile, out Scp2536Projectile wrapper) ? wrapper : (Scp2536Projectile)CreateItemWrapper(projectile); + } + + /// <summary> + /// A protected constructor to prevent external instantiation. + /// </summary> + /// <param name="projectilePickup">The <see cref="ThrownProjectile"/> of the pickup.</param> + internal Scp2536Projectile(BaseScp2536Projectile projectilePickup) + : base(projectilePickup) + { + Base = projectilePickup; + + if (CanCache) + { + Dictionary.Add(projectilePickup, this); + } + } + + /// <summary> + /// The <see cref="BaseScp2536Projectile"/> of the pickup. + /// </summary> + public new BaseScp2536Projectile Base { get; } + + /// <inheritdoc /> + internal override void OnRemove() + { + base.OnRemove(); + + Dictionary.Remove(Base); + } +} diff --git a/LabApi/Features/Wrappers/Pickups/Projectiles/SingleTrajectoryProjectile.cs b/LabApi/Features/Wrappers/Pickups/Projectiles/SingleTrajectoryProjectile.cs new file mode 100644 index 00000000..8e96268b --- /dev/null +++ b/LabApi/Features/Wrappers/Pickups/Projectiles/SingleTrajectoryProjectile.cs @@ -0,0 +1,66 @@ +using InventorySystem.Items.ThrowableProjectiles; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using BaseSingleTrajectoryProjectile = InventorySystem.Items.ThrowableProjectiles.SingleTrajectoryProjectile; + +namespace LabApi.Features.Wrappers; + +/// <summary> +/// The wrapper representing <see cref="BaseSingleTrajectoryProjectile">pre-calculated trajectory</see>. +/// </summary> +public class SingleTrajectoryProjectile : Projectile +{ + /// <summary> + /// Contains all the cached projectiles, accessible through their <see cref="BaseSingleTrajectoryProjectile"/>. + /// </summary> + public static new Dictionary<BaseSingleTrajectoryProjectile, SingleTrajectoryProjectile> Dictionary { get; } = []; + + /// <summary> + /// A reference to all instances of <see cref="Projectile"/>. + /// </summary> + public static new IReadOnlyCollection<SingleTrajectoryProjectile> List => Dictionary.Values; + + /// <summary> + /// Gets the projectile wrapper from the <see cref="Dictionary"/> or creates a new if it doesn't exist and the provided <see cref="ThrownProjectile"/> was not <see langword="null"/>. + /// </summary> + /// <param name="projectile">The <see cref="Base"/> if the projectile.</param> + /// <returns>The requested wrapper or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(projectile))] + public static SingleTrajectoryProjectile? Get(BaseSingleTrajectoryProjectile? projectile) + { + if (projectile == null) + { + return null; + } + + return Dictionary.TryGetValue(projectile, out SingleTrajectoryProjectile wrapper) ? wrapper : (SingleTrajectoryProjectile)CreateItemWrapper(projectile); + } + + /// <summary> + /// A protected constructor to prevent external instantiation. + /// </summary> + /// <param name="projectilePickup">The <see cref="ThrownProjectile"/> of the pickup.</param> + internal SingleTrajectoryProjectile(BaseSingleTrajectoryProjectile projectilePickup) + : base(projectilePickup) + { + Base = projectilePickup; + + if (CanCache) + { + Dictionary.Add(projectilePickup, this); + } + } + + /// <summary> + /// The <see cref="BaseSingleTrajectoryProjectile"/> of the pickup. + /// </summary> + public new BaseSingleTrajectoryProjectile Base { get; } + + /// <inheritdoc /> + internal override void OnRemove() + { + base.OnRemove(); + + Dictionary.Remove(Base); + } +} diff --git a/LabApi/Features/Wrappers/Pickups/Projectiles/SnowballProjectile.cs b/LabApi/Features/Wrappers/Pickups/Projectiles/SnowballProjectile.cs new file mode 100644 index 00000000..6f4265cb --- /dev/null +++ b/LabApi/Features/Wrappers/Pickups/Projectiles/SnowballProjectile.cs @@ -0,0 +1,65 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using BaseSnowballProjectile = InventorySystem.Items.ThrowableProjectiles.SnowballProjectile; + +namespace LabApi.Features.Wrappers; + +/// <summary> +/// The wrapper representing <see cref="BaseSnowballProjectile">snowball projectile</see>. +/// </summary> +public class SnowballProjectile : FlybyDetectorProjectile +{ + /// <summary> + /// Contains all the cached projectiles, accessible through their <see cref="BaseSnowballProjectile"/>. + /// </summary> + public static new Dictionary<BaseSnowballProjectile, SnowballProjectile> Dictionary { get; } = []; + + /// <summary> + /// A reference to all instances of <see cref="Projectile"/>. + /// </summary> + public static new IReadOnlyCollection<SnowballProjectile> List => Dictionary.Values; + + /// <summary> + /// Gets the projectile wrapper from the <see cref="Dictionary"/> or creates a new if it doesn't exist and the provided <see cref="SnowballProjectile"/> was not <see langword="null"/>. + /// </summary> + /// <param name="projectile">The <see cref="Base"/> if the projectile.</param> + /// <returns>The requested wrapper or <see langword="null"/>.</returns> + [return: NotNullIfNotNull(nameof(projectile))] + public static SnowballProjectile? Get(BaseSnowballProjectile? projectile) + { + if (projectile == null) + { + return null; + } + + return Dictionary.TryGetValue(projectile, out SnowballProjectile wrapper) ? wrapper : (SnowballProjectile)CreateItemWrapper(projectile); + } + + /// <summary> + /// A protected constructor to prevent external instantiation. + /// </summary> + /// <param name="projectilePickup">The <see cref="SnowballProjectile"/> of the pickup.</param> + internal SnowballProjectile(BaseSnowballProjectile projectilePickup) + : base(projectilePickup) + { + Base = projectilePickup; + + if (CanCache) + { + Dictionary.Add(projectilePickup, this); + } + } + + /// <summary> + /// The <see cref="BaseSnowballProjectile"/> of the pickup. + /// </summary> + public new BaseSnowballProjectile Base { get; } + + /// <inheritdoc /> + internal override void OnRemove() + { + base.OnRemove(); + + Dictionary.Remove(Base); + } +} From 72a6403d64d0352e09fc552ee918a13b813f09d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20=C5=A0ebesta?= <david.sebesta@post.cz> Date: Fri, 2 Jan 2026 21:53:39 +0100 Subject: [PATCH 204/215] Version bump --- LabApi/LabApi.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LabApi/LabApi.csproj b/LabApi/LabApi.csproj index 24a0b84d..98fff75e 100644 --- a/LabApi/LabApi.csproj +++ b/LabApi/LabApi.csproj @@ -6,7 +6,7 @@ <PlatformTarget>x64</PlatformTarget> <LangVersion>12.0</LangVersion> - <Version>1.1.4.2</Version> + <Version>1.1.4.3</Version> <AssemblyName>LabApi</AssemblyName> <PackageId>Northwood.LabAPI</PackageId> @@ -17,7 +17,7 @@ <PackageProjectUrl>https://www.nuget.org/packages/Northwood.LabAPI/</PackageProjectUrl> <RepositoryUrl>https://github.com/northwood-studios/LabAPI/</RepositoryUrl> <RepositoryType>git</RepositoryType> - <Copyright>© 2025 Northwood Studios</Copyright> + <Copyright>© 2026 Northwood Studios</Copyright> <Nullable>enable</Nullable> <Platforms>AnyCPU</Platforms> From 1d0e238cf0d824696b11ee0692018e1f571bf779 Mon Sep 17 00:00:00 2001 From: SlejmUr <slejmur@protonmail.com> Date: Sat, 3 Jan 2026 20:42:40 +0000 Subject: [PATCH 205/215] Implement MarshmallowItem and Scp021JItem --- LabApi/Features/Wrappers/Items/Item.cs | 2 + .../Wrappers/Items/MarshmallowItem.cs | 66 +++++++++++++++++++ .../Items/Usable/Consumable/Scp021JItem.cs | 66 +++++++++++++++++++ 3 files changed, 134 insertions(+) create mode 100644 LabApi/Features/Wrappers/Items/MarshmallowItem.cs create mode 100644 LabApi/Features/Wrappers/Items/Usable/Consumable/Scp021JItem.cs diff --git a/LabApi/Features/Wrappers/Items/Item.cs b/LabApi/Features/Wrappers/Items/Item.cs index 56281c6d..202ad2fd 100644 --- a/LabApi/Features/Wrappers/Items/Item.cs +++ b/LabApi/Features/Wrappers/Items/Item.cs @@ -146,6 +146,7 @@ internal static void Initialize() Register<Medkit>(x => new MedkitItem(x)); Register<Scp207>(x => new Scp207Item(x)); Register<AntiScp207>(x => new AntiScp207Item(x)); + Register<Scp021J>(x => new Scp021JItem(x)); Register<InventorySystem.Items.Usables.UsableItem>(x => new UsableItem(x)); Register<InventorySystem.Items.Usables.Scp1576.Scp1576Item>(x => new Scp1576Item(x)); @@ -159,6 +160,7 @@ internal static void Initialize() Register<InventorySystem.Items.Jailbird.JailbirdItem>(x => new JailbirdItem(x)); Register<Coin>(x => new CoinItem(x)); + Register<InventorySystem.Items.MarshmallowMan.MarshmallowItem>(x => new MarshmallowItem(x)); Register<InventorySystem.Items.ToggleableLights.ToggleableLightItemBase>(x => new LightItem(x)); Register<InventorySystem.Items.ToggleableLights.Flashlight.FlashlightItem>(x => new FlashlightItem(x)); diff --git a/LabApi/Features/Wrappers/Items/MarshmallowItem.cs b/LabApi/Features/Wrappers/Items/MarshmallowItem.cs new file mode 100644 index 00000000..90ad42e3 --- /dev/null +++ b/LabApi/Features/Wrappers/Items/MarshmallowItem.cs @@ -0,0 +1,66 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using BaseMarshmallowItem = InventorySystem.Items.MarshmallowMan.MarshmallowItem; + +namespace LabApi.Features.Wrappers; + +/// <summary> +/// The wrapper representing <see cref="BaseMarshmallowItem"/>. +/// </summary> +public class MarshmallowItem : Item +{ + /// <summary> + /// Contains all the cached Marshmallow items, accessible through their <see cref="BaseMarshmallowItem"/>. + /// </summary> + public static new Dictionary<BaseMarshmallowItem, MarshmallowItem> Dictionary { get; } = []; + + /// <summary> + /// A reference to all instances of <see cref="MarshmallowItem"/>. + /// </summary> + public static new IReadOnlyCollection<MarshmallowItem> List => Dictionary.Values; + + /// <summary> + /// Gets the SCP-021J item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseMarshmallowItem"/> was not null. + /// </summary> + /// <param name="baseMarshmallowItem">The <see cref="Base"/> of the item.</param> + /// <returns>The requested item or null.</returns> + [return: NotNullIfNotNull(nameof(baseMarshmallowItem))] + public static MarshmallowItem? Get(BaseMarshmallowItem? baseMarshmallowItem) + { + if (baseMarshmallowItem == null) + { + return null; + } + + return Dictionary.TryGetValue(baseMarshmallowItem, out MarshmallowItem item) ? item : (MarshmallowItem)CreateItemWrapper(baseMarshmallowItem); + } + + /// <summary> + /// An internal constructor to prevent external instantiation. + /// </summary> + /// <param name="baseMarshmallowItem">The base <see cref="BaseMarshmallowItem"/> object.</param> + internal MarshmallowItem(BaseMarshmallowItem baseMarshmallowItem) + : base(baseMarshmallowItem) + { + Base = baseMarshmallowItem; + + if (CanCache) + { + Dictionary.Add(baseMarshmallowItem, this); + } + } + + /// <summary> + /// The base <see cref="BaseMarshmallowItem"/> object. + /// </summary> + public new BaseMarshmallowItem Base { get; } + + /// <summary> + /// An internal method to remove itself from the cache when the base object is destroyed. + /// </summary> + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); + } +} diff --git a/LabApi/Features/Wrappers/Items/Usable/Consumable/Scp021JItem.cs b/LabApi/Features/Wrappers/Items/Usable/Consumable/Scp021JItem.cs new file mode 100644 index 00000000..73dd2a3d --- /dev/null +++ b/LabApi/Features/Wrappers/Items/Usable/Consumable/Scp021JItem.cs @@ -0,0 +1,66 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using BaseScp021JItem = InventorySystem.Items.Usables.Scp021J; + +namespace LabApi.Features.Wrappers; + +/// <summary> +/// The wrapper representing <see cref="BaseScp021JItem"/>. +/// </summary> +public class Scp021JItem : ConsumableItem +{ + /// <summary> + /// Contains all the cached SCP-021J items, accessible through their <see cref="BaseScp021JItem"/>. + /// </summary> + public static new Dictionary<BaseScp021JItem, Scp021JItem> Dictionary { get; } = []; + + /// <summary> + /// A reference to all instances of <see cref="Scp021JItem"/>. + /// </summary> + public static new IReadOnlyCollection<Scp021JItem> List => Dictionary.Values; + + /// <summary> + /// Gets the SCP-021J item wrapper from the <see cref="Dictionary"/> or creates a new one if it doesn't exist and the provided <see cref="BaseScp021JItem"/> was not null. + /// </summary> + /// <param name="baseScp021JItem">The <see cref="Base"/> of the item.</param> + /// <returns>The requested item or null.</returns> + [return: NotNullIfNotNull(nameof(baseScp021JItem))] + public static Scp021JItem? Get(BaseScp021JItem? baseScp021JItem) + { + if (baseScp021JItem == null) + { + return null; + } + + return Dictionary.TryGetValue(baseScp021JItem, out Scp021JItem item) ? item : (Scp021JItem)CreateItemWrapper(baseScp021JItem); + } + + /// <summary> + /// An internal constructor to prevent external instantiation. + /// </summary> + /// <param name="baseScp021JItem">The base <see cref="BaseScp021JItem"/> object.</param> + internal Scp021JItem(BaseScp021JItem baseScp021JItem) + : base(baseScp021JItem) + { + Base = baseScp021JItem; + + if (CanCache) + { + Dictionary.Add(baseScp021JItem, this); + } + } + + /// <summary> + /// The base <see cref="BaseScp021JItem"/> object. + /// </summary> + public new BaseScp021JItem Base { get; } + + /// <summary> + /// An internal method to remove itself from the cache when the base object is destroyed. + /// </summary> + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); + } +} From bae22a838e230724f5f722f119f3174de11dfd56 Mon Sep 17 00:00:00 2001 From: SlejmUr <slejmur@protonmail.com> Date: Sat, 10 Jan 2026 08:19:57 +0000 Subject: [PATCH 206/215] Rename Cassie to Announcer --- .../Features/Wrappers/Facility/Announcer.cs | 277 ++++++++++++++++ LabApi/Features/Wrappers/Facility/Cassie.cs | 308 +++++------------- 2 files changed, 355 insertions(+), 230 deletions(-) create mode 100644 LabApi/Features/Wrappers/Facility/Announcer.cs diff --git a/LabApi/Features/Wrappers/Facility/Announcer.cs b/LabApi/Features/Wrappers/Facility/Announcer.cs new file mode 100644 index 00000000..628dc96e --- /dev/null +++ b/LabApi/Features/Wrappers/Facility/Announcer.cs @@ -0,0 +1,277 @@ +using Cassie; +using Cassie.Interpreters; +using NorthwoodLib.Pools; +using PlayerRoles; +using PlayerStatsSystem; +using Respawning.NamingRules; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace LabApi.Features.Wrappers; + +/// <summary> +/// The wrapper for in game CASSIE announcer. +/// </summary> +public static class Announcer +{ + /// <summary> + /// Gets whether CASSIE is currently speaking. + /// </summary> + public static bool IsSpeaking + => CassieAnnouncementDispatcher.CurrentAnnouncement != null; + + /// <summary> + /// Gets the line database for CASSIE. + /// </summary> + public static CassieLineDatabase? LineDatabase + => !CassieTtsAnnouncer.TryGetDatabase(out CassieLineDatabase db) ? null : db; + + /// <summary> + /// Gets all available voice lines for CASSIE. + /// </summary> + public static CassieLine[] AllLines + => LineDatabase ? LineDatabase.AllLines : []; + + /// <summary> + /// Gets all collection names in which voice lines are in. + /// </summary> + public static string[] CollectionNames + => AllLines.Select(static line => line.ApiName).Distinct().ToArray(); + + /// <summary> + /// Checks whether a specified word is valid for CASSIE. + /// <note>String comparison is case-insensitive.</note> + /// </summary> + /// <param name="word">The word to check.</param> + /// <returns>Whether the word is valid.</returns> + public static bool IsValid(string word) + => CollectionNames.Any(line => line.Equals(word, StringComparison.InvariantCultureIgnoreCase)); + + /// <summary> + /// Calculates duration of specific message. + /// </summary> + /// <param name="message">The message.</param> + /// <param name="rawNumber">Raw numbers.</param> + /// <param name="speed">The speed of the cassie talking.</param> + /// <returns>Duration of the specific message in seconds.</returns> + [Obsolete("Use CalculateDuration(string message, CassiePlaybackModifiers playbackModifiers) instead.", true)] + public static float CalculateDuration(string message, bool rawNumber = false, float speed = 1f) + { + CassiePlaybackModifiers playbackModifiers = new() + { + Pitch = speed, + }; + return (float)CalculateDuration(message, playbackModifiers); + } + + /// <summary> + /// Calculates duration of specific message. + /// </summary> + /// <param name="message">The message.</param> + /// <param name="playbackModifiers">The playback modifier.</param> + /// <returns>Duration of the specific message in seconds.</returns> + public static double CalculateDuration(string message, CassiePlaybackModifiers playbackModifiers) + { + CalculateDuration(message, playbackModifiers, out double time); + return time; + } + + /// <summary> + /// Queues a custom announcement. + /// </summary> + /// <param name="message">The sentence CASSIE is supposed to say.</param> + /// <param name="isHeld">Sets a minimal 3-second moment of silence before the announcement. For most cases you wanna keep it true.</param> + /// <param name="isNoisy">Whether the background noises play.</param> + /// <param name="isSubtitles">Show subtitles.</param> + /// <param name="customSubtitles">Custom subtitles to appear instead of the actual message.</param> + [Obsolete("Use Message(string message, string customSubtitles = \"\", bool playBackground = true, float priority = 0f, float glitchScale = 1f) instead.", true)] + public static void Message(string message, bool isHeld = false, bool isNoisy = true, bool isSubtitles = true, string customSubtitles = "") + => Message(message, customSubtitles); + + /// <summary> + /// Queues a custom announcement. + /// </summary> + /// <param name="message">The sentence CASSIE is supposed to say.</param> + /// <param name="customSubtitles">Custom subtitles to play.</param> + /// <param name="playBackground">Should play the background track (bells, noise).</param> + /// <param name="priority">The priority of this message. The higher the value, the earlier it will be dequeued compared to lower-priority announcements.</param> + /// <param name="glitchScale">Intensity of glitches and stutters added before sending to clients.</param> + public static void Message(string message, string customSubtitles = "", bool playBackground = true, float priority = 0f, float glitchScale = 1f) + { + CassieTtsPayload payload = new(message, customSubtitles, playBackground); + Message(payload, priority, glitchScale); + } + + /// <summary> + /// Queues an cassie payload announcement. + /// </summary> + /// <param name="payload">The payload to sent.</param> + /// <param name="priority">The priority of this message. The higher the value, the earlier it will be dequeued compared to lower-priority announcements.</param> + /// <param name="glitchScale">Intensity of glitches and stutters added before sending to clients. Range from 0f to 1f.</param> + public static void Message(CassieTtsPayload payload, float priority = 0f, float glitchScale = 1f) + { + CassieAnnouncement announcement = new(payload, priority, glitchScale); + CassieAnnouncementDispatcher.AddToQueue(announcement); + } + + /// <summary> + /// Plays the custom announcement with chance of 0f to 1f of adding a glitch or jam before each word. Values closer to 1f are higher chances. + /// </summary> + /// <param name="message">The sentence CASSIE is supposed to say.</param> + /// <param name="glitchChance">The chance for glitch sound to be added before each word. Range from 0f to 1f.</param> + /// <param name="jamChance">The chance for jam sound to be added before each word. Range from 0f to 1f.</param> + public static void GlitchyMessage(string message, float glitchChance, float jamChance) + { + message = CassieGlitchifier.Glitchify(message, glitchChance, jamChance); + Message(message, string.Empty, true, 0f, 0f); + } + + /// <summary> + /// Plays the termination announcement of a SCP player. If the specified player does not have an SCP role then nothing is played. + /// </summary> + /// <param name="player">The player who is being terminated as an SCP.</param> + /// <param name="info">Damage handler causing the death of the player.</param> + public static void ScpTermination(Player player, DamageHandlerBase info) + => CassieScpTerminationAnnouncement.AnnounceScpTermination(player.ReferenceHub, info); + + /// <summary> + /// Clears the CASSIE announcements queue. + /// </summary> + public static void Clear() + => CassieAnnouncementDispatcher.ClearAll(); + + /// <summary> + /// Converts player's team into CASSIE-able word. Unit names are converted into NATO_X words, followed by a number. For example "Alpha-5" is converted to "NATO_A 5". + /// </summary> + /// <param name="team">Target team.</param> + /// <param name="unitName">MTF Unit name (for team <see cref="Team.FoundationForces"/>).</param> + /// <returns>Converted name.</returns> + public static string ConvertTeam(Team team, string unitName) + { + string text = "CONTAINMENTUNIT UNKNOWN"; + switch (team) + { + case Team.FoundationForces: + { + if (!NamingRulesManager.TryGetNamingRule(team, out UnitNamingRule unitNamingRule)) + { + return text; + } + + string text2 = unitNamingRule.TranslateToCassie(unitName); + return "CONTAINMENTUNIT " + text2; + } + + case Team.ChaosInsurgency: + return "CHAOSINSURGENCY"; + case Team.Scientists: + return "SCIENCE PERSONNEL"; + case Team.ClassD: + return "CLASSD PERSONNEL"; + default: + return text; + } + } + + /// <summary> + /// Converts number into string. + /// </summary> + /// <param name="num">The number.</param> + /// <returns>Number converted to string.</returns> + public static string ConvertNumber(int num) + { + if (LineDatabase == null) + { + return string.Empty; + } + + NumberInterpreter? numberInterpreter = (NumberInterpreter?)CassieTtsAnnouncer.Interpreters.FirstOrDefault(x => x is NumberInterpreter); + if (numberInterpreter == null) + { + return string.Empty; + } + + string word = num.ToString(); + + CassiePlaybackModifiers cassiePlaybackModifiers = default; + StringBuilder sb = StringBuilderPool.Shared.Rent(); + numberInterpreter.GetResults(LineDatabase, ref cassiePlaybackModifiers, word, sb, out bool halt); + + return StringBuilderPool.Shared.ToStringReturn(sb); + } + + /// <summary> + /// Converts player's <see cref="RoleTypeId"/> into an SCP <b>number</b> identifier. + /// </summary> + /// <param name="role">The target <see cref="RoleTypeId"/>.</param> + /// <param name="withoutSpace">The SCP number without spaces between. Used by CASSIE.</param> + /// <param name="withSpace">The SCP number with spaces between. Used by Subtitles.</param> + public static void ConvertScp(RoleTypeId role, out string withoutSpace, out string withSpace) + => CassieScpTerminationAnnouncement.ConvertSCP(role, out withoutSpace, out withSpace); + + /// <summary> + /// Converts player's role name into an SCP <b>number</b> identifier. + /// </summary> + /// <param name="roleName">The targets role name.</param> + /// <param name="withoutSpace">The SCP number without spaces between. Used by CASSIE.</param> + /// <param name="withSpace">The SCP number with spaces between. Used by Subtitles.</param> + public static void ConvertScp(string roleName, out string withoutSpace, out string withSpace) + => CassieScpTerminationAnnouncement.ConvertSCP(roleName, out withoutSpace, out withSpace); + + /// <summary> + /// Calculates duration of message. + /// </summary> + /// <param name="remaining">The remaining message.</param> + /// <param name="modifiers">The playback modifier.</param> + /// <param name="time">The duration of the message.</param> + public static void CalculateDuration(string remaining, CassiePlaybackModifiers modifiers, out double time) + => CalculateDuration(remaining.AsSpan(), modifiers, out time); + + /// <summary> + /// Calculates duration of message. + /// </summary> + /// <param name="remaining">The remaining message.</param> + /// <param name="modifiers">The playback modifier.</param> + /// <param name="time">The duration of the message.</param> + public static void CalculateDuration(ReadOnlySpan<char> remaining, CassiePlaybackModifiers modifiers, out double time) + { + time = 0; + + if (LineDatabase == null) + { + return; + } + + int index = remaining.IndexOf(' '); + + StringBuilder sb = StringBuilderPool.Shared.Rent(); + + ReadOnlySpan<char> word = index < 0 ? remaining : remaining[..index]; + + foreach (CassieInterpreter inter in CassieTtsAnnouncer.Interpreters) + { + List<CassieInterpreter.Result> results = inter.GetResults(LineDatabase, ref modifiers, word, sb, out bool jobDone); + + time += results.Sum(static result => result.Modifiers.GetTimeUntilNextWord(result.Line)); + + if (jobDone) + { + // The interpreter claims there's no need to process the word by other interpreters. + break; + } + } + + StringBuilderPool.Shared.Return(sb); + + if (index < 0) + { + return; + } + + remaining = remaining[(index + 1)..]; + CalculateDuration(remaining, modifiers, out double timeOut); + time += timeOut; + } +} \ No newline at end of file diff --git a/LabApi/Features/Wrappers/Facility/Cassie.cs b/LabApi/Features/Wrappers/Facility/Cassie.cs index 9e724c2e..e9319d71 100644 --- a/LabApi/Features/Wrappers/Facility/Cassie.cs +++ b/LabApi/Features/Wrappers/Facility/Cassie.cs @@ -1,253 +1,101 @@ using Cassie; -using Cassie.Interpreters; using PlayerRoles; using PlayerStatsSystem; -using Respawning.NamingRules; using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace LabApi.Features.Wrappers; -/// <summary> -/// The wrapper for in game CASSIE announcer. -/// </summary> +/// <inheritdoc cref="Announcer"/> +[Obsolete("Use Announcer instead of Cassie.", true)] public static class Cassie { - /// <summary> - /// Gets whether CASSIE is currently speaking. - /// </summary> - public static bool IsSpeaking => CassieAnnouncementDispatcher.CurrentAnnouncement != null; - - /// <summary> - /// Gets all available voice lines for CASSIE. - /// </summary> - public static CassieLine[] AllLines => !CassieTtsAnnouncer.TryGetDatabase(out CassieLineDatabase db) ? [] : db.AllLines; - - /// <summary> - /// Gets the line database for CASSIE. - /// </summary> - public static CassieLineDatabase? LineDatabase => !CassieTtsAnnouncer.TryGetDatabase(out CassieLineDatabase db) ? null : db; - - /// <summary> - /// Gets all collection names in which voice lines are in. - /// </summary> - public static string[] CollectionNames => AllLines.Select(n => n.ApiName).Distinct().ToArray(); - - /// <summary> - /// Checks whether a specified word is valid for CASSIE. - /// <note>String comparison is case-insensitive.</note> - /// </summary> - /// <param name="word">The word to check.</param> - /// <returns>Whether the word is valid.</returns> - public static bool IsValid(string word) => CollectionNames.Any(line => line.Equals(word, StringComparison.InvariantCultureIgnoreCase)); - - /// <summary> - /// Calculates duration of specific message. - /// </summary> - /// <param name="message">The message.</param> - /// <param name="rawNumber">Raw numbers.</param> - /// <param name="speed">The speed of the cassie talking.</param> - /// <returns>Duration of the specific message in seconds.</returns> - [Obsolete("Use CalculateDuration(string message, CassiePlaybackModifiers playbackModifiers) instead.", true)] + /// <inheritdoc cref="Announcer.IsSpeaking"/> + [Obsolete("Use Announcer.IsSpeaking instead.", true)] + public static bool IsSpeaking + => Announcer.IsSpeaking; + + /// <inheritdoc cref="Announcer.LineDatabase"/> + [Obsolete("Use Announcer.LineDatabase instead.", true)] + public static CassieLineDatabase? LineDatabase + => Announcer.LineDatabase; + + /// <inheritdoc cref="Announcer.AllLines"/> + [Obsolete("Use Announcer.AllLines instead.", true)] + public static CassieLine[] AllLines + => Announcer.AllLines; + + /// <inheritdoc cref="Announcer.CollectionNames"/> + [Obsolete("Use Announcer.CollectionNames instead.", true)] + public static string[] CollectionNames + => Announcer.CollectionNames; + + /// <inheritdoc cref="Announcer.IsValid(string)"/> + [Obsolete("Use Announcer.IsValid(string) instead.", true)] + public static bool IsValid(string word) + => Announcer.IsValid(word); + + /// <inheritdoc cref="Announcer.CalculateDuration(string, bool, float)"/> + [Obsolete("Use Announcer.CalculateDuration(string message, CassiePlaybackModifiers playbackModifiers) instead.", true)] public static float CalculateDuration(string message, bool rawNumber = false, float speed = 1f) - { - CassiePlaybackModifiers playbackModifiers = new() - { - Pitch = speed, - }; - return (float)CalculateDuration(message, playbackModifiers); - } - - /// <summary> - /// Calculates duration of specific message. - /// </summary> - /// <param name="message">The message.</param> - /// <param name="playbackModifiers">The playback modifier.</param> - /// <returns>Duration of the specific message in seconds.</returns> + => Announcer.CalculateDuration(message, rawNumber, speed); + + /// <inheritdoc cref="Announcer.CalculateDuration(string, CassiePlaybackModifiers)"/> + [Obsolete("Use Announcer.CalculateDuration(string, CassiePlaybackModifiers) instead.", true)] public static double CalculateDuration(string message, CassiePlaybackModifiers playbackModifiers) - { - CalculateDuration(message, playbackModifiers, out var time); - return time; - } - - /// <summary> - /// Plays a custom announcement. - /// Queues a custom announcement. - /// </summary> - /// <param name="message">The sentence CASSIE is supposed to say.</param> - /// <param name="isHeld">Sets a minimal 3-second moment of silence before the announcement. For most cases you wanna keep it true.</param> - /// <param name="isNoisy">Whether the background noises play.</param> - /// <param name="isSubtitles">Show subtitles.</param> - /// <param name="customSubtitles">Custom subtitles to appear instead of the actual message.</param> - [Obsolete("Use Message(string message, string customSubtitles = \"\", bool playBackground = true, float priority = 0f, float glitchScale = 1f) instead.", true)] + => Announcer.CalculateDuration(message, playbackModifiers); + + /// <inheritdoc cref="Announcer.Message(string, bool, bool, bool, string)"/> + [Obsolete("Use Announcer.Message(string message, string customSubtitles = \"\", bool playBackground = true, float priority = 0f, float glitchScale = 1f) instead.", true)] public static void Message(string message, bool isHeld = false, bool isNoisy = true, bool isSubtitles = true, string customSubtitles = "") - => Message(message, customSubtitles); - - /// <summary> - /// Queues a custom announcement. - /// </summary> - /// <param name="message">The sentence CASSIE is supposed to say.</param> - /// <param name="customSubtitles">Custom subtitles to play.</param> - /// <param name="playBackground">Should play the background track (bells, noise).</param> - /// <param name="priority">The priority of this message.</param> - /// <param name="glitchScale">Intensity of glitches and stutters added before sending to clients.</param> + => Announcer.Message(message, customSubtitles); + + /// <inheritdoc cref="Announcer.Message(string, string, bool, float, float)"/> + [Obsolete("Use Announcer.Message(string, string, bool, float, float) instead.", true)] public static void Message(string message, string customSubtitles = "", bool playBackground = true, float priority = 0f, float glitchScale = 1f) - { - CassieTtsPayload payload = new(message, customSubtitles, playBackground); - Message(payload, priority, glitchScale); - } - - /// <summary> - /// Queues an cassie payload announcement. - /// </summary> - /// <param name="payload">The payload to sent.</param> - /// <param name="priority">The priority of this message.</param> - /// <param name="glitchScale">Intensity of glitches and stutters added before sending to clients.</param> - public static void Message(CassieTtsPayload payload, float priority = 0f, float glitchScale = 1f) - { - CassieAnnouncement announcement = new(payload, priority, glitchScale); - CassieAnnouncementDispatcher.AddToQueue(announcement); - } - - /// <summary> - /// Plays the custom announcement with chance of 0f to 1f of adding a glitch or jam before each word. Values closer to 1f are higher chances. - /// </summary> - /// <param name="message">The sentence CASSIE is supposed to say.</param> - /// <param name="glitchChance">The chance for glitch sound to be added before each word. Range from 0f to 1f.</param> - /// <param name="jamChance">The chance for jam sound to be added before each word. Range from 0f to 1f.</param> - public static void GlitchyMessage(string message, float glitchChance, float jamChance) => CassieGlitchifier.Glitchify(message, glitchChance, jamChance); - - /// <summary> - /// Plays the termination announcement of a SCP player. If the specified player does not have an SCP role then nothing is played. - /// </summary> - /// <param name="player">The player who is being terminated as an SCP.</param> - /// <param name="info">Damage handler causing the death of the player.</param> - public static void ScpTermination(Player player, DamageHandlerBase info) => CassieScpTerminationAnnouncement.AnnounceScpTermination(player.ReferenceHub, info); - - /// <summary> - /// Clears the CASSIE announcements queue. - /// </summary> - public static void Clear() => CassieAnnouncementDispatcher.ClearAll(); - - /// <summary> - /// Converts player's team into CASSIE-able word. Unit names are converted into NATO_X words, followed by a number. For example "Alpha-5" is converted to "NATO_A 5". - /// </summary> - /// <param name="team">Target team.</param> - /// <param name="unitName">MTF Unit name (for team <see cref="Team.FoundationForces"/>).</param> - /// <returns>Converted name.</returns> - public static string ConvertTeam(Team team, string unitName) - { - string text = "CONTAINMENTUNIT UNKNOWN"; - switch (team) - { - case Team.FoundationForces: - { - if (!NamingRulesManager.TryGetNamingRule(team, out UnitNamingRule unitNamingRule)) - { - return text; - } - - string text2 = unitNamingRule.TranslateToCassie(unitName); - return "CONTAINMENTUNIT " + text2; - } - - case Team.ChaosInsurgency: - return "BY CHAOSINSURGENCY"; - case Team.Scientists: - return "BY SCIENCE PERSONNEL"; - case Team.ClassD: - return "BY CLASSD PERSONNEL"; - default: - return text; - } - } - - /// <summary> - /// Converts number into string. - /// </summary> - /// <param name="num">The number.</param> - /// <returns>Number converted to string.</returns> - public static string ConvertNumber(int num) - { - if (LineDatabase == null) - { - return string.Empty; - } - - NumberInterpreter? numberInterpreter = (NumberInterpreter?)CassieTtsAnnouncer.Interpreters.FirstOrDefault(x => x is NumberInterpreter); - if (numberInterpreter == null) - { - return string.Empty; - } - - string word = num.ToString(); - - CassiePlaybackModifiers cassiePlaybackModifiers = default; - StringBuilder sb = new(); - numberInterpreter.GetResults(LineDatabase, ref cassiePlaybackModifiers, word, sb, out bool halt); - - return sb.ToString(); - } - - /// <summary> - /// Converts player's <see cref="RoleTypeId"/> into an SCP <b>number</b> identifier. - /// </summary> - /// <param name="role">The target <see cref="RoleTypeId"/>.</param> - /// <param name="withoutSpace">The SCP number without spaces between. Used by CASSIE.</param> - /// <param name="withSpace">The SCP number with spaces between. Used by Subtitles.</param> - public static void ConvertScp(RoleTypeId role, out string withoutSpace, out string withSpace) => CassieScpTerminationAnnouncement.ConvertSCP(role, out withoutSpace, out withSpace); - - /// <summary> - /// Converts player's role name into an SCP <b>number</b> identifier. - /// </summary> - /// <param name="roleName">The targets role name.</param> - /// <param name="withoutSpace">The SCP number without spaces between. Used by CASSIE.</param> - /// <param name="withSpace">The SCP number with spaces between. Used by Subtitles.</param> - public static void ConvertScp(string roleName, out string withoutSpace, out string withSpace) => CassieScpTerminationAnnouncement.ConvertSCP(roleName, out withoutSpace, out withSpace); - - /// <summary> - /// Calculates duration of message. - /// </summary> - /// <param name="remaining">The remaining message.</param> - /// <param name="modifiers">The playback modifier.</param> - /// <param name="time">The duration of the message.</param> - public static void CalculateDuration(ReadOnlySpan<char> remaining, CassiePlaybackModifiers modifiers, out double time) - { - time = 0; + => Announcer.Message(message, customSubtitles, playBackground, priority, glitchScale); - if (LineDatabase == null) - { - return; - } + /// <inheritdoc cref="Announcer.Message(CassieTtsPayload, float, float)"/> + [Obsolete("Use Announcer.Message(CassieTtsPayload, float, float) instead.", true)] + public static void Message(CassieTtsPayload payload, float priority = 0f, float glitchScale = 1f) + => Announcer.Message(payload, priority, glitchScale); - int index = remaining.IndexOf(' '); + /// <inheritdoc cref="Announcer.GlitchyMessage(string, float, float)"/> + [Obsolete("Use Announcer.GlitchyMessage(string, float, float) instead.", true)] + public static void GlitchyMessage(string message, float glitchChance, float jamChance) + => Announcer.GlitchyMessage(message, glitchChance, jamChance); - StringBuilder sb = new(); + /// <inheritdoc cref="Announcer.ScpTermination(Player, DamageHandlerBase)"/> + [Obsolete("Use Announcer.ScpTermination(Player, DamageHandlerBase) instead.", true)] + public static void ScpTermination(Player player, DamageHandlerBase info) + => Announcer.ScpTermination(player, info); - ReadOnlySpan<char> word = index < 0 ? remaining : remaining[..index]; + /// <inheritdoc cref="Announcer.Clear()"/> + [Obsolete("Use Announcer.Clear() instead.", true)] + public static void Clear() + => Announcer.Clear(); - foreach (CassieInterpreter inter in CassieTtsAnnouncer.Interpreters) - { - List<CassieInterpreter.Result> results = inter.GetResults(LineDatabase, ref modifiers, word, sb, out bool jobDone); + /// <inheritdoc cref="Announcer.ConvertTeam(Team, string)"/> + [Obsolete("Use Announcer.ConvertTeam(Team, string) instead.", true)] + public static string ConvertTeam(Team team, string unitName) + => Announcer.ConvertTeam(team, unitName); - time += results.Sum(result => result.Modifiers.GetTimeUntilNextWord(result.Line)); + /// <inheritdoc cref="Announcer.ConvertNumber(int)"/> + [Obsolete("Use Announcer.ConvertNumber(int) instead.", true)] + public static string ConvertNumber(int num) + => Announcer.ConvertNumber(num); - if (jobDone) - { - // The interpreter claims there's no need to process the word by other interpreters. - break; - } - } + /// <inheritdoc cref="Announcer.ConvertScp(RoleTypeId, out string, out string)"/> + [Obsolete("Use Announcer.ConvertScp(RoleTypeId, out string, out string) instead.", true)] + public static void ConvertScp(RoleTypeId role, out string withoutSpace, out string withSpace) + => Announcer.ConvertScp(role, out withoutSpace, out withSpace); - if (index < 0) - { - return; - } + /// <inheritdoc cref="Announcer.ConvertScp(string, out string, out string)"/> + [Obsolete("Use Announcer.ConvertScp(string, out string, out string) instead.", true)] + public static void ConvertScp(string roleName, out string withoutSpace, out string withSpace) + => Announcer.ConvertScp(roleName, out withoutSpace, out withSpace); - remaining = remaining[(index + 1)..]; - CalculateDuration(remaining, modifiers, out double timeOut); - time += timeOut; - } + /// <inheritdoc cref="Announcer.CalculateDuration(ReadOnlySpan{char}, CassiePlaybackModifiers, out double)"/> + [Obsolete("Use Announcer.CalculateDuration(ReadOnlySpan{char}, CassiePlaybackModifiers, out double) instead.", true)] + public static void CalculateDuration(ReadOnlySpan<char> remaining, CassiePlaybackModifiers modifiers, out double time) + => Announcer.CalculateDuration(remaining, modifiers, out time); } \ No newline at end of file From 1a0f2e3a4d7ef4906eacba226c93c924ce42ca15 Mon Sep 17 00:00:00 2001 From: Axwabo <axwabo@gmail.com> Date: Sat, 10 Jan 2026 09:20:18 +0100 Subject: [PATCH 207/215] TimedGrenadeProjectile timeOverride behavior docs --- .../Pickups/Projectiles/Grenades/TimedGrenadeProjectile.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/TimedGrenadeProjectile.cs b/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/TimedGrenadeProjectile.cs index c8fda8e8..22071934 100644 --- a/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/TimedGrenadeProjectile.cs +++ b/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/TimedGrenadeProjectile.cs @@ -1,5 +1,4 @@ using Footprinting; -using Hazards; using InventorySystem; using InventorySystem.Items.Pickups; using InventorySystem.Items.ThrowableProjectiles; @@ -57,7 +56,7 @@ public class TimedGrenadeProjectile : Projectile /// <param name="pos">The position to spawn the grenade on.</param> /// <param name="type">Type of the grenade.</param> /// <param name="owner">The player owner of the grenade.</param> - /// <param name="timeOverride">Time override until detonation.</param> + /// <param name="timeOverride">Time override until detonation. A value less than 0 will not change the original fuse time.</param> /// <returns>An active projectile.</returns> public static TimedGrenadeProjectile? SpawnActive(Vector3 pos, ItemType type, Player? owner = null, double timeOverride = -1d) { From 359270c4a6a0d7488900c5ca28cbcd64c5eadd02 Mon Sep 17 00:00:00 2001 From: SlejmUr <slejmur@protonmail.com> Date: Sat, 10 Jan 2026 08:20:38 +0000 Subject: [PATCH 208/215] Fix CheckpointDoor SubDoors return null. --- LabApi/Features/Wrappers/Facility/Doors/Door.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/LabApi/Features/Wrappers/Facility/Doors/Door.cs b/LabApi/Features/Wrappers/Facility/Doors/Door.cs index 8a6fc6c6..03e8e6c5 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/Door.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/Door.cs @@ -269,7 +269,19 @@ protected Door(DoorVariant doorVariant) /// <summary> /// Gets the rooms which have this door. /// </summary> - public Room[] Rooms => Base.Rooms.Select(Room.Get).ToArray()!; + public Room[] Rooms + { + get + { + // Sometimes the Rooms can be null. (When registering checkpoint SubDoors) + if (Base.Rooms == null) + { + return []; + } + + return Base.Rooms.Select(Room.Get).ToArray()!; + } + } /// <summary> /// Gets the zone in which this door is. From dd865f3ca2ef5325563b0acfc7fb0649734d5b45 Mon Sep 17 00:00:00 2001 From: davidsebesta <david.sebesta@post.cz> Date: Sat, 10 Jan 2026 09:34:04 +0100 Subject: [PATCH 209/215] Version push --- LabApi/LabApi.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LabApi/LabApi.csproj b/LabApi/LabApi.csproj index 98fff75e..d25a73be 100644 --- a/LabApi/LabApi.csproj +++ b/LabApi/LabApi.csproj @@ -6,7 +6,7 @@ <PlatformTarget>x64</PlatformTarget> <LangVersion>12.0</LangVersion> - <Version>1.1.4.3</Version> + <Version>1.1.5</Version> <AssemblyName>LabApi</AssemblyName> <PackageId>Northwood.LabAPI</PackageId> From 7fb9f32bb88ddaf42e6004dd84069a24edd664db Mon Sep 17 00:00:00 2001 From: Molly <mollydevel@gmail.com> Date: Sat, 17 Jan 2026 13:02:21 +0200 Subject: [PATCH 210/215] Load plugins from subdirectories recursively Updated the plugin loader to search for DLL files in all subdirectories, not just the top-level directory. This allows plugins to be organized in nested folders. --- LabApi/Loader/PluginLoader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LabApi/Loader/PluginLoader.cs b/LabApi/Loader/PluginLoader.cs index 0e86b10f..29755297 100644 --- a/LabApi/Loader/PluginLoader.cs +++ b/LabApi/Loader/PluginLoader.cs @@ -157,7 +157,7 @@ public static void LoadAllPlugins() if (Directory.Exists(fullPath)) { - LoadPlugins(new DirectoryInfo(fullPath).GetFiles(DllSearchPattern)); + LoadPlugins(new DirectoryInfo(fullPath).GetFiles(DllSearchPattern, SearchOption.AllDirectories)); } } From e464110ca607ee5792ef734c4330a7b42e19194b Mon Sep 17 00:00:00 2001 From: TtroubleTT <121741230+TtroubleTT@users.noreply.github.com> Date: Sat, 17 Jan 2026 03:05:32 -0800 Subject: [PATCH 211/215] Fix player events interfaces --- .../PlayerEvents/PlayerCancelledUsingItemEventArgs.cs | 2 +- .../PlayerEvents/PlayerCancellingUsingItemEventArgs.cs | 2 +- .../PlayerEvents/PlayerChangedRadioRangeEventArgs.cs | 2 +- .../PlayerEvents/PlayerChangingRadioRangeEventArgs.cs | 2 +- .../Arguments/PlayerEvents/PlayerDamagingWindowEventArgs.cs | 2 +- .../PlayerEvents/PlayerDeactivatingGeneratorEventArgs.cs | 2 +- .../Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs | 2 +- .../Arguments/PlayerEvents/PlayerDryFiringWeaponEventArgs.cs | 2 +- .../Arguments/PlayerEvents/PlayerEffectUpdatingEventArgs.cs | 2 +- .../Arguments/PlayerEvents/PlayerFlippingCoinEventArgs.cs | 2 +- .../Arguments/PlayerEvents/PlayerInteractingDoorEventArgs.cs | 2 +- .../Arguments/PlayerEvents/PlayerPlacedBulletHoleEventArgs.cs | 4 +++- .../Arguments/PlayerEvents/PlayerReloadingWeaponEventArgs.cs | 2 +- 13 files changed, 15 insertions(+), 13 deletions(-) diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerCancelledUsingItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerCancelledUsingItemEventArgs.cs index bd5a4c20..751c18b2 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerCancelledUsingItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerCancelledUsingItemEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.CancelledUsingItem"/> event. /// </summary> -public class PlayerCancelledUsingItemEventArgs : EventArgs, IUsableItemEvent +public class PlayerCancelledUsingItemEventArgs : EventArgs, IUsableItemEvent, IPlayerEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerCancelledUsingItemEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerCancellingUsingItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerCancellingUsingItemEventArgs.cs index f088410c..fdbc61d1 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerCancellingUsingItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerCancellingUsingItemEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.CancellingUsingItem"/> event. /// </summary> -public class PlayerCancellingUsingItemEventArgs : EventArgs, IUsableItemEvent, ICancellableEvent +public class PlayerCancellingUsingItemEventArgs : EventArgs, IUsableItemEvent, ICancellableEvent, IPlayerEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerCancellingUsingItemEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangedRadioRangeEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedRadioRangeEventArgs.cs index baafec54..59978c05 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerChangedRadioRangeEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedRadioRangeEventArgs.cs @@ -9,7 +9,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.ChangedRadioRange"/> event. /// </summary> -public class PlayerChangedRadioRangeEventArgs : EventArgs, IRadioItemEvent +public class PlayerChangedRadioRangeEventArgs : EventArgs, IRadioItemEvent, IPlayerEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerChangedRadioRangeEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangingRadioRangeEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingRadioRangeEventArgs.cs index 387e0ca3..d1a848c3 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerChangingRadioRangeEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingRadioRangeEventArgs.cs @@ -9,7 +9,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.ChangingRadioRange"/> event. /// </summary> -public class PlayerChangingRadioRangeEventArgs : EventArgs, IRadioItemEvent, ICancellableEvent +public class PlayerChangingRadioRangeEventArgs : EventArgs, IRadioItemEvent, ICancellableEvent, IPlayerEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerChangingRadioRangeEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingWindowEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingWindowEventArgs.cs index 86fd4a70..a25afb44 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingWindowEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingWindowEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.DamagingWindow"/> event. /// </summary> -public class PlayerDamagingWindowEventArgs : EventArgs, ICancellableEvent +public class PlayerDamagingWindowEventArgs : EventArgs, ICancellableEvent, IPlayerEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerDamagingWindowEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDeactivatingGeneratorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDeactivatingGeneratorEventArgs.cs index 978da2c8..cd9e95fe 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDeactivatingGeneratorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDeactivatingGeneratorEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.DeactivatingGenerator"/> event. /// </summary> -public class PlayerDeactivatingGeneratorEventArgs : EventArgs, IGeneratorEvent, ICancellableEvent +public class PlayerDeactivatingGeneratorEventArgs : EventArgs, IGeneratorEvent, ICancellableEvent, IPlayerEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerDeactivatingGeneratorEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs index 74cca24a..6e0a74cd 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.DroppingItem"/> event. /// </summary> -public class PlayerDroppingItemEventArgs : EventArgs, ICancellableEvent, IItemEvent +public class PlayerDroppingItemEventArgs : EventArgs, ICancellableEvent, IItemEvent, IPlayerEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerDroppingItemEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDryFiringWeaponEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDryFiringWeaponEventArgs.cs index bf5283d7..b2d3a93e 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDryFiringWeaponEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDryFiringWeaponEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.DryFiringWeapon"/> event. /// </summary> -public class PlayerDryFiringWeaponEventArgs : EventArgs, IFirearmItemEvent, ICancellableEvent +public class PlayerDryFiringWeaponEventArgs : EventArgs, IFirearmItemEvent, ICancellableEvent, IPlayerEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerDryFiringWeaponEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerEffectUpdatingEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerEffectUpdatingEventArgs.cs index 9c539679..40d30c2f 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerEffectUpdatingEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerEffectUpdatingEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.UpdatingEffect"/> event. /// </summary> -public class PlayerEffectUpdatingEventArgs : EventArgs, ICancellableEvent +public class PlayerEffectUpdatingEventArgs : EventArgs, ICancellableEvent, IPlayerEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerEffectUpdatingEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerFlippingCoinEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerFlippingCoinEventArgs.cs index 3df5bfd8..16037336 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerFlippingCoinEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerFlippingCoinEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.FlippingCoin"/> event. /// </summary> -public class PlayerFlippingCoinEventArgs : EventArgs, ICancellableEvent, ICoinItemEvent +public class PlayerFlippingCoinEventArgs : EventArgs, ICancellableEvent, ICoinItemEvent, IPlayerEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerFlippingCoinEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingDoorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingDoorEventArgs.cs index f4293733..b08eedf9 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingDoorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingDoorEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.InteractingDoor"/> event. /// </summary> -public class PlayerInteractingDoorEventArgs : EventArgs, IDoorEvent, ICancellableEvent +public class PlayerInteractingDoorEventArgs : EventArgs, IDoorEvent, ICancellableEvent, IPlayerEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerInteractingDoorEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBulletHoleEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBulletHoleEventArgs.cs index 910ac3a7..05f4790a 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBulletHoleEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBulletHoleEventArgs.cs @@ -5,10 +5,12 @@ namespace LabApi.Events.Arguments.PlayerEvents; +using Interfaces; + /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.PlacedBulletHole"/> event. /// </summary> -public class PlayerPlacedBulletHoleEventArgs : EventArgs +public class PlayerPlacedBulletHoleEventArgs : EventArgs, IPlayerEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerPlacedBulletHoleEventArgs"/> class. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerReloadingWeaponEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerReloadingWeaponEventArgs.cs index 061cdb11..94ae6744 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerReloadingWeaponEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerReloadingWeaponEventArgs.cs @@ -8,7 +8,7 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// <summary> /// Represents the arguments for the <see cref="Handlers.PlayerEvents.ReloadingWeapon"/> event. /// </summary> -public class PlayerReloadingWeaponEventArgs : EventArgs, IFirearmItemEvent, ICancellableEvent +public class PlayerReloadingWeaponEventArgs : EventArgs, IFirearmItemEvent, ICancellableEvent, IPlayerEvent { /// <summary> /// Initializes a new instance of the <see cref="PlayerReloadingWeaponEventArgs"/> class. From 4a420a7f9dae58dc26c57a8f9a6028264a11a382 Mon Sep 17 00:00:00 2001 From: Xname <66174882+Xname7@users.noreply.github.com> Date: Mon, 26 Jan 2026 10:57:09 +0100 Subject: [PATCH 212/215] Load dependencies from subdirectories recursively --- LabApi/Loader/PluginLoader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LabApi/Loader/PluginLoader.cs b/LabApi/Loader/PluginLoader.cs index 29755297..04a75ddd 100644 --- a/LabApi/Loader/PluginLoader.cs +++ b/LabApi/Loader/PluginLoader.cs @@ -107,7 +107,7 @@ public static void LoadAllDependencies() Directory.CreateDirectory(fullPath); - LoadDependencies(new DirectoryInfo(fullPath).GetFiles(DllSearchPattern)); + LoadDependencies(new DirectoryInfo(fullPath).GetFiles(DllSearchPattern, SearchOption.AllDirectories)); } } From 1b261cb0d9a43e964399ecadb4feebb459a6c02a Mon Sep 17 00:00:00 2001 From: OMEGA3065 <90201528+OMEGA3065@users.noreply.github.com> Date: Fri, 27 Feb 2026 18:07:15 +0100 Subject: [PATCH 213/215] Adding extra reload-related getters + better CanReload check * Added IsReloading, IsUnloading and IsReloadingOrUnloading getters to the FirearmItem. * Added an extra check to CanReload (FirearmItem) to prevent CanReload from being through even though base game wouldn't allow for reloading to happen --------- Co-authored-by: OMEGA3065 <martin@salstar.sk> --- .../Wrappers/Items/Firearm/FirearmItem.cs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/LabApi/Features/Wrappers/Items/Firearm/FirearmItem.cs b/LabApi/Features/Wrappers/Items/Firearm/FirearmItem.cs index a1f3c798..ed379556 100644 --- a/LabApi/Features/Wrappers/Items/Firearm/FirearmItem.cs +++ b/LabApi/Features/Wrappers/Items/Firearm/FirearmItem.cs @@ -127,15 +127,30 @@ internal FirearmItem(Firearm firearm) /// </summary> public float BaseLength => Base.BaseLength; + /// <summary> + /// Gets whether the player is currently reloading this firearm. + /// </summary> + public bool IsReloading => ReloaderModule.IsReloading; + + /// <summary> + /// Gets whether the player is currently unloading this firearm. + /// </summary> + public bool IsUnloading => ReloaderModule.IsUnloading; + + /// <summary> + /// Gets whether the player is either reloading or unloading this firearm. + /// </summary> + public bool IsReloadingOrUnloading => ReloaderModule.IsReloadingOrUnloading; + /// <summary> /// Gets whether the player can reload this firearm. /// </summary> - public bool CanReload => IReloadUnloadValidatorModule.ValidateReload(Base); + public bool CanReload => IReloadUnloadValidatorModule.ValidateReload(Base) && !IsReloadingOrUnloading; /// <summary> /// Gets whether the player can unload this firearm. /// </summary> - public bool CanUnload => IReloadUnloadValidatorModule.ValidateUnload(Base); + public bool CanUnload => IReloadUnloadValidatorModule.ValidateUnload(Base) && !IsReloadingOrUnloading; /// <summary> /// Gets the firearm's ammo type. From ff4a68c9dbd951f50ed80c1841d03f96542401ff Mon Sep 17 00:00:00 2001 From: Crous <150693998+CCrous@users.noreply.github.com> Date: Tue, 3 Mar 2026 20:01:52 +0800 Subject: [PATCH 214/215] Fixed incorrect TimeLeft setter in RespawnWave * fix TimeLeft wrong * Update LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs Co-authored-by: Axwabo <95743682+Axwabo@users.noreply.github.com> --------- Co-authored-by: Axwabo <95743682+Axwabo@users.noreply.github.com> --- .../Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs b/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs index 62a5f027..04b2cd0a 100644 --- a/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs +++ b/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs @@ -106,7 +106,7 @@ public float Influence public float TimeLeft { get => Base.Timer.TimeLeft; - set => Base.Timer.SetTime(value); + set => Base.Timer.SetTime(Base.Timer.SpawnIntervalSeconds - value); } /// <summary> From 3bd246e92fb56fb3b93bfebb7deee568c1ea4542 Mon Sep 17 00:00:00 2001 From: michcio <89903081+michcio15@users.noreply.github.com> Date: Tue, 3 Mar 2026 13:02:13 +0100 Subject: [PATCH 215/215] Fix IsUsing setter --- LabApi/Features/Wrappers/Items/Usable/UsableItem.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/LabApi/Features/Wrappers/Items/Usable/UsableItem.cs b/LabApi/Features/Wrappers/Items/Usable/UsableItem.cs index 6c3debac..6d45cfad 100644 --- a/LabApi/Features/Wrappers/Items/Usable/UsableItem.cs +++ b/LabApi/Features/Wrappers/Items/Usable/UsableItem.cs @@ -63,7 +63,9 @@ internal UsableItem(BaseUsableItem baseUsableItem) public bool IsUsing { get => Base.IsUsing; - set => Base.IsUsing = value; + set => UsableItemsController.ServerEmulateMessage( + Serial, + value ? StatusMessage.StatusType.Start : StatusMessage.StatusType.Cancel); } /// <summary>