From db60910db5062bf8507cce04a5350768d258e48b Mon Sep 17 00:00:00 2001 From: SrLicht Date: Sat, 24 Aug 2024 16:29:35 -0300 Subject: [PATCH 01/23] QoL * Added ``RoomSpawnPoint`` for spawning things in a room with a offset property. * Now Items will be spawned in the MapGenerated event instead of RoundStart avoiding the micro-log for spawning to many pickups in one frame. * YES YAMATO I USE NULLEABLE --- .../Features/Spawn/RoomSpawnPoint.cs | 58 +++++++++++++++++++ .../Features/Spawn/SpawnProperties.cs | 5 ++ .../API/Features/CustomItem.cs | 8 ++- EXILED/Exiled.CustomItems/CustomItems.cs | 4 +- .../Exiled.CustomItems/Events/RoundHandler.cs | 4 +- 5 files changed, 72 insertions(+), 7 deletions(-) create mode 100644 EXILED/Exiled.API/Features/Spawn/RoomSpawnPoint.cs diff --git a/EXILED/Exiled.API/Features/Spawn/RoomSpawnPoint.cs b/EXILED/Exiled.API/Features/Spawn/RoomSpawnPoint.cs new file mode 100644 index 000000000..3790c312c --- /dev/null +++ b/EXILED/Exiled.API/Features/Spawn/RoomSpawnPoint.cs @@ -0,0 +1,58 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) Exiled Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- +namespace Exiled.API.Features.Spawn +{ + using System; + + using Exiled.API.Enums; + + using UnityEngine; + + using YamlDotNet.Serialization; + + /// + /// Represents a spawn point within a specific room in the game. + /// + public class RoomSpawnPoint : SpawnPoint + { + /// + /// Gets or sets the room type used for this spawn. + /// + public RoomType Room { get; set; } + + /// + /// Gets or sets the offset position within the room where the spawn point is located, relative to the room's origin. + /// + public Vector3? Offset { get; set; } + + /// + public override float Chance { get; set; } + + /// + [YamlIgnore] + public override string Name + { + get => Room.ToString(); + set => throw new InvalidOperationException("The name of this type of SpawnPoint cannot be changed."); + } + + /// + [YamlIgnore] + public override Vector3 Position + { + get + { + Room roomInstance = Features.Room.Get(Room) ?? throw new InvalidOperationException("The room instance could not be found."); + + return Offset.HasValue + ? (roomInstance.Type == RoomType.Surface ? Offset.Value : roomInstance.transform.TransformPoint(Offset.Value)) + : roomInstance.Position; + } + set => throw new InvalidOperationException("The position of this type of SpawnPoint cannot be changed."); + } + } +} diff --git a/EXILED/Exiled.API/Features/Spawn/SpawnProperties.cs b/EXILED/Exiled.API/Features/Spawn/SpawnProperties.cs index ee8ddef4b..bc53233f6 100644 --- a/EXILED/Exiled.API/Features/Spawn/SpawnProperties.cs +++ b/EXILED/Exiled.API/Features/Spawn/SpawnProperties.cs @@ -34,6 +34,11 @@ public class SpawnProperties /// public List RoleSpawnPoints { get; set; } = new(); + /// + /// Gets or sets a of possible room-based spawn points. + /// + public List RoomSpawnPoints { get; set; } = new(); + /// /// Counts how many spawn points are in this instance. /// diff --git a/EXILED/Exiled.CustomItems/API/Features/CustomItem.cs b/EXILED/Exiled.CustomItems/API/Features/CustomItem.cs index 23359d6b0..85a2b142d 100644 --- a/EXILED/Exiled.CustomItems/API/Features/CustomItem.cs +++ b/EXILED/Exiled.CustomItems/API/Features/CustomItem.cs @@ -694,8 +694,8 @@ public virtual void SpawnAll() if (SpawnProperties is null) return; - // This will go over each spawn property type (static, dynamic and role) to try and spawn the item. - // It will attempt to spawn in role-based locations, and then dynamic ones, and finally static. + // This will go over each spawn property type (static, dynamic, role-based, and room-based) to try and spawn the item. + // It will attempt to spawn in role-based locations, then dynamic ones, followed by room-based, and finally static. // Math.Min is used here to ensure that our recursive Spawn() calls do not result in exceeding the spawn limit config. // This is the same as: // int spawned = 0; @@ -703,8 +703,10 @@ public virtual void SpawnAll() // if (spawned < SpawnProperties.Limit) // spawned += Spawn(SpawnProperties.DynamicSpawnPoints, SpawnProperties.Limit - spawned); // if (spawned < SpawnProperties.Limit) + // spawned += Spawn(SpawnProperties.RoomSpawnPoints, SpawnProperties.Limit - spawned); + // if (spawned < SpawnProperties.Limit) // Spawn(SpawnProperties.StaticSpawnPoints, SpawnProperties.Limit - spawned); - Spawn(SpawnProperties.StaticSpawnPoints, Math.Min(0, SpawnProperties.Limit - Math.Min(0, Spawn(SpawnProperties.DynamicSpawnPoints, SpawnProperties.Limit) - Spawn(SpawnProperties.RoleSpawnPoints, SpawnProperties.Limit)))); + Spawn(SpawnProperties.StaticSpawnPoints, Math.Min(SpawnProperties.Limit, SpawnProperties.Limit - Math.Min(Spawn(SpawnProperties.DynamicSpawnPoints, SpawnProperties.Limit), SpawnProperties.Limit - Math.Min(Spawn(SpawnProperties.RoleSpawnPoints, SpawnProperties.Limit), SpawnProperties.Limit - Spawn(SpawnProperties.RoomSpawnPoints, SpawnProperties.Limit))))); } /// diff --git a/EXILED/Exiled.CustomItems/CustomItems.cs b/EXILED/Exiled.CustomItems/CustomItems.cs index 8a8e15b36..eb344762d 100644 --- a/EXILED/Exiled.CustomItems/CustomItems.cs +++ b/EXILED/Exiled.CustomItems/CustomItems.cs @@ -35,7 +35,7 @@ public override void OnEnabled() roundHandler = new RoundHandler(); playerHandler = new PlayerHandler(); - Exiled.Events.Handlers.Server.RoundStarted += roundHandler.OnRoundStarted; + Exiled.Events.Handlers.Map.Generated += roundHandler.OnMapGenerated; Exiled.Events.Handlers.Player.ChangingItem += playerHandler.OnChangingItem; @@ -50,7 +50,7 @@ public override void OnEnabled() /// public override void OnDisabled() { - Exiled.Events.Handlers.Server.RoundStarted -= roundHandler!.OnRoundStarted; + Exiled.Events.Handlers.Map.Generated -= roundHandler!.OnMapGenerated; Exiled.Events.Handlers.Player.ChangingItem -= playerHandler!.OnChangingItem; diff --git a/EXILED/Exiled.CustomItems/Events/RoundHandler.cs b/EXILED/Exiled.CustomItems/Events/RoundHandler.cs index ebc8c4648..65e505c7a 100644 --- a/EXILED/Exiled.CustomItems/Events/RoundHandler.cs +++ b/EXILED/Exiled.CustomItems/Events/RoundHandler.cs @@ -14,8 +14,8 @@ namespace Exiled.CustomItems.Events /// internal sealed class RoundHandler { - /// - public void OnRoundStarted() + /// + public void OnMapGenerated() { foreach (CustomItem customItem in CustomItem.Registered) customItem?.SpawnAll(); From d50425b679fc27894b61a979d637dd17366b25c0 Mon Sep 17 00:00:00 2001 From: SrLicht Date: Sat, 24 Aug 2024 16:53:35 -0300 Subject: [PATCH 02/23] Shut --- EXILED/Exiled.API/Features/Spawn/RoomSpawnPoint.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/EXILED/Exiled.API/Features/Spawn/RoomSpawnPoint.cs b/EXILED/Exiled.API/Features/Spawn/RoomSpawnPoint.cs index 3790c312c..21f50fb9b 100644 --- a/EXILED/Exiled.API/Features/Spawn/RoomSpawnPoint.cs +++ b/EXILED/Exiled.API/Features/Spawn/RoomSpawnPoint.cs @@ -48,9 +48,7 @@ public override Vector3 Position { Room roomInstance = Features.Room.Get(Room) ?? throw new InvalidOperationException("The room instance could not be found."); - return Offset.HasValue - ? (roomInstance.Type == RoomType.Surface ? Offset.Value : roomInstance.transform.TransformPoint(Offset.Value)) - : roomInstance.Position; + return Offset.HasValue ? roomInstance.transform.TransformPoint(Offset.Value) : roomInstance.Position; } set => throw new InvalidOperationException("The position of this type of SpawnPoint cannot be changed."); } From 1ab2c04e1eb3b66ad3cd25b3fd136237bed97a25 Mon Sep 17 00:00:00 2001 From: SrLicht Date: Sun, 25 Aug 2024 22:12:33 -0300 Subject: [PATCH 03/23] Done * Created a Wrapper for Locker * Created LockerSpawnPoint * I NEED HELP FOR IMPLEMENTING SUPPLYLOCKER I DONT FUCKING KNOW HOW MAKE A TRANSPILER * I hate you Yamato :D --- EXILED/Exiled.API/Enums/SpawnLocationType.cs | 4 +- .../Features/Spawn/LockerSpawnPoint.cs | 49 +++++ EXILED/Exiled.API/Features/SupplyLocker.cs | 178 ++++++++++++++++++ 3 files changed, 230 insertions(+), 1 deletion(-) create mode 100644 EXILED/Exiled.API/Features/Spawn/LockerSpawnPoint.cs create mode 100644 EXILED/Exiled.API/Features/SupplyLocker.cs diff --git a/EXILED/Exiled.API/Enums/SpawnLocationType.cs b/EXILED/Exiled.API/Enums/SpawnLocationType.cs index 852e07f43..63568ba3b 100644 --- a/EXILED/Exiled.API/Enums/SpawnLocationType.cs +++ b/EXILED/Exiled.API/Enums/SpawnLocationType.cs @@ -4,9 +4,10 @@ // Licensed under the CC BY-SA 3.0 license. // // ----------------------------------------------------------------------- - namespace Exiled.API.Enums { + using System; + /// /// All of the valid spawn location types. /// @@ -150,6 +151,7 @@ public enum SpawnLocationType /// /// Inside a random locker on the map. /// + [Obsolete("Use LockerSpawnPoint instead")] InsideLocker, } } \ No newline at end of file diff --git a/EXILED/Exiled.API/Features/Spawn/LockerSpawnPoint.cs b/EXILED/Exiled.API/Features/Spawn/LockerSpawnPoint.cs new file mode 100644 index 000000000..f978c4964 --- /dev/null +++ b/EXILED/Exiled.API/Features/Spawn/LockerSpawnPoint.cs @@ -0,0 +1,49 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) Exiled Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- +namespace Exiled.API.Features.Spawn +{ + using System; + using System.Linq; + + using Exiled.API.Enums; + using UnityEngine; + using YamlDotNet.Serialization; + + /// + /// Handles the spawn point inside a locker. + /// + public class LockerSpawnPoint : SpawnPoint + { + /// + /// Gets or sets the zone where the locker is located. + /// + public ZoneType Zone { get; set; } + + /// + public override float Chance { get; set; } + + /// + [YamlIgnore] + public override string Name + { + get => Zone.ToString(); + set => throw new InvalidOperationException("The name of this type of SpawnPoint cannot be changed."); + } + + /// + [YamlIgnore] + public override Vector3 Position + { + get + { + SupplyLocker foundLocker = SupplyLocker.Get(Zone).FirstOrDefault(); + return foundLocker == null ? throw new NullReferenceException("No locker found in the specified zone.") : foundLocker.Position; + } + set => throw new InvalidOperationException("The position of this type of SpawnPoint cannot be changed."); + } + } +} diff --git a/EXILED/Exiled.API/Features/SupplyLocker.cs b/EXILED/Exiled.API/Features/SupplyLocker.cs new file mode 100644 index 000000000..4b3b45849 --- /dev/null +++ b/EXILED/Exiled.API/Features/SupplyLocker.cs @@ -0,0 +1,178 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) Exiled Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- +namespace Exiled.API.Features +{ + using System; + using System.Collections.Generic; + using System.Linq; + + using Exiled.API.Enums; + using Exiled.API.Extensions; + using Exiled.API.Interfaces; + using InventorySystem.Items.Pickups; + using MapGeneration.Distributors; + using Mirror; + using PluginAPI.Core.Items; + using UnityEngine; + +#nullable enable + /// + /// The in-game SupplyLocker. + /// + public class SupplyLocker : IWrapper, IWorldSpace + { + /// + /// A containing all known s and their corresponding . + /// + internal static readonly Dictionary LockerToSupplyLocker = new(250, new ComponentsEqualityComparer()); + + /// + /// Initializes a new instance of the class. + /// + /// The encapsulated . + internal SupplyLocker(Locker locker) + { + Base = locker; + LockerToSupplyLocker.Add(locker, this); + } + + /// + /// Gets a of which contains all the instances. + /// + public static IReadOnlyCollection List => LockerToSupplyLocker.Values; + + /// + /// Gets the instance of the supply locker. + /// + public Locker Base { get; } + + /// + /// Gets the . + /// + public Transform Transform => Base.transform; + + /// + /// Gets the position. + /// + public Vector3 Position => Base.transform.position; + + /// + /// Gets the rotation. + /// + public Quaternion Rotation => Base.transform.rotation; + + /// + /// Gets the in which the is located. + /// + public Room? Room => Room.Get(Position); + + /// + /// Gets the in which the locker is located. + /// + public ZoneType Zone => Room?.Zone ?? ZoneType.Unspecified; + + /// + /// Gets the 's in this . + /// + public IEnumerable Chambers => Base.Chambers; + + /// + /// Gets the who has been open. + /// + public IEnumerable OpenedChambers => Chambers.Where(c => c.IsOpen).ToArray(); + + /// + /// Gets the belonging to the , if any. + /// + /// The to get. + /// A or if not found. + public static SupplyLocker? Get(Locker locker) => locker == null ? null : + LockerToSupplyLocker.TryGetValue(locker, out SupplyLocker supply) ? supply : new SupplyLocker(locker); + + /// + /// Gets a of given the specified . + /// + /// The to search for. + /// The with the given or if not found. + public static IEnumerable Get(ZoneType zoneType) => Get(room => room.Zone.HasFlag(zoneType)); + + /// + /// Gets a of filtered based on a predicate. + /// + /// The condition to satify. + /// A of which contains elements that satify the condition. + public static IEnumerable Get(Func predicate) => List.Where(predicate); + + /// + /// Gets a random . + /// + /// Filters by . + /// object. + public static SupplyLocker Random(ZoneType zoneType = ZoneType.Unspecified) => (zoneType is not ZoneType.Unspecified ? Get(r => r.Zone.HasFlag(zoneType)) : List).GetRandomValue(); + + /// + /// Adds an item to a randomly selected locker chamber. + /// + /// The to be added to the locker chamber. + public void AddItem(ItemPickup item) + { + // Select a random chamber from the available locker chambers. + LockerChamber chamber = Chambers.GetRandomValue(); + + // Determine the parent transform where the item will be placed. + Transform parentTransform = chamber._useMultipleSpawnpoints && chamber._spawnpoints.Length > 0 + ? chamber._spawnpoints.RandomItem() + : chamber._spawnpoint; + + // If the chamber is open, immediately set the item's parent and spawn it. + if (chamber.IsOpen) + { + item.Transform.SetParent(parentTransform); + item.Spawn(); + } + else + { + // If the item is already spawned on the network, unspawn it before proceeding. + if (NetworkServer.spawned.ContainsKey(item.OriginalObject.netId)) + NetworkServer.UnSpawn(item.GameObject); + + // Set the item's parent transform. + item.Transform.SetParent(parentTransform); + + // Lock the item in place. + item.IsLocked = true; + + // Notify any pickup distributor triggers. + (item.OriginalObject as IPickupDistributorTrigger)?.OnDistributed(); + + // If the item has a Rigidbody component, make it kinematic and reset its position and rotation. + if (item.Rigidbody != null) + { + item.Rigidbody.isKinematic = true; + item.Rigidbody.transform.localPosition = Vector3.zero; + item.Rigidbody.transform.localRotation = Quaternion.identity; + + // Add the Rigidbody to the list of bodies to be unfrozen later. + SpawnablesDistributorBase.BodiesToUnfreeze.Add(item.Rigidbody); + } + + // If the chamber is configured to spawn items on the first opening, add the item to the list of items to be spawned. + // Otherwise, spawn the item immediately. + if (chamber._spawnOnFirstChamberOpening) + chamber._toBeSpawned.Add(item.OriginalObject); + else + ItemDistributor.SpawnPickup(item.OriginalObject); + } + } + + /// + /// Spawns an item of the specified to the locker by creating a new . + /// + /// The type of item to be added. + public void AddItem(ItemType type) => AddItem(ItemPickup.Create(type, default, default)); + } +} From 2a81d9a53b0534d7ce10cd4b967b59fbffcaddb5 Mon Sep 17 00:00:00 2001 From: SrLicht Date: Sun, 25 Aug 2024 22:21:40 -0300 Subject: [PATCH 04/23] Boop --- EXILED/Exiled.API/Features/Spawn/SpawnProperties.cs | 7 ++++++- EXILED/Exiled.CustomItems/API/Features/CustomItem.cs | 8 +++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/EXILED/Exiled.API/Features/Spawn/SpawnProperties.cs b/EXILED/Exiled.API/Features/Spawn/SpawnProperties.cs index bc53233f6..4cdf3345b 100644 --- a/EXILED/Exiled.API/Features/Spawn/SpawnProperties.cs +++ b/EXILED/Exiled.API/Features/Spawn/SpawnProperties.cs @@ -39,10 +39,15 @@ public class SpawnProperties /// public List RoomSpawnPoints { get; set; } = new(); + /// + /// Gets or sets a of possible locker-based spawn points. + /// + public List LockerSpawnPoints { get; set; } = new(); + /// /// Counts how many spawn points are in this instance. /// /// How many spawn points there are. - public int Count() => DynamicSpawnPoints.Count + StaticSpawnPoints.Count + RoleSpawnPoints.Count; + public int Count() => DynamicSpawnPoints.Count + StaticSpawnPoints.Count + RoleSpawnPoints.Count + RoomSpawnPoints.Count + LockerSpawnPoints.Count; } } \ No newline at end of file diff --git a/EXILED/Exiled.CustomItems/API/Features/CustomItem.cs b/EXILED/Exiled.CustomItems/API/Features/CustomItem.cs index 85a2b142d..4c049e3ef 100644 --- a/EXILED/Exiled.CustomItems/API/Features/CustomItem.cs +++ b/EXILED/Exiled.CustomItems/API/Features/CustomItem.cs @@ -694,8 +694,8 @@ public virtual void SpawnAll() if (SpawnProperties is null) return; - // This will go over each spawn property type (static, dynamic, role-based, and room-based) to try and spawn the item. - // It will attempt to spawn in role-based locations, then dynamic ones, followed by room-based, and finally static. + // This will go over each spawn property type (static, dynamic, role-based, room-based, and locker-based) to try and spawn the item. + // It will attempt to spawn in role-based locations, then dynamic ones, followed by room-based, locker-based, and finally static. // Math.Min is used here to ensure that our recursive Spawn() calls do not result in exceeding the spawn limit config. // This is the same as: // int spawned = 0; @@ -705,8 +705,10 @@ public virtual void SpawnAll() // if (spawned < SpawnProperties.Limit) // spawned += Spawn(SpawnProperties.RoomSpawnPoints, SpawnProperties.Limit - spawned); // if (spawned < SpawnProperties.Limit) + // spawned += Spawn(SpawnProperties.LockerSpawnPoints, SpawnProperties.Limit - spawned); + // if (spawned < SpawnProperties.Limit) // Spawn(SpawnProperties.StaticSpawnPoints, SpawnProperties.Limit - spawned); - Spawn(SpawnProperties.StaticSpawnPoints, Math.Min(SpawnProperties.Limit, SpawnProperties.Limit - Math.Min(Spawn(SpawnProperties.DynamicSpawnPoints, SpawnProperties.Limit), SpawnProperties.Limit - Math.Min(Spawn(SpawnProperties.RoleSpawnPoints, SpawnProperties.Limit), SpawnProperties.Limit - Spawn(SpawnProperties.RoomSpawnPoints, SpawnProperties.Limit))))); + Spawn(SpawnProperties.StaticSpawnPoints, Math.Min(SpawnProperties.Limit, SpawnProperties.Limit - Math.Min(Spawn(SpawnProperties.DynamicSpawnPoints, SpawnProperties.Limit), SpawnProperties.Limit - Math.Min(Spawn(SpawnProperties.RoleSpawnPoints, SpawnProperties.Limit), SpawnProperties.Limit - Math.Min(Spawn(SpawnProperties.RoomSpawnPoints, SpawnProperties.Limit),SpawnProperties.Limit - Spawn(SpawnProperties.LockerSpawnPoints, SpawnProperties.Limit)))))); } /// From 2342dde92af0b8e10fe3ad72ab274ab26e4ac579 Mon Sep 17 00:00:00 2001 From: SrLicht Date: Mon, 26 Aug 2024 04:29:42 -0300 Subject: [PATCH 05/23] Why Exiled use MONO.POSIX * And dont use the nuget for it :skull: --- EXILED/Exiled.Loader/Exiled.Loader.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/EXILED/Exiled.Loader/Exiled.Loader.csproj b/EXILED/Exiled.Loader/Exiled.Loader.csproj index 4a48187e2..cb3a04e39 100644 --- a/EXILED/Exiled.Loader/Exiled.Loader.csproj +++ b/EXILED/Exiled.Loader/Exiled.Loader.csproj @@ -17,6 +17,7 @@ + From 7e2d32eab488421e8322bc6940a5a543195b7c88 Mon Sep 17 00:00:00 2001 From: SrLicht Date: Mon, 26 Aug 2024 04:35:30 -0300 Subject: [PATCH 06/23] Now it will compile in the page * Removing Else if (spawnPoint is RoleSpawnPoint roleSpawnPoint) since its not necessary spawnpoint.Position does the same. * Supressing CS0618 due the obsolet in SpawnLocationType.InsideLocker. * Note: SpawnLocationType.InsideLocker its only used in CustomItem.SpawnAll() so it will be fine to deleted this in futures releases. * Fixing compile action due the warnings --- EXILED/Exiled.CustomItems/API/Features/CustomItem.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/EXILED/Exiled.CustomItems/API/Features/CustomItem.cs b/EXILED/Exiled.CustomItems/API/Features/CustomItem.cs index 4c049e3ef..1987108eb 100644 --- a/EXILED/Exiled.CustomItems/API/Features/CustomItem.cs +++ b/EXILED/Exiled.CustomItems/API/Features/CustomItem.cs @@ -619,6 +619,7 @@ public virtual uint Spawn(IEnumerable spawnPoints, uint limit) spawned++; +#pragma warning disable CS0618 // Type or member is obsolete \\ TODO: REMOVE THIS if (spawnPoint is DynamicSpawnPoint dynamicSpawnPoint && dynamicSpawnPoint.Location == SpawnLocationType.InsideLocker) { for (int i = 0; i < 50; i++) @@ -666,10 +667,6 @@ public virtual uint Spawn(IEnumerable spawnPoints, uint limit) break; } } - else if (spawnPoint is RoleSpawnPoint roleSpawnPoint) - { - Spawn(roleSpawnPoint.Role.GetRandomSpawnLocation().Position, null); - } else { Pickup? pickup = Spawn(spawnPoint.Position, null); @@ -681,6 +678,7 @@ public virtual uint Spawn(IEnumerable spawnPoints, uint limit) Log.Debug($"Spawned {Name} at {spawnPoint.Position} ({spawnPoint.Name})"); } +#pragma warning restore CS0618 // Type or member is obsolete } return spawned; @@ -708,7 +706,7 @@ public virtual void SpawnAll() // spawned += Spawn(SpawnProperties.LockerSpawnPoints, SpawnProperties.Limit - spawned); // if (spawned < SpawnProperties.Limit) // Spawn(SpawnProperties.StaticSpawnPoints, SpawnProperties.Limit - spawned); - Spawn(SpawnProperties.StaticSpawnPoints, Math.Min(SpawnProperties.Limit, SpawnProperties.Limit - Math.Min(Spawn(SpawnProperties.DynamicSpawnPoints, SpawnProperties.Limit), SpawnProperties.Limit - Math.Min(Spawn(SpawnProperties.RoleSpawnPoints, SpawnProperties.Limit), SpawnProperties.Limit - Math.Min(Spawn(SpawnProperties.RoomSpawnPoints, SpawnProperties.Limit),SpawnProperties.Limit - Spawn(SpawnProperties.LockerSpawnPoints, SpawnProperties.Limit)))))); + Spawn(SpawnProperties.StaticSpawnPoints, Math.Min(SpawnProperties.Limit, SpawnProperties.Limit - Math.Min(Spawn(SpawnProperties.DynamicSpawnPoints, SpawnProperties.Limit), SpawnProperties.Limit - Math.Min(Spawn(SpawnProperties.RoleSpawnPoints, SpawnProperties.Limit), SpawnProperties.Limit - Math.Min(Spawn(SpawnProperties.RoomSpawnPoints, SpawnProperties.Limit), SpawnProperties.Limit - Spawn(SpawnProperties.LockerSpawnPoints, SpawnProperties.Limit)))))); } /// From b57a4cedd0b0ba73608be85ed5d90cc962627051 Mon Sep 17 00:00:00 2001 From: SrLicht Date: Mon, 26 Aug 2024 04:47:41 -0300 Subject: [PATCH 07/23] Adding support for Offset Almost forget about this :P --- EXILED/Exiled.API/Features/Spawn/LockerSpawnPoint.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/EXILED/Exiled.API/Features/Spawn/LockerSpawnPoint.cs b/EXILED/Exiled.API/Features/Spawn/LockerSpawnPoint.cs index f978c4964..76d7d9f4a 100644 --- a/EXILED/Exiled.API/Features/Spawn/LockerSpawnPoint.cs +++ b/EXILED/Exiled.API/Features/Spawn/LockerSpawnPoint.cs @@ -23,6 +23,11 @@ public class LockerSpawnPoint : SpawnPoint /// public ZoneType Zone { get; set; } + /// + /// Gets or sets the offset position within the locker where the spawn point is located, relative to the locker's origin. + /// + public Vector3? Offset { get; set; } + /// public override float Chance { get; set; } @@ -40,8 +45,8 @@ public override Vector3 Position { get { - SupplyLocker foundLocker = SupplyLocker.Get(Zone).FirstOrDefault(); - return foundLocker == null ? throw new NullReferenceException("No locker found in the specified zone.") : foundLocker.Position; + SupplyLocker foundLocker = SupplyLocker.Random(Zone) ?? throw new NullReferenceException("No locker found in the specified zone."); + return Offset.HasValue ? foundLocker.Transform.TransformPoint(Offset.Value) : foundLocker.Position; } set => throw new InvalidOperationException("The position of this type of SpawnPoint cannot be changed."); } From 0ff63f1ce5bfc9d7fa033804d8ac7a129a08c27c Mon Sep 17 00:00:00 2001 From: SrLicht Date: Mon, 26 Aug 2024 05:00:12 -0300 Subject: [PATCH 08/23] Sorry I cant resist adding more things --- .../Features/Spawn/LockerSpawnPoint.cs | 12 +++++++++++ EXILED/Exiled.API/Features/SupplyLocker.cs | 21 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/EXILED/Exiled.API/Features/Spawn/LockerSpawnPoint.cs b/EXILED/Exiled.API/Features/Spawn/LockerSpawnPoint.cs index 76d7d9f4a..216e19ca1 100644 --- a/EXILED/Exiled.API/Features/Spawn/LockerSpawnPoint.cs +++ b/EXILED/Exiled.API/Features/Spawn/LockerSpawnPoint.cs @@ -23,6 +23,12 @@ public class LockerSpawnPoint : SpawnPoint /// public ZoneType Zone { get; set; } + /// + /// Gets or sets a value indicating whether to use a random locker chamber's position for spawning. + /// If , will be ignored. + /// + public bool UseChamber { get; set; } + /// /// Gets or sets the offset position within the locker where the spawn point is located, relative to the locker's origin. /// @@ -46,6 +52,12 @@ public override Vector3 Position get { SupplyLocker foundLocker = SupplyLocker.Random(Zone) ?? throw new NullReferenceException("No locker found in the specified zone."); + + // If UseChamber is true, use a random chamber's position. + if (UseChamber) + return foundLocker.RandomChamberPosition; + + // Otherwise, use the Offset if provided, or the locker's position. return Offset.HasValue ? foundLocker.Transform.TransformPoint(Offset.Value) : foundLocker.Position; } set => throw new InvalidOperationException("The position of this type of SpawnPoint cannot be changed."); diff --git a/EXILED/Exiled.API/Features/SupplyLocker.cs b/EXILED/Exiled.API/Features/SupplyLocker.cs index 4b3b45849..a776f47fa 100644 --- a/EXILED/Exiled.API/Features/SupplyLocker.cs +++ b/EXILED/Exiled.API/Features/SupplyLocker.cs @@ -85,6 +85,27 @@ internal SupplyLocker(Locker locker) /// public IEnumerable OpenedChambers => Chambers.Where(c => c.IsOpen).ToArray(); + /// + /// Gets a random position from one of the . + /// + public Vector3 RandomChamberPosition + { + get + { + LockerChamber randomChamber = Chambers.GetRandomValue(); + + // Determine if the chamber uses multiple spawn points and has at least one available spawn point. + if (randomChamber._useMultipleSpawnpoints && randomChamber._spawnpoints.Length > 0) + { + // Return the position of a random spawn point within the chamber. + return randomChamber._spawnpoints.RandomItem().position; + } + + // Return the position of the main spawn point for the chamber. + return randomChamber._spawnpoint.position; + } + } + /// /// Gets the belonging to the , if any. /// From 7cf5ee05d686587b6e60621e8fc02d07fe202ae0 Mon Sep 17 00:00:00 2001 From: SrLicht Date: Mon, 26 Aug 2024 07:30:56 -0300 Subject: [PATCH 09/23] Adding support for CustomRoles --- EXILED/Exiled.CustomItems/Commands/Info.cs | 11 ++++++++++- EXILED/Exiled.CustomItems/CustomItems.cs | 4 ++-- EXILED/Exiled.CustomRoles/API/Features/CustomRole.cs | 10 ++++++++++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/EXILED/Exiled.CustomItems/Commands/Info.cs b/EXILED/Exiled.CustomItems/Commands/Info.cs index f0de9f1a9..0b6c6e549 100644 --- a/EXILED/Exiled.CustomItems/Commands/Info.cs +++ b/EXILED/Exiled.CustomItems/Commands/Info.cs @@ -68,7 +68,7 @@ public bool Execute(ArraySegment arguments, ICommandSender sender, out s .Append("- ").AppendLine(item?.Description) .AppendLine(item?.Type.ToString()) .Append("- Spawn Limit: ").AppendLine(item?.SpawnProperties?.Limit.ToString()).AppendLine() - .Append("[Spawn Locations (").Append(item?.SpawnProperties?.DynamicSpawnPoints.Count + item?.SpawnProperties?.StaticSpawnPoints.Count).AppendLine(")]"); + .Append("[Spawn Locations (").Append(item?.SpawnProperties?.Count()).AppendLine(")]"); foreach (DynamicSpawnPoint spawnPoint in item?.SpawnProperties?.DynamicSpawnPoints!) message.Append(spawnPoint.Name).Append(' ').Append(spawnPoint.Position).Append(" Chance: ").Append(spawnPoint.Chance).AppendLine("%"); @@ -76,6 +76,15 @@ public bool Execute(ArraySegment arguments, ICommandSender sender, out s foreach (StaticSpawnPoint spawnPoint in item.SpawnProperties.StaticSpawnPoints) message.Append(spawnPoint.Name).Append(' ').Append(spawnPoint.Position).Append(" Chance: ").Append(spawnPoint.Chance).AppendLine("%"); + foreach (RoleSpawnPoint spawnPoint in item.SpawnProperties.RoleSpawnPoints) + message.Append(spawnPoint.Name).Append(' ').Append(spawnPoint.Position).Append(" Chance: ").Append(spawnPoint.Chance).AppendLine("%"); + + foreach (LockerSpawnPoint spawnPoint in item.SpawnProperties.LockerSpawnPoints) + message.Append(spawnPoint.Name).Append(' ').Append(spawnPoint.Position).Append(" Chance: ").Append(spawnPoint.Chance).AppendLine("%"); + + foreach (RoomSpawnPoint spawnPoint in item.SpawnProperties.RoomSpawnPoints) + message.Append(spawnPoint.Name).Append(' ').Append(spawnPoint.Position).Append(" Chance: ").Append(spawnPoint.Chance).AppendLine("%"); + response = StringBuilderPool.Pool.ToStringReturn(message); return true; } diff --git a/EXILED/Exiled.CustomItems/CustomItems.cs b/EXILED/Exiled.CustomItems/CustomItems.cs index eb344762d..855186c00 100644 --- a/EXILED/Exiled.CustomItems/CustomItems.cs +++ b/EXILED/Exiled.CustomItems/CustomItems.cs @@ -19,7 +19,7 @@ namespace Exiled.CustomItems /// public class CustomItems : Plugin { - private RoundHandler? roundHandler; + private MapHandler? roundHandler; private PlayerHandler? playerHandler; private Harmony? harmony; @@ -32,7 +32,7 @@ public class CustomItems : Plugin public override void OnEnabled() { Instance = this; - roundHandler = new RoundHandler(); + roundHandler = new MapHandler(); playerHandler = new PlayerHandler(); Exiled.Events.Handlers.Map.Generated += roundHandler.OnMapGenerated; diff --git a/EXILED/Exiled.CustomRoles/API/Features/CustomRole.cs b/EXILED/Exiled.CustomRoles/API/Features/CustomRole.cs index 61f88ec2c..29151b1f4 100644 --- a/EXILED/Exiled.CustomRoles/API/Features/CustomRole.cs +++ b/EXILED/Exiled.CustomRoles/API/Features/CustomRole.cs @@ -840,6 +840,16 @@ protected Vector3 GetSpawnPosition() } } + if (SpawnProperties.RoomSpawnPoints.Count > 0) + { + foreach ((float chance, Vector3 pos) in SpawnProperties.RoomSpawnPoints) + { + double r = Loader.Random.NextDouble() * 100; + if (r <= chance) + return pos; + } + } + return Vector3.zero; } From 30e3cee3c66bcd812e10b86a72abffd1d45bffc8 Mon Sep 17 00:00:00 2001 From: SrLicht Date: Mon, 26 Aug 2024 18:50:01 -0300 Subject: [PATCH 10/23] Implementing SupplyLocker * I literally copy the generator transpiler * Its works i test it. * Give me my exiled contributor role. --- EXILED/Exiled.API/Features/Map.cs | 9 +-------- .../Features/Spawn/LockerSpawnPoint.cs | 4 ++-- .../Features/Spawn/RoomSpawnPoint.cs | 4 ++-- EXILED/Exiled.API/Features/SupplyLocker.cs | 20 +++++++++++++++++++ .../Events/{RoundHandler.cs => MapHandler.cs} | 12 +++++++---- .../Handlers/Internal/MapGenerated.cs | 1 + .../Patches/Generic/LockerList.cs | 6 +++--- 7 files changed, 37 insertions(+), 19 deletions(-) rename EXILED/Exiled.CustomItems/Events/{RoundHandler.cs => MapHandler.cs} (60%) diff --git a/EXILED/Exiled.API/Features/Map.cs b/EXILED/Exiled.API/Features/Map.cs index 2b3c4cdb0..05e5007a4 100644 --- a/EXILED/Exiled.API/Features/Map.cs +++ b/EXILED/Exiled.API/Features/Map.cs @@ -42,11 +42,6 @@ namespace Exiled.API.Features /// public static class Map { - /// - /// A list of s on the map. - /// - internal static readonly List LockersValue = new(35); - /// /// A list of s on the map. /// @@ -86,7 +81,7 @@ DecontaminationController.Singleton.NetworkDecontaminationOverride is Decontamin /// /// Gets all objects. /// - public static ReadOnlyCollection Lockers { get; } = LockersValue.AsReadOnly(); + public static ReadOnlyCollection Lockers { get; } = SupplyLocker.LockerToSupplyLocker.Keys.ToList().AsReadOnly(); /// /// Gets all objects. @@ -389,8 +384,6 @@ internal static void ClearCache() { Item.BaseToItem.Clear(); - LockersValue.RemoveAll(locker => locker == null); - Ragdoll.BasicRagdollToRagdoll.Clear(); Items.Firearm.ItemTypeToFirearmInstance.Clear(); diff --git a/EXILED/Exiled.API/Features/Spawn/LockerSpawnPoint.cs b/EXILED/Exiled.API/Features/Spawn/LockerSpawnPoint.cs index 216e19ca1..155be3a7b 100644 --- a/EXILED/Exiled.API/Features/Spawn/LockerSpawnPoint.cs +++ b/EXILED/Exiled.API/Features/Spawn/LockerSpawnPoint.cs @@ -32,7 +32,7 @@ public class LockerSpawnPoint : SpawnPoint /// /// Gets or sets the offset position within the locker where the spawn point is located, relative to the locker's origin. /// - public Vector3? Offset { get; set; } + public Vector3 Offset { get; set; } = Vector3.zero; /// public override float Chance { get; set; } @@ -58,7 +58,7 @@ public override Vector3 Position return foundLocker.RandomChamberPosition; // Otherwise, use the Offset if provided, or the locker's position. - return Offset.HasValue ? foundLocker.Transform.TransformPoint(Offset.Value) : foundLocker.Position; + return Offset != Vector3.zero ? foundLocker.Transform.TransformPoint(Offset) : foundLocker.Position; } set => throw new InvalidOperationException("The position of this type of SpawnPoint cannot be changed."); } diff --git a/EXILED/Exiled.API/Features/Spawn/RoomSpawnPoint.cs b/EXILED/Exiled.API/Features/Spawn/RoomSpawnPoint.cs index 21f50fb9b..92e24e712 100644 --- a/EXILED/Exiled.API/Features/Spawn/RoomSpawnPoint.cs +++ b/EXILED/Exiled.API/Features/Spawn/RoomSpawnPoint.cs @@ -27,7 +27,7 @@ public class RoomSpawnPoint : SpawnPoint /// /// Gets or sets the offset position within the room where the spawn point is located, relative to the room's origin. /// - public Vector3? Offset { get; set; } + public Vector3 Offset { get; set; } = Vector3.zero; /// public override float Chance { get; set; } @@ -48,7 +48,7 @@ public override Vector3 Position { Room roomInstance = Features.Room.Get(Room) ?? throw new InvalidOperationException("The room instance could not be found."); - return Offset.HasValue ? roomInstance.transform.TransformPoint(Offset.Value) : roomInstance.Position; + return Offset != Vector3.zero ? roomInstance.transform.TransformPoint(Offset) : roomInstance.Position; } set => throw new InvalidOperationException("The position of this type of SpawnPoint cannot be changed."); } diff --git a/EXILED/Exiled.API/Features/SupplyLocker.cs b/EXILED/Exiled.API/Features/SupplyLocker.cs index a776f47fa..157c45ee9 100644 --- a/EXILED/Exiled.API/Features/SupplyLocker.cs +++ b/EXILED/Exiled.API/Features/SupplyLocker.cs @@ -9,6 +9,7 @@ namespace Exiled.API.Features using System; using System.Collections.Generic; using System.Linq; + using System.Reflection; using Exiled.API.Enums; using Exiled.API.Extensions; @@ -195,5 +196,24 @@ public void AddItem(ItemPickup item) /// /// The type of item to be added. public void AddItem(ItemType type) => AddItem(ItemPickup.Create(type, default, default)); + + /// + /// Clears the cached lockers in the dictionary that have become invalid. + /// This method identifies and removes all entries where either the key (a instance) + /// or the value (a instance) is null, ensuring that only valid references + /// are kept in the cache. + /// + internal static void ClearCache() + { + List keysToRemove = LockerToSupplyLocker + .Where(kv => kv.Key == null || kv.Value == null) + .Select(kv => kv.Key) + .ToList(); + + foreach (Locker key in keysToRemove) + { + LockerToSupplyLocker.Remove(key); + } + } } } diff --git a/EXILED/Exiled.CustomItems/Events/RoundHandler.cs b/EXILED/Exiled.CustomItems/Events/MapHandler.cs similarity index 60% rename from EXILED/Exiled.CustomItems/Events/RoundHandler.cs rename to EXILED/Exiled.CustomItems/Events/MapHandler.cs index 65e505c7a..8d9ca2708 100644 --- a/EXILED/Exiled.CustomItems/Events/RoundHandler.cs +++ b/EXILED/Exiled.CustomItems/Events/MapHandler.cs @@ -1,5 +1,5 @@ // ----------------------------------------------------------------------- -// +// // Copyright (c) Exiled Team. All rights reserved. // Licensed under the CC BY-SA 3.0 license. // @@ -8,17 +8,21 @@ namespace Exiled.CustomItems.Events { using Exiled.CustomItems.API.Features; + using MEC; /// /// Event Handlers for the CustomItem API. /// - internal sealed class RoundHandler + internal sealed class MapHandler { /// public void OnMapGenerated() { - foreach (CustomItem customItem in CustomItem.Registered) - customItem?.SpawnAll(); + Timing.CallDelayed(1, () => // Delay its necessary for the spawnpoints of lockers and rooms to be generated. + { + foreach (CustomItem customItem in CustomItem.Registered) + customItem?.SpawnAll(); + }); } } } \ No newline at end of file diff --git a/EXILED/Exiled.Events/Handlers/Internal/MapGenerated.cs b/EXILED/Exiled.Events/Handlers/Internal/MapGenerated.cs index f75f2e91f..1bbcc5ddb 100644 --- a/EXILED/Exiled.Events/Handlers/Internal/MapGenerated.cs +++ b/EXILED/Exiled.Events/Handlers/Internal/MapGenerated.cs @@ -47,6 +47,7 @@ public static void OnMapGenerated() { Map.ClearCache(); PrefabHelper.LoadPrefabs(); + SupplyLocker.ClearCache(); // TODO: Fix For (https://git.scpslgame.com/northwood-qa/scpsl-bug-reporting/-/issues/377) PlayerRoles.RoleAssign.HumanSpawner.Handlers[PlayerRoles.Team.ChaosInsurgency] = new PlayerRoles.RoleAssign.OneRoleHumanSpawner(PlayerRoles.RoleTypeId.ChaosConscript); diff --git a/EXILED/Exiled.Events/Patches/Generic/LockerList.cs b/EXILED/Exiled.Events/Patches/Generic/LockerList.cs index 26b0732ab..a4491f5c3 100644 --- a/EXILED/Exiled.Events/Patches/Generic/LockerList.cs +++ b/EXILED/Exiled.Events/Patches/Generic/LockerList.cs @@ -29,14 +29,14 @@ private static IEnumerable Transpiler(IEnumerable newInstructions = ListPool.Pool.Get(codeInstructions); - // Map.LockersValue.Add(this); + // new SupplyLocker(this) newInstructions.InsertRange( 0, new CodeInstruction[] { - new(OpCodes.Ldsfld, Field(typeof(Map), nameof(Map.LockersValue))), new(OpCodes.Ldarg_0), - new(OpCodes.Callvirt, Method(typeof(List), nameof(List.Add), new[] { typeof(Locker) })), + new(OpCodes.Newobj, GetDeclaredConstructors(typeof(SupplyLocker))[0]), + new(OpCodes.Pop), }); for (int z = 0; z < newInstructions.Count; z++) From f2a2141f033694e66d9eb575e5f2bdd03b233946 Mon Sep 17 00:00:00 2001 From: SrLicht Date: Mon, 26 Aug 2024 20:43:41 -0300 Subject: [PATCH 11/23] LockerType enum * Code part of the code has been taken from MER (https://github.com/Michal78900/MapEditorReborn/blob/dev/MapEditorReborn/API/Extensions/LockerExtensions.cs) - Credits to Michal, i ask him i can use it, not answer yet but if the say no i will use another way. * SupplyLocker now have a LockerType Property to know what type of Locker is * LockerSpawnPoint can now chose what locker want to use --- EXILED/Exiled.API/Enums/LockerType.cs | 50 +++++++++++++++++++ .../Exiled.API/Extensions/LockerExtensions.cs | 43 ++++++++++++++++ .../Features/Spawn/LockerSpawnPoint.cs | 9 +++- EXILED/Exiled.API/Features/SupplyLocker.cs | 27 ++++++++-- 4 files changed, 123 insertions(+), 6 deletions(-) create mode 100644 EXILED/Exiled.API/Enums/LockerType.cs create mode 100644 EXILED/Exiled.API/Extensions/LockerExtensions.cs diff --git a/EXILED/Exiled.API/Enums/LockerType.cs b/EXILED/Exiled.API/Enums/LockerType.cs new file mode 100644 index 000000000..7b65dfd18 --- /dev/null +++ b/EXILED/Exiled.API/Enums/LockerType.cs @@ -0,0 +1,50 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) Exiled Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- + +namespace Exiled.API.Enums +{ + /// + /// Unique identifier for different types of s. + /// + public enum LockerType + { + /// + /// The pedestal used by SCPs. + /// + Pedestal, + + /// + /// Large weapon locker. + /// + LargeGun, + + /// + /// Locker for rifles, known as a rifle rack. + /// + RifleRack, + + /// + /// Miscellaneous locker for various items. + /// + Misc, + + /// + /// Locker that contains medkits. + /// + Medkit, + + /// + /// Locker that contains adrenaline. + /// + Adrenaline, + + /// + /// Unknow type of locker. + /// + Unknow + } +} diff --git a/EXILED/Exiled.API/Extensions/LockerExtensions.cs b/EXILED/Exiled.API/Extensions/LockerExtensions.cs new file mode 100644 index 000000000..7304cbd4e --- /dev/null +++ b/EXILED/Exiled.API/Extensions/LockerExtensions.cs @@ -0,0 +1,43 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) Exiled Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- + +namespace Exiled.API.Extensions +{ + using System; + + using Exiled.API.Enums; + using MapGeneration.Distributors; + + /// + /// A set of extensions for . + /// + public static class LockerExtensions + { + /// + /// Gets the from the given object. + /// + /// The to check. + /// The corresponding . + public static LockerType GetLockerType(this Locker locker) => locker.name.GetLockerTypeByName(); + + /// + /// Gets the by name. + /// + /// The name to check. + /// The corresponding . + public static LockerType GetLockerTypeByName(this string name) => name.Replace("(Clone)", string.Empty) switch + { + "Scp500PedestalStructure Variant" => LockerType.Pedestal, + "LargeGunLockerStructure" => LockerType.LargeGun, + "RifleRackStructure" => LockerType.RifleRack, + "MiscLocker" => LockerType.Misc, + "RegularMedkitStructure" => LockerType.Medkit, + "AdrenalineMedkitStructure" => LockerType.Adrenaline, + _ => LockerType.Unknow, + }; + } +} diff --git a/EXILED/Exiled.API/Features/Spawn/LockerSpawnPoint.cs b/EXILED/Exiled.API/Features/Spawn/LockerSpawnPoint.cs index 155be3a7b..84579e227 100644 --- a/EXILED/Exiled.API/Features/Spawn/LockerSpawnPoint.cs +++ b/EXILED/Exiled.API/Features/Spawn/LockerSpawnPoint.cs @@ -21,7 +21,7 @@ public class LockerSpawnPoint : SpawnPoint /// /// Gets or sets the zone where the locker is located. /// - public ZoneType Zone { get; set; } + public ZoneType Zone { get; set; } = ZoneType.Unspecified; /// /// Gets or sets a value indicating whether to use a random locker chamber's position for spawning. @@ -34,6 +34,11 @@ public class LockerSpawnPoint : SpawnPoint /// public Vector3 Offset { get; set; } = Vector3.zero; + /// + /// Gets or sets the type of the . + /// + public LockerType Type { get; set; } = LockerType.Unknow; + /// public override float Chance { get; set; } @@ -51,7 +56,7 @@ public override Vector3 Position { get { - SupplyLocker foundLocker = SupplyLocker.Random(Zone) ?? throw new NullReferenceException("No locker found in the specified zone."); + SupplyLocker foundLocker = SupplyLocker.Random(Zone, Type) ?? throw new NullReferenceException("No locker found in the specified zone."); // If UseChamber is true, use a random chamber's position. if (UseChamber) diff --git a/EXILED/Exiled.API/Features/SupplyLocker.cs b/EXILED/Exiled.API/Features/SupplyLocker.cs index 157c45ee9..e72deb7b7 100644 --- a/EXILED/Exiled.API/Features/SupplyLocker.cs +++ b/EXILED/Exiled.API/Features/SupplyLocker.cs @@ -39,6 +39,7 @@ internal SupplyLocker(Locker locker) { Base = locker; LockerToSupplyLocker.Add(locker, this); + Type = locker.GetLockerType(); } /// @@ -51,6 +52,12 @@ internal SupplyLocker(Locker locker) /// public Locker Base { get; } + + /// + /// Gets the of the . + /// + public LockerType Type { get; } + /// /// Gets the . /// @@ -130,11 +137,23 @@ public Vector3 RandomChamberPosition public static IEnumerable Get(Func predicate) => List.Where(predicate); /// - /// Gets a random . + /// Gets a random based on the specified filters. /// - /// Filters by . - /// object. - public static SupplyLocker Random(ZoneType zoneType = ZoneType.Unspecified) => (zoneType is not ZoneType.Unspecified ? Get(r => r.Zone.HasFlag(zoneType)) : List).GetRandomValue(); + /// The to filter by. If unspecified, all zones are considered. + /// The to filter by. If unspecified, all locker types are considered. + /// A random object, or null if no matching locker is found. + public static SupplyLocker? Random(ZoneType zone = ZoneType.Unspecified, LockerType lockerType = LockerType.Unknow) + { + IEnumerable filteredLockers = List; + + if (lockerType != LockerType.Unknow) + filteredLockers = filteredLockers.Where(l => l.Type == lockerType); + + if (zone != ZoneType.Unspecified) + filteredLockers = filteredLockers.Where(l => l.Zone == zone); + + return filteredLockers.GetRandomValue(); + } /// /// Adds an item to a randomly selected locker chamber. From 0edfb01ed3620827ee61e6cd1edde400c3424e7b Mon Sep 17 00:00:00 2001 From: SrLicht Date: Mon, 26 Aug 2024 20:46:39 -0300 Subject: [PATCH 12/23] Mimimi warnings --- EXILED/Exiled.API/Enums/LockerType.cs | 2 +- EXILED/Exiled.API/Features/SupplyLocker.cs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/EXILED/Exiled.API/Enums/LockerType.cs b/EXILED/Exiled.API/Enums/LockerType.cs index 7b65dfd18..d960514ac 100644 --- a/EXILED/Exiled.API/Enums/LockerType.cs +++ b/EXILED/Exiled.API/Enums/LockerType.cs @@ -45,6 +45,6 @@ public enum LockerType /// /// Unknow type of locker. /// - Unknow + Unknow, } } diff --git a/EXILED/Exiled.API/Features/SupplyLocker.cs b/EXILED/Exiled.API/Features/SupplyLocker.cs index e72deb7b7..b3bdd538a 100644 --- a/EXILED/Exiled.API/Features/SupplyLocker.cs +++ b/EXILED/Exiled.API/Features/SupplyLocker.cs @@ -52,7 +52,6 @@ internal SupplyLocker(Locker locker) /// public Locker Base { get; } - /// /// Gets the of the . /// From dd26c8511af386fd4e8100af2de744036f6b8c16 Mon Sep 17 00:00:00 2001 From: SrLicht Date: Tue, 27 Aug 2024 06:36:21 -0300 Subject: [PATCH 13/23] Re-implementing Locker API * Re-implementing locker api of https://github.com/Exiled-Team/EXILED/pull/2026 --- EXILED/Exiled.API/Enums/LockerType.cs | 2 +- EXILED/Exiled.API/Features/Lockers/Chamber.cs | 173 ++++++++++++++++++ .../{SupplyLocker.cs => Lockers/Locker.cs} | 146 +++++++-------- EXILED/Exiled.API/Features/Map.cs | 11 +- .../Features/Spawn/LockerSpawnPoint.cs | 5 +- .../Handlers/Internal/MapGenerated.cs | 4 +- .../Patches/Generic/LockerList.cs | 10 +- 7 files changed, 259 insertions(+), 92 deletions(-) create mode 100644 EXILED/Exiled.API/Features/Lockers/Chamber.cs rename EXILED/Exiled.API/Features/{SupplyLocker.cs => Lockers/Locker.cs} (50%) diff --git a/EXILED/Exiled.API/Enums/LockerType.cs b/EXILED/Exiled.API/Enums/LockerType.cs index d960514ac..6b21f699c 100644 --- a/EXILED/Exiled.API/Enums/LockerType.cs +++ b/EXILED/Exiled.API/Enums/LockerType.cs @@ -8,7 +8,7 @@ namespace Exiled.API.Enums { /// - /// Unique identifier for different types of s. + /// Unique identifier for different types of s. /// public enum LockerType { diff --git a/EXILED/Exiled.API/Features/Lockers/Chamber.cs b/EXILED/Exiled.API/Features/Lockers/Chamber.cs new file mode 100644 index 000000000..c6bae8c8c --- /dev/null +++ b/EXILED/Exiled.API/Features/Lockers/Chamber.cs @@ -0,0 +1,173 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) Exiled Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- +namespace Exiled.API.Features.Lockers +{ + using System.Collections.Generic; + using System.Diagnostics; + using System.Linq; + + using Exiled.API.Enums; + using Exiled.API.Features.Pickups; + using Exiled.API.Interfaces; + using MapGeneration.Distributors; + using UnityEngine; + + /// + /// A wrapper for . + /// + public class Chamber : IWrapper, IWorldSpace + { + /// + /// with and . + /// + internal static readonly Dictionary Chambers = new(); + + /// + /// Initializes a new instance of the class. + /// + /// instance. + /// where this chamber is located. + public Chamber(LockerChamber chamber, Locker locker) + { + Base = chamber; + Locker = locker; + + Chambers.Add(chamber, this); + } + + /// + /// Gets a of which contains all the instances. + /// + public static IReadOnlyCollection List => Chambers.Values; + + /// + public LockerChamber Base { get; } + + /// + /// Gets the where this chamber is located at. + /// + public Locker Locker { get; } + + /// + public Vector3 Position => Base.transform.position; + + /// + public Quaternion Rotation => Base.transform.rotation; + + /// + /// Gets or sets all pickups that should be spawned when the door is initially opened. + /// + public IEnumerable ToBeSpawned + { + get => Base._toBeSpawned.Select(Pickup.Get); + set + { + Base._toBeSpawned.Clear(); + + foreach (Pickup pickup in value) + Base._toBeSpawned.Add(pickup.Base); + } + } + + /// + /// Gets or sets all spawn points. + /// + /// + /// Used if is set to . + /// + public IEnumerable Spawnpoints + { + get => Base._spawnpoints; + set => Base._spawnpoints = value.ToArray(); + } + + /// + /// Gets or sets all the acceptable items which can be spawned in this chamber. + /// + public IEnumerable AcceptableTypes + { + get => Base.AcceptableItems; + set => Base.AcceptableItems = value.ToArray(); + } + + /// + /// Gets or sets required permissions to open this chamber. + /// + public KeycardPermissions RequiredPermissions + { + get => (KeycardPermissions)Base.RequiredPermissions; + set => Base.RequiredPermissions = (Interactables.Interobjects.DoorUtils.KeycardPermissions)value; + } + + /// + /// Gets or sets a value indicating whether multiple spawn points should be used. + /// + /// + /// If , will be used over . + /// + public bool UseMultipleSpawnpoints + { + get => Base._useMultipleSpawnpoints; + set => Base._useMultipleSpawnpoints = value; + } + + /// + /// Gets or sets a spawn point for the items in the chamber. + /// + /// + /// Used if is set to . + /// + public Transform Spawnpoint + { + get => Base._spawnpoint; + set => Base._spawnpoint = value; + } + + /// + /// Gets or sets a value indicating whether or not items should be spawned as soon as they one chamber is opened. + /// + public bool InitiallySpawn + { + get => Base._spawnOnFirstChamberOpening; + set => Base._spawnOnFirstChamberOpening = value; + } + + /// + /// Gets or sets the amount of time before a player can interact with the chamber again. + /// + public float Cooldown + { + get => Base._targetCooldown; + set => Base._targetCooldown = value; + } + + /// + /// Gets the of current cooldown. + /// + /// Used in check. + public Stopwatch CurrentCooldown => Base._stopwatch; + + /// + /// Gets a value indicating whether the chamber is interactable. + /// + public bool CanInteract => Base.CanInteract; + + /// + /// Spawns a specified item from . + /// + /// from . + /// Amount of items that should be spawned. + public void SpawnItem(ItemType type, int amount) => Base.SpawnItem(type, amount); + + /// + /// Gets the chamber by its . + /// + /// . + /// . + internal static Chamber Get(LockerChamber chamber) => Chambers.TryGetValue(chamber, out Chamber chmb) ? chmb : new(chamber, Locker.Get(x => x.Chambers.Any(x => x.Base == chamber)).FirstOrDefault()); + } +} diff --git a/EXILED/Exiled.API/Features/SupplyLocker.cs b/EXILED/Exiled.API/Features/Lockers/Locker.cs similarity index 50% rename from EXILED/Exiled.API/Features/SupplyLocker.cs rename to EXILED/Exiled.API/Features/Lockers/Locker.cs index b3bdd538a..15fb2ccae 100644 --- a/EXILED/Exiled.API/Features/SupplyLocker.cs +++ b/EXILED/Exiled.API/Features/Lockers/Locker.cs @@ -1,79 +1,78 @@ // ----------------------------------------------------------------------- -// +// // Copyright (c) Exiled Team. All rights reserved. // Licensed under the CC BY-SA 3.0 license. // // ----------------------------------------------------------------------- -namespace Exiled.API.Features +namespace Exiled.API.Features.Lockers { using System; using System.Collections.Generic; using System.Linq; - using System.Reflection; using Exiled.API.Enums; using Exiled.API.Extensions; + using Exiled.API.Features; + using Exiled.API.Features.Pickups; using Exiled.API.Interfaces; + using InventorySystem.Items.Pickups; using MapGeneration.Distributors; + using Mirror; - using PluginAPI.Core.Items; using UnityEngine; + using BaseLocker = MapGeneration.Distributors.Locker; #nullable enable /// - /// The in-game SupplyLocker. + /// The in-game Locker. /// - public class SupplyLocker : IWrapper, IWorldSpace + public class Locker : IWrapper, IWorldSpace { /// - /// A containing all known s and their corresponding . + /// A containing all known s and their corresponding . /// - internal static readonly Dictionary LockerToSupplyLocker = new(250, new ComponentsEqualityComparer()); + internal static readonly Dictionary BaseToExiledLockers = new(); /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The encapsulated . - internal SupplyLocker(Locker locker) + /// The encapsulated . + public Locker(BaseLocker locker) { Base = locker; - LockerToSupplyLocker.Add(locker, this); + BaseToExiledLockers.Add(locker, this); + + Chambers = locker.Chambers.Select(x => new Chamber(x, this)).ToList(); Type = locker.GetLockerType(); } /// - /// Gets a of which contains all the instances. + /// Gets a of which contains all the instances. /// - public static IReadOnlyCollection List => LockerToSupplyLocker.Values; + public static IReadOnlyCollection List => BaseToExiledLockers.Values; - /// - /// Gets the instance of the supply locker. - /// - public Locker Base { get; } + /// + public BaseLocker Base { get; } /// - /// Gets the of the . + /// Gets the of the . /// public LockerType Type { get; } /// - /// Gets the . + /// Gets the . /// public Transform Transform => Base.transform; - /// - /// Gets the position. - /// + /// public Vector3 Position => Base.transform.position; - /// - /// Gets the rotation. - /// + /// public Quaternion Rotation => Base.transform.rotation; /// - /// Gets the in which the is located. + /// Gets the in which the is located. /// public Room? Room => Room.Get(Position); @@ -83,14 +82,18 @@ internal SupplyLocker(Locker locker) public ZoneType Zone => Room?.Zone ?? ZoneType.Unspecified; /// - /// Gets the 's in this . + /// Gets the all in this locker. /// - public IEnumerable Chambers => Base.Chambers; + public IReadOnlyCollection Chambers { get; } /// - /// Gets the who has been open. + /// Gets or sets an id for manipulating opened chambers. /// - public IEnumerable OpenedChambers => Chambers.Where(c => c.IsOpen).ToArray(); + public ushort OpenedChambers + { + get => Base.OpenedChambers; + set => Base.NetworkOpenedChambers = value; + } /// /// Gets a random position from one of the . @@ -99,51 +102,51 @@ public Vector3 RandomChamberPosition { get { - LockerChamber randomChamber = Chambers.GetRandomValue(); + Chamber randomChamber = Chambers.GetRandomValue(); // Determine if the chamber uses multiple spawn points and has at least one available spawn point. - if (randomChamber._useMultipleSpawnpoints && randomChamber._spawnpoints.Length > 0) + if (randomChamber.UseMultipleSpawnpoints && randomChamber.Spawnpoints.Count() > 0) { // Return the position of a random spawn point within the chamber. - return randomChamber._spawnpoints.RandomItem().position; + return randomChamber.Spawnpoints.GetRandomValue().position; } // Return the position of the main spawn point for the chamber. - return randomChamber._spawnpoint.position; + return randomChamber.Spawnpoint.position; } } /// - /// Gets the belonging to the , if any. + /// Gets the belonging to the , if any. /// - /// The to get. - /// A or if not found. - public static SupplyLocker? Get(Locker locker) => locker == null ? null : - LockerToSupplyLocker.TryGetValue(locker, out SupplyLocker supply) ? supply : new SupplyLocker(locker); + /// The to get. + /// A or if not found. + public static Locker? Get(BaseLocker locker) => locker == null ? null : + BaseToExiledLockers.TryGetValue(locker, out Locker supply) ? supply : new Locker(locker); /// - /// Gets a of given the specified . + /// Gets a of given the specified . /// /// The to search for. - /// The with the given or if not found. - public static IEnumerable Get(ZoneType zoneType) => Get(room => room.Zone.HasFlag(zoneType)); + /// The with the given or if not found. + public static IEnumerable Get(ZoneType zoneType) => Get(room => room.Zone.HasFlag(zoneType)); /// - /// Gets a of filtered based on a predicate. + /// Gets a of filtered based on a predicate. /// /// The condition to satify. - /// A of which contains elements that satify the condition. - public static IEnumerable Get(Func predicate) => List.Where(predicate); + /// A of which contains elements that satify the condition. + public static IEnumerable Get(Func predicate) => List.Where(predicate); /// - /// Gets a random based on the specified filters. + /// Gets a random based on the specified filters. /// /// The to filter by. If unspecified, all zones are considered. /// The to filter by. If unspecified, all locker types are considered. - /// A random object, or null if no matching locker is found. - public static SupplyLocker? Random(ZoneType zone = ZoneType.Unspecified, LockerType lockerType = LockerType.Unknow) + /// A random object, or null if no matching locker is found. + public static Locker? Random(ZoneType zone = ZoneType.Unspecified, LockerType lockerType = LockerType.Unknow) { - IEnumerable filteredLockers = List; + IEnumerable filteredLockers = List; if (lockerType != LockerType.Unknow) filteredLockers = filteredLockers.Where(l => l.Type == lockerType); @@ -157,19 +160,19 @@ public Vector3 RandomChamberPosition /// /// Adds an item to a randomly selected locker chamber. /// - /// The to be added to the locker chamber. - public void AddItem(ItemPickup item) + /// The to be added to the locker chamber. + public void AddItem(Pickup item) { // Select a random chamber from the available locker chambers. - LockerChamber chamber = Chambers.GetRandomValue(); + Chamber chamber = Chambers.GetRandomValue(); // Determine the parent transform where the item will be placed. - Transform parentTransform = chamber._useMultipleSpawnpoints && chamber._spawnpoints.Length > 0 - ? chamber._spawnpoints.RandomItem() - : chamber._spawnpoint; + Transform parentTransform = chamber.UseMultipleSpawnpoints && chamber.Spawnpoints.Count() > 0 + ? chamber.Spawnpoints.GetRandomValue() + : chamber.Spawnpoint; // If the chamber is open, immediately set the item's parent and spawn it. - if (chamber.IsOpen) + if (chamber.Base.IsOpen) { item.Transform.SetParent(parentTransform); item.Spawn(); @@ -177,7 +180,7 @@ public void AddItem(ItemPickup item) else { // If the item is already spawned on the network, unspawn it before proceeding. - if (NetworkServer.spawned.ContainsKey(item.OriginalObject.netId)) + if (NetworkServer.spawned.ContainsKey(item.Base.netId)) NetworkServer.UnSpawn(item.GameObject); // Set the item's parent transform. @@ -187,7 +190,7 @@ public void AddItem(ItemPickup item) item.IsLocked = true; // Notify any pickup distributor triggers. - (item.OriginalObject as IPickupDistributorTrigger)?.OnDistributed(); + (item.Base as IPickupDistributorTrigger)?.OnDistributed(); // If the item has a Rigidbody component, make it kinematic and reset its position and rotation. if (item.Rigidbody != null) @@ -202,36 +205,25 @@ public void AddItem(ItemPickup item) // If the chamber is configured to spawn items on the first opening, add the item to the list of items to be spawned. // Otherwise, spawn the item immediately. - if (chamber._spawnOnFirstChamberOpening) - chamber._toBeSpawned.Add(item.OriginalObject); + if (chamber.InitiallySpawn) + chamber.Base._toBeSpawned.Add(item.Base); else - ItemDistributor.SpawnPickup(item.OriginalObject); + ItemDistributor.SpawnPickup(item.Base); } } /// - /// Spawns an item of the specified to the locker by creating a new . + /// Spawns an item of the specified to the locker by creating a new . /// /// The type of item to be added. - public void AddItem(ItemType type) => AddItem(ItemPickup.Create(type, default, default)); + public void AddItem(ItemType type) => AddItem(Pickup.Create(type)); /// - /// Clears the cached lockers in the dictionary that have become invalid. - /// This method identifies and removes all entries where either the key (a instance) - /// or the value (a instance) is null, ensuring that only valid references - /// are kept in the cache. + /// Clears the cached lockers in the dictionary. /// internal static void ClearCache() { - List keysToRemove = LockerToSupplyLocker - .Where(kv => kv.Key == null || kv.Value == null) - .Select(kv => kv.Key) - .ToList(); - - foreach (Locker key in keysToRemove) - { - LockerToSupplyLocker.Remove(key); - } + BaseToExiledLockers.Clear(); } } } diff --git a/EXILED/Exiled.API/Features/Map.cs b/EXILED/Exiled.API/Features/Map.cs index 05e5007a4..13d55fc98 100644 --- a/EXILED/Exiled.API/Features/Map.cs +++ b/EXILED/Exiled.API/Features/Map.cs @@ -16,6 +16,7 @@ namespace Exiled.API.Features using Enums; using Exiled.API.Extensions; using Exiled.API.Features.Hazards; + using Exiled.API.Features.Lockers; using Exiled.API.Features.Pickups; using Exiled.API.Features.Toys; using global::Hazards; @@ -79,9 +80,9 @@ DecontaminationController.Singleton.NetworkDecontaminationOverride is Decontamin public static ReadOnlyCollection PocketDimensionTeleports { get; } = TeleportsValue.AsReadOnly(); /// - /// Gets all objects. + /// Gets all objects. /// - public static ReadOnlyCollection Lockers { get; } = SupplyLocker.LockerToSupplyLocker.Keys.ToList().AsReadOnly(); + public static ReadOnlyCollection Lockers { get; } = Features.Lockers.Locker.BaseToExiledLockers.Keys.ToList().AsReadOnly(); /// /// Gets all objects. @@ -207,10 +208,10 @@ public static void ResetLightsColor() } /// - /// Gets a random . + /// Gets a random . /// - /// object. - public static Locker GetRandomLocker() => Lockers.GetRandomValue(); + /// object. + public static MapGeneration.Distributors.Locker GetRandomLocker() => Lockers.GetRandomValue(); /// /// Gets a random . diff --git a/EXILED/Exiled.API/Features/Spawn/LockerSpawnPoint.cs b/EXILED/Exiled.API/Features/Spawn/LockerSpawnPoint.cs index 84579e227..ecc434127 100644 --- a/EXILED/Exiled.API/Features/Spawn/LockerSpawnPoint.cs +++ b/EXILED/Exiled.API/Features/Spawn/LockerSpawnPoint.cs @@ -10,6 +10,7 @@ namespace Exiled.API.Features.Spawn using System.Linq; using Exiled.API.Enums; + using Exiled.API.Features.Lockers; using UnityEngine; using YamlDotNet.Serialization; @@ -35,7 +36,7 @@ public class LockerSpawnPoint : SpawnPoint public Vector3 Offset { get; set; } = Vector3.zero; /// - /// Gets or sets the type of the . + /// Gets or sets the type of the . /// public LockerType Type { get; set; } = LockerType.Unknow; @@ -56,7 +57,7 @@ public override Vector3 Position { get { - SupplyLocker foundLocker = SupplyLocker.Random(Zone, Type) ?? throw new NullReferenceException("No locker found in the specified zone."); + Locker foundLocker = Locker.Random(Zone, Type) ?? throw new NullReferenceException("No locker found in the specified zone."); // If UseChamber is true, use a random chamber's position. if (UseChamber) diff --git a/EXILED/Exiled.Events/Handlers/Internal/MapGenerated.cs b/EXILED/Exiled.Events/Handlers/Internal/MapGenerated.cs index 1bbcc5ddb..30ad47c9f 100644 --- a/EXILED/Exiled.Events/Handlers/Internal/MapGenerated.cs +++ b/EXILED/Exiled.Events/Handlers/Internal/MapGenerated.cs @@ -18,7 +18,7 @@ namespace Exiled.Events.Handlers.Internal using Exiled.API.Enums; using Exiled.API.Extensions; - + using Exiled.API.Features.Lockers; using InventorySystem.Items.Firearms.Attachments; using InventorySystem.Items.Firearms.Attachments.Components; @@ -47,7 +47,7 @@ public static void OnMapGenerated() { Map.ClearCache(); PrefabHelper.LoadPrefabs(); - SupplyLocker.ClearCache(); + Locker.ClearCache(); // TODO: Fix For (https://git.scpslgame.com/northwood-qa/scpsl-bug-reporting/-/issues/377) PlayerRoles.RoleAssign.HumanSpawner.Handlers[PlayerRoles.Team.ChaosInsurgency] = new PlayerRoles.RoleAssign.OneRoleHumanSpawner(PlayerRoles.RoleTypeId.ChaosConscript); diff --git a/EXILED/Exiled.Events/Patches/Generic/LockerList.cs b/EXILED/Exiled.Events/Patches/Generic/LockerList.cs index a4491f5c3..7dadd8817 100644 --- a/EXILED/Exiled.Events/Patches/Generic/LockerList.cs +++ b/EXILED/Exiled.Events/Patches/Generic/LockerList.cs @@ -12,7 +12,7 @@ namespace Exiled.Events.Patches.Generic using API.Features; using API.Features.Pools; - + using Exiled.API.Features.Lockers; using HarmonyLib; using MapGeneration.Distributors; @@ -20,22 +20,22 @@ namespace Exiled.Events.Patches.Generic using static HarmonyLib.AccessTools; /// - /// Patches . + /// Patches . /// - [HarmonyPatch(typeof(Locker), nameof(Locker.Start))] + [HarmonyPatch(typeof(MapGeneration.Distributors.Locker), nameof(MapGeneration.Distributors.Locker.Start))] internal class LockerList { private static IEnumerable Transpiler(IEnumerable codeInstructions) { List newInstructions = ListPool.Pool.Get(codeInstructions); - // new SupplyLocker(this) + // new Locker(this) newInstructions.InsertRange( 0, new CodeInstruction[] { new(OpCodes.Ldarg_0), - new(OpCodes.Newobj, GetDeclaredConstructors(typeof(SupplyLocker))[0]), + new(OpCodes.Newobj, GetDeclaredConstructors(typeof(API.Features.Lockers.Locker))[0]), new(OpCodes.Pop), }); From 2c32093604363d1dd2e86f21efbff8c1a1cb1110 Mon Sep 17 00:00:00 2001 From: SrLicht Date: Wed, 28 Aug 2024 03:36:47 -0300 Subject: [PATCH 14/23] Update EXILED/Exiled.API/Enums/LockerType.cs Co-authored-by: Nameless <85962933+Misfiy@users.noreply.github.com> --- EXILED/Exiled.API/Enums/LockerType.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EXILED/Exiled.API/Enums/LockerType.cs b/EXILED/Exiled.API/Enums/LockerType.cs index 6b21f699c..c44037a3a 100644 --- a/EXILED/Exiled.API/Enums/LockerType.cs +++ b/EXILED/Exiled.API/Enums/LockerType.cs @@ -13,7 +13,7 @@ namespace Exiled.API.Enums public enum LockerType { /// - /// The pedestal used by SCPs. + /// The pedestal used by SCP items. /// Pedestal, From 8d1dab9ccd15432ccecb6e680b1d7d085cdfd9b5 Mon Sep 17 00:00:00 2001 From: SrLicht Date: Wed, 28 Aug 2024 15:16:30 -0300 Subject: [PATCH 15/23] I dont like the name of ExiledLockers but * Resolving https://github.com/ExMod-Team/EXILED/pull/77#discussion_r1734360930 * Resolving https://github.com/ExMod-Team/EXILED/pull/77#discussion_r1734360419 * Cleaning Chambers List. --- EXILED/Exiled.API/Features/Lockers/Locker.cs | 3 +- EXILED/Exiled.API/Features/Map.cs | 36 ++++++++++++++++++-- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/EXILED/Exiled.API/Features/Lockers/Locker.cs b/EXILED/Exiled.API/Features/Lockers/Locker.cs index 15fb2ccae..73108359b 100644 --- a/EXILED/Exiled.API/Features/Lockers/Locker.cs +++ b/EXILED/Exiled.API/Features/Lockers/Locker.cs @@ -143,7 +143,7 @@ public Vector3 RandomChamberPosition /// /// The to filter by. If unspecified, all zones are considered. /// The to filter by. If unspecified, all locker types are considered. - /// A random object, or null if no matching locker is found. + /// A random object, or if no matching locker is found. public static Locker? Random(ZoneType zone = ZoneType.Unspecified, LockerType lockerType = LockerType.Unknow) { IEnumerable filteredLockers = List; @@ -224,6 +224,7 @@ public void AddItem(Pickup item) internal static void ClearCache() { BaseToExiledLockers.Clear(); + Chamber.Chambers.Clear(); } } } diff --git a/EXILED/Exiled.API/Features/Map.cs b/EXILED/Exiled.API/Features/Map.cs index 13d55fc98..666b19815 100644 --- a/EXILED/Exiled.API/Features/Map.cs +++ b/EXILED/Exiled.API/Features/Map.cs @@ -82,8 +82,20 @@ DecontaminationController.Singleton.NetworkDecontaminationOverride is Decontamin /// /// Gets all objects. /// + /// + /// This method is obsolete. Use instead to retrieve the objects directly. + /// + [Obsolete("Use Map.ExiledLockers instead")] public static ReadOnlyCollection Lockers { get; } = Features.Lockers.Locker.BaseToExiledLockers.Keys.ToList().AsReadOnly(); + /// + /// Gets all objects. + /// + /// + /// This metod will be renamed to Lockers when is discontinued. + /// + public static IReadOnlyCollection ExiledLockers { get; } = Features.Lockers.Locker.List; + /// /// Gets all objects. /// @@ -210,8 +222,28 @@ public static void ResetLightsColor() /// /// Gets a random . /// - /// object. - public static MapGeneration.Distributors.Locker GetRandomLocker() => Lockers.GetRandomValue(); + /// + /// This method is obsolete. Use instead. + /// to specify the zone and locker type for more precise filtering. + /// + /// A object from any zone and of any type. + [Obsolete("Use GetRandomLocker(ZoneType, LockerType) instead.")] + public static MapGeneration.Distributors.Locker GetRandomLocker() => Features.Lockers.Locker.Random().Base; + + /// + /// Gets a random from the specified zone and locker type. + /// + /// + /// The to filter the lockers by. If is provided, lockers from all zones are considered. + /// + /// + /// The to filter the lockers by. If is provided, lockers of any type are considered. + /// + /// + /// A object that matches the specified zone and locker type, or if no matching locker is found. + /// + public static Lockers.Locker GetRandomLocker(ZoneType zone = ZoneType.Unspecified, LockerType lockerType = LockerType.Unknow) => Features.Lockers.Locker.Random(zone, lockerType); + /// /// Gets a random . From 30d94ec11adf8d777ac6d4382f5043254a580376 Mon Sep 17 00:00:00 2001 From: SrLicht Date: Wed, 28 Aug 2024 15:20:37 -0300 Subject: [PATCH 16/23] Fixing CustomWeapon * Fixing a Bug with custom items with spawning in old SpawnLocationType.InsideLocker --- EXILED/Exiled.CustomItems/API/Features/CustomItem.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/EXILED/Exiled.CustomItems/API/Features/CustomItem.cs b/EXILED/Exiled.CustomItems/API/Features/CustomItem.cs index 1987108eb..c8598a98b 100644 --- a/EXILED/Exiled.CustomItems/API/Features/CustomItem.cs +++ b/EXILED/Exiled.CustomItems/API/Features/CustomItem.cs @@ -661,9 +661,15 @@ public virtual uint Spawn(IEnumerable spawnPoints, uint limit) } Vector3 position = chamber._spawnpoint.transform.position; - Spawn(position, null); - Log.Debug($"Spawned {Name} at {position} ({spawnPoint.Name})"); + Pickup? pickup = Spawn(position, null); + if (pickup?.Base is BaseFirearmPickup firearmPickup && this is CustomWeapon customWeapon) + { + firearmPickup.Status = new FirearmStatus(customWeapon.ClipSize, firearmPickup.Status.Flags, firearmPickup.Status.Attachments); + firearmPickup.NetworkStatus = firearmPickup.Status; + } + + Log.Debug($"Spawned {Name} at {position} ({spawnPoint.Name})"); break; } } From 0efff9845555222c0a8c4e584f0b307da0aade4a Mon Sep 17 00:00:00 2001 From: SrLicht Date: Wed, 28 Aug 2024 15:21:11 -0300 Subject: [PATCH 17/23] Update Map.cs Removing blank line. --- EXILED/Exiled.API/Features/Map.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/EXILED/Exiled.API/Features/Map.cs b/EXILED/Exiled.API/Features/Map.cs index 666b19815..8efc49271 100644 --- a/EXILED/Exiled.API/Features/Map.cs +++ b/EXILED/Exiled.API/Features/Map.cs @@ -244,7 +244,6 @@ public static void ResetLightsColor() /// public static Lockers.Locker GetRandomLocker(ZoneType zone = ZoneType.Unspecified, LockerType lockerType = LockerType.Unknow) => Features.Lockers.Locker.Random(zone, lockerType); - /// /// Gets a random . /// From 03fbe42f3bed5f07dac308008c153b444e61161b Mon Sep 17 00:00:00 2001 From: SrLicht Date: Wed, 28 Aug 2024 15:36:44 -0300 Subject: [PATCH 18/23] MORE * Added GetRandomSpawnPoint() in Chamber * Added AddItemToSpawn((ItemType itemType, int quantity = 1, bool spawnIfIsOpen = false)) in Chamber * Added IsOpen in chamber. --- EXILED/Exiled.API/Features/Lockers/Chamber.cs | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/EXILED/Exiled.API/Features/Lockers/Chamber.cs b/EXILED/Exiled.API/Features/Lockers/Chamber.cs index c6bae8c8c..25f9385b8 100644 --- a/EXILED/Exiled.API/Features/Lockers/Chamber.cs +++ b/EXILED/Exiled.API/Features/Lockers/Chamber.cs @@ -11,6 +11,7 @@ namespace Exiled.API.Features.Lockers using System.Linq; using Exiled.API.Enums; + using Exiled.API.Extensions; using Exiled.API.Features.Pickups; using Exiled.API.Interfaces; using MapGeneration.Distributors; @@ -145,6 +146,11 @@ public float Cooldown set => Base._targetCooldown = value; } + /// + /// Gets a value indicating whether the chamber is currently open. + /// + public bool IsOpen => Base.IsOpen; + /// /// Gets the of current cooldown. /// @@ -163,6 +169,51 @@ public float Cooldown /// Amount of items that should be spawned. public void SpawnItem(ItemType type, int amount) => Base.SpawnItem(type, amount); + /// + /// Adds an item of the specified type to the chamber's spawn list. + /// If the chamber is open and is set to , + /// the item is spawned immediately at a random spawn point within the chamber. + /// + /// The type of item to add to the spawn list. + /// The number of items to add. Defaults to 1. + /// + /// If and the chamber is open, the item is immediately spawned at a random spawn point. + /// Otherwise, the item is added to the spawn list and will spawn when the chamber is opened. + /// + public void AddItemToSpawn(ItemType itemType, int quantity = 1, bool spawnIfIsOpen = false) + { + for (int i = 0; i < quantity; i++) + { + Pickup pickup = Pickup.Create(itemType); + + if (spawnIfIsOpen && IsOpen) + { + pickup.Position = GetRandomSpawnPoint(); + pickup.Spawn(); + continue; + } + + Base._toBeSpawned.Add(pickup.Base); + } + } + + /// + /// Gets a random spawn point within the chamber. + /// If multiple spawn points are available and is , + /// a random spawn point is selected from the available points. + /// Otherwise, the default spawn point is used. + /// + /// A representing the position of the selected spawn point. + public Vector3 GetRandomSpawnPoint() + { + if (UseMultipleSpawnpoints && Spawnpoints.Any()) + { + return Spawnpoints.GetRandomValue().position; + } + + return Spawnpoint.position; + } + /// /// Gets the chamber by its . /// From 10797554eb93a7fbcc812a9b6aa04d0f1a841da8 Mon Sep 17 00:00:00 2001 From: SrLicht Date: Wed, 28 Aug 2024 15:45:11 -0300 Subject: [PATCH 19/23] Fixing obsolet use --- EXILED/Exiled.API/Features/Player.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/EXILED/Exiled.API/Features/Player.cs b/EXILED/Exiled.API/Features/Player.cs index b7a4afee5..bde4b0e85 100644 --- a/EXILED/Exiled.API/Features/Player.cs +++ b/EXILED/Exiled.API/Features/Player.cs @@ -3572,11 +3572,11 @@ public void RandomTeleport(Type type) nameof(Player) => Dictionary.Values.GetRandomValue(), nameof(Pickup) => Pickup.BaseToPickup.GetRandomValue().Value, nameof(Ragdoll) => Ragdoll.List.GetRandomValue(), - nameof(Locker) => Map.GetRandomLocker(), + nameof(Locker) => Map.GetRandomLocker(ZoneType.Unspecified, LockerType.Unknow), nameof(Generator) => Generator.List.GetRandomValue(), nameof(Window) => Window.List.GetRandomValue(), nameof(Scp914) => Scp914.Scp914Controller, - nameof(LockerChamber) => Map.GetRandomLocker().Chambers.GetRandomValue(), + nameof(LockerChamber) => Map.GetRandomLocker(ZoneType.Unspecified, LockerType.Unknow).Chambers.GetRandomValue(), _ => null, }; From 3301f87988da1e039ff842ac87e482f06fa18b8c Mon Sep 17 00:00:00 2001 From: SrLicht Date: Wed, 28 Aug 2024 15:54:46 -0300 Subject: [PATCH 20/23] Sorry @VALERA771 * Resolve https://github.com/ExMod-Team/EXILED/pull/77#pullrequestreview-2267004377 --- EXILED/Exiled.API/Features/Map.cs | 39 ++++++---------------------- EXILED/Exiled.API/Features/Player.cs | 4 +-- 2 files changed, 10 insertions(+), 33 deletions(-) diff --git a/EXILED/Exiled.API/Features/Map.cs b/EXILED/Exiled.API/Features/Map.cs index 8efc49271..4e341eeb0 100644 --- a/EXILED/Exiled.API/Features/Map.cs +++ b/EXILED/Exiled.API/Features/Map.cs @@ -80,22 +80,14 @@ DecontaminationController.Singleton.NetworkDecontaminationOverride is Decontamin public static ReadOnlyCollection PocketDimensionTeleports { get; } = TeleportsValue.AsReadOnly(); /// - /// Gets all objects. + /// Gets all objects in the current map. /// /// - /// This method is obsolete. Use instead to retrieve the objects directly. + /// This property is obsolete. Use instead to retrieve a collection of all instances. /// - [Obsolete("Use Map.ExiledLockers instead")] + [Obsolete("Use Locker.List instead.")] public static ReadOnlyCollection Lockers { get; } = Features.Lockers.Locker.BaseToExiledLockers.Keys.ToList().AsReadOnly(); - /// - /// Gets all objects. - /// - /// - /// This metod will be renamed to Lockers when is discontinued. - /// - public static IReadOnlyCollection ExiledLockers { get; } = Features.Lockers.Locker.List; - /// /// Gets all objects. /// @@ -220,29 +212,14 @@ public static void ResetLightsColor() } /// - /// Gets a random . + /// Gets a random object from the current map. /// /// - /// This method is obsolete. Use instead. - /// to specify the zone and locker type for more precise filtering. + /// This method is obsolete. Use instead to get a random instance. /// - /// A object from any zone and of any type. - [Obsolete("Use GetRandomLocker(ZoneType, LockerType) instead.")] - public static MapGeneration.Distributors.Locker GetRandomLocker() => Features.Lockers.Locker.Random().Base; - - /// - /// Gets a random from the specified zone and locker type. - /// - /// - /// The to filter the lockers by. If is provided, lockers from all zones are considered. - /// - /// - /// The to filter the lockers by. If is provided, lockers of any type are considered. - /// - /// - /// A object that matches the specified zone and locker type, or if no matching locker is found. - /// - public static Lockers.Locker GetRandomLocker(ZoneType zone = ZoneType.Unspecified, LockerType lockerType = LockerType.Unknow) => Features.Lockers.Locker.Random(zone, lockerType); + /// A randomly selected object. + [Obsolete("Use Locker.Random() instead.")] + public static MapGeneration.Distributors.Locker GetRandomLocker() => Lockers.GetRandomValue(); /// /// Gets a random . diff --git a/EXILED/Exiled.API/Features/Player.cs b/EXILED/Exiled.API/Features/Player.cs index bde4b0e85..b249e6903 100644 --- a/EXILED/Exiled.API/Features/Player.cs +++ b/EXILED/Exiled.API/Features/Player.cs @@ -3572,11 +3572,11 @@ public void RandomTeleport(Type type) nameof(Player) => Dictionary.Values.GetRandomValue(), nameof(Pickup) => Pickup.BaseToPickup.GetRandomValue().Value, nameof(Ragdoll) => Ragdoll.List.GetRandomValue(), - nameof(Locker) => Map.GetRandomLocker(ZoneType.Unspecified, LockerType.Unknow), + nameof(Locker) => Lockers.Locker.Random().Base, nameof(Generator) => Generator.List.GetRandomValue(), nameof(Window) => Window.List.GetRandomValue(), nameof(Scp914) => Scp914.Scp914Controller, - nameof(LockerChamber) => Map.GetRandomLocker(ZoneType.Unspecified, LockerType.Unknow).Chambers.GetRandomValue(), + nameof(LockerChamber) => Lockers.Locker.Random().Chambers.GetRandomValue().Base, _ => null, }; From 3bac7e3b6fdfe3945f60bfa0a0a8e83eea6e3407 Mon Sep 17 00:00:00 2001 From: SrLicht Date: Thu, 29 Aug 2024 15:20:33 -0300 Subject: [PATCH 21/23] Update Exiled.Loader.csproj * Resolving https://github.com/ExMod-Team/EXILED/pull/77#discussion_r1734047353 --- EXILED/Exiled.Loader/Exiled.Loader.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/EXILED/Exiled.Loader/Exiled.Loader.csproj b/EXILED/Exiled.Loader/Exiled.Loader.csproj index cb3a04e39..4a48187e2 100644 --- a/EXILED/Exiled.Loader/Exiled.Loader.csproj +++ b/EXILED/Exiled.Loader/Exiled.Loader.csproj @@ -17,7 +17,6 @@ - From 7a9317b2fd3c9b876260a57eba6123df53abb04f Mon Sep 17 00:00:00 2001 From: SrLicht Date: Thu, 29 Aug 2024 21:38:13 -0300 Subject: [PATCH 22/23] Update MapHandler.cs Reduce the delay on spawning items, its not necessary to be to long --- EXILED/Exiled.CustomItems/Events/MapHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EXILED/Exiled.CustomItems/Events/MapHandler.cs b/EXILED/Exiled.CustomItems/Events/MapHandler.cs index 8d9ca2708..12c658ece 100644 --- a/EXILED/Exiled.CustomItems/Events/MapHandler.cs +++ b/EXILED/Exiled.CustomItems/Events/MapHandler.cs @@ -18,7 +18,7 @@ internal sealed class MapHandler /// public void OnMapGenerated() { - Timing.CallDelayed(1, () => // Delay its necessary for the spawnpoints of lockers and rooms to be generated. + Timing.CallDelayed(0.3f, () => // Delay its necessary for the spawnpoints of lockers and rooms to be generated. { foreach (CustomItem customItem in CustomItem.Registered) customItem?.SpawnAll(); From 720a34a3e251d38554fe590b595628e72259a725 Mon Sep 17 00:00:00 2001 From: SrLicht Date: Sat, 31 Aug 2024 21:06:18 -0300 Subject: [PATCH 23/23] Ups Ups --- EXILED/Exiled.CustomItems/Events/MapHandler.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/EXILED/Exiled.CustomItems/Events/MapHandler.cs b/EXILED/Exiled.CustomItems/Events/MapHandler.cs index 82a51cfa2..4e0c2442f 100644 --- a/EXILED/Exiled.CustomItems/Events/MapHandler.cs +++ b/EXILED/Exiled.CustomItems/Events/MapHandler.cs @@ -9,7 +9,7 @@ namespace Exiled.CustomItems.Events { using Exiled.CustomItems.API.Features; using MEC; - + /// /// Event Handlers for the CustomItem API. /// @@ -23,5 +23,6 @@ public void OnMapGenerated() foreach (CustomItem customItem in CustomItem.Registered) customItem?.SpawnAll(); }); + } } } \ No newline at end of file