Skip to content

Commit

Permalink
Item::<T>Get() and Pickup::<T>Get() (#17)
Browse files Browse the repository at this point in the history
* `Item::::<T>Get()` and `Pickup::<T>Get()`

* Revert doc change

* Add `Hazard::Get<T>()`

* doc fix

* `Door::Get<T>()`

* AdminToy.Get<T>()

* More <T> implementation

* WeirdFix

* simplify Scp244Spawning patch and AddedComment & NO IL error

* Remove Log.info

* DroppingItem light modifiication

* Moving Item.Get inside the eventargs instead of transpiller
  • Loading branch information
louis1706 authored Aug 9, 2024
1 parent 03d6bd7 commit 06cf2d7
Show file tree
Hide file tree
Showing 40 changed files with 271 additions and 103 deletions.
57 changes: 43 additions & 14 deletions EXILED/Exiled.API/Features/Doors/Door.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ namespace Exiled.API.Features.Doors
using Exiled.API.Enums;
using Exiled.API.Extensions;
using Exiled.API.Features.Core;
using Exiled.API.Features.Hazards;
using Exiled.API.Interfaces;
using global::Hazards;
using Interactables.Interobjects;
using Interactables.Interobjects.DoorUtils;
using MEC;
Expand Down Expand Up @@ -309,6 +311,31 @@ public static Door Get(DoorVariant doorVariant)
return DoorVariantToDoor[doorVariant];
}

/// <summary>
/// Gets the <see cref="Door"/> by <see cref="DoorVariant"/>.
/// </summary>
/// <param name="doorVariant">The <see cref="DoorVariant"/> to convert into an door.</param>
/// <typeparam name="T">The specified <see cref="Door"/> type.</typeparam>
/// <returns>The door wrapper for the given <see cref="DoorVariant"/>.</returns>
public static T Get<T>(DoorVariant doorVariant)
where T : Door => Get(doorVariant) as T;

/// <summary>
/// Gets a <see cref="Door"/> given the specified <see cref="DoorType"/>.
/// </summary>
/// <param name="doorType">The <see cref="DoorType"/> to search for.</param>
/// <returns>The <see cref="Door"/> with the given <see cref="DoorType"/> or <see langword="null"/> if not found.</returns>
public static Door Get(DoorType doorType) => List.FirstOrDefault(x => x.Type == doorType);

/// <summary>
/// Gets the <see cref="Door"/> by <see cref="DoorVariant"/>.
/// </summary>
/// <param name="doorType">The <see cref="DoorVariant"/> to convert into an door.</param>
/// <typeparam name="T">The specified <see cref="Door"/> type.</typeparam>
/// <returns>The door wrapper for the given <see cref="DoorVariant"/>.</returns>
public static T Get<T>(DoorType doorType)
where T : Door => Get(doorType) as T;

/// <summary>
/// Gets a <see cref="Door"/> given the specified name.
/// </summary>
Expand All @@ -320,27 +347,22 @@ public static Door Get(string name)
return nameExtension is null ? null : Get(nameExtension.TargetDoor);
}

/// <summary>
/// Gets the <see cref="Door"/> by <see cref="DoorVariant"/>.
/// </summary>
/// <param name="name">The name to search for.</param>
/// <typeparam name="T">The specified <see cref="Door"/> type.</typeparam>
/// <returns>The door wrapper for the given <see cref="DoorVariant"/>.</returns>
public static T Get<T>(string name)
where T : Door => Get(name) as T;

/// <summary>
/// Gets the door object associated with a specific <see cref="UnityEngine.GameObject"/>, or creates a new one if there isn't one.
/// </summary>
/// <param name="gameObject">The base-game <see cref="UnityEngine.GameObject"/>.</param>
/// <returns>The <see cref="Door"/> with the given name or <see langword="null"/> if not found.</returns>
public static Door Get(GameObject gameObject) => gameObject is null ? null : Get(gameObject.GetComponentInChildren<DoorVariant>());

/// <summary>
/// Gets a <see cref="IEnumerable{T}"/> of <see cref="Door"/> filtered based on a predicate.
/// </summary>
/// <param name="predicate">The condition to satify.</param>
/// <returns>A <see cref="IEnumerable{T}"/> of <see cref="Door"/> which contains elements that satify the condition.</returns>
public static IEnumerable<Door> Get(Func<Door, bool> predicate) => List.Where(predicate);

/// <summary>
/// Gets a <see cref="Door"/> given the specified <see cref="DoorType"/>.
/// </summary>
/// <param name="doorType">The <see cref="DoorType"/> to search for.</param>
/// <returns>The <see cref="Door"/> with the given <see cref="DoorType"/> or <see langword="null"/> if not found.</returns>
public static Door Get(DoorType doorType) => List.FirstOrDefault(x => x.Type == doorType);

/// <summary>
/// Returns the closest <see cref="Door"/> to the given <paramref name="position"/>.
/// </summary>
Expand All @@ -367,6 +389,13 @@ public static Door Random(ZoneType type = ZoneType.Unspecified, bool onlyUnbroke
return doors[UnityEngine.Random.Range(0, doors.Count)];
}

/// <summary>
/// Gets a <see cref="IEnumerable{T}"/> of <see cref="Door"/> filtered based on a predicate.
/// </summary>
/// <param name="predicate">The condition to satify.</param>
/// <returns>A <see cref="IEnumerable{T}"/> of <see cref="Door"/> which contains elements that satify the condition.</returns>
public static IEnumerable<Door> Get(Func<Door, bool> predicate) => List.Where(predicate);

/// <summary>
/// Locks all <see cref="Door">doors</see> given the specified <see cref="ZoneType"/>.
/// </summary>
Expand Down
9 changes: 9 additions & 0 deletions EXILED/Exiled.API/Features/Hazards/Hazard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,15 @@ public static Hazard Get(EnvironmentalHazard environmentalHazard) =>
_ => new Hazard(environmentalHazard)
};

/// <summary>
/// Gets the <see cref="Hazard"/> by <see cref="EnvironmentalHazard"/>.
/// </summary>
/// <param name="environmentalHazard">The <see cref="EnvironmentalHazard"/> to convert into an hazard.</param>
/// <typeparam name="T">The specified <see cref="Hazard"/> type.</typeparam>
/// <returns>The hazard wrapper for the given <see cref="EnvironmentalHazard"/>.</returns>
public static T Get<T>(EnvironmentalHazard environmentalHazard)
where T : Hazard => Get(environmentalHazard) as T;

/// <summary>
/// Gets the hazard by the room where it's located.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion EXILED/Exiled.API/Features/Items/ExplosiveGrenade.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ public ExplosionGrenadeProjectile SpawnActive(Vector3 position, Player owner = n

ipb.Info = new PickupSyncInfo(Type, Weight, ItemSerialGenerator.GenerateNext());

ExplosionGrenadeProjectile grenade = (ExplosionGrenadeProjectile)Pickup.Get(ipb);
ExplosionGrenadeProjectile grenade = Pickup.Get<ExplosionGrenadeProjectile>(ipb);

grenade.Base.gameObject.SetActive(true);

Expand Down
2 changes: 1 addition & 1 deletion EXILED/Exiled.API/Features/Items/FlashGrenade.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public FlashbangProjectile SpawnActive(Vector3 position, Player owner = null)

ipb.Info = new PickupSyncInfo(Type, Weight, ItemSerialGenerator.GenerateNext());

FlashbangProjectile grenade = (FlashbangProjectile)Pickup.Get(ipb);
FlashbangProjectile grenade = Pickup.Get<FlashbangProjectile>(ipb);

grenade.Base.gameObject.SetActive(true);

Expand Down
45 changes: 43 additions & 2 deletions EXILED/Exiled.API/Features/Items/Item.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,13 @@ namespace Exiled.API.Features.Items
using InventorySystem.Items.Radio;
using InventorySystem.Items.ThrowableProjectiles;
using InventorySystem.Items.ToggleableLights;
using InventorySystem.Items.ToggleableLights.Flashlight;
using InventorySystem.Items.Usables;
using InventorySystem.Items.Usables.Scp1576;
using InventorySystem.Items.Usables.Scp244;
using InventorySystem.Items.Usables.Scp330;
using UnityEngine;

using BaseConsumable = InventorySystem.Items.Usables.Consumable;
using Object = UnityEngine.Object;

/// <summary>
/// A wrapper class for <see cref="ItemBase"/>.
Expand Down Expand Up @@ -219,6 +217,15 @@ public static Item Get(ItemBase itemBase)
};
}

/// <summary>
/// Gets an existing <see cref="Item"/> or creates a new instance of one.
/// </summary>
/// <param name="itemBase">The <see cref="ItemBase"/> to convert into an item.</param>
/// <typeparam name="T">The specified <see cref="Item"/> type.</typeparam>
/// <returns>The item wrapper for the given <see cref="ItemBase"/>.</returns>
public static T Get<T>(ItemBase itemBase)
where T : Item => Get(itemBase) as T;

/// <summary>
/// Gets the Item belonging to the specified serial.
/// </summary>
Expand Down Expand Up @@ -279,6 +286,40 @@ ItemType.KeycardGuard or ItemType.KeycardJanitor or ItemType.KeycardO5 or ItemTy
_ => new Item(type),
};

/// <summary>
/// Creates a new <see cref="Item"/> with the proper inherited subclass.
/// <para>
/// Based on the <paramref name="type"/>, the returned <see cref="Item"/> can be casted into a subclass to gain more control over the object.
/// <br />- Usable items (Adrenaline, Medkit, Painkillers, SCP-207, SCP-268, and SCP-500) should be casted to the <see cref="Usable"/> class.
/// <br />- All valid ammo should be casted to the <see cref="Ammo"/> class.
/// <br />- All valid firearms (not including the Micro HID) should be casted to the <see cref="Firearm"/> class.
/// <br />- All valid keycards should be casted to the <see cref="Keycard"/> class.
/// <br />- All valid armor should be casted to the <see cref="Armor"/> class.
/// <br />- Explosive grenades and SCP-018 should be casted to the <see cref="ExplosiveGrenade"/> class.
/// <br />- Flash grenades should be casted to the <see cref="FlashGrenade"/> class.
/// </para>
/// <para>
/// <br />The following have their own respective classes:
/// <br />- Flashlights can be casted to <see cref="Flashlight"/>.
/// <br />- Radios can be casted to <see cref="Radio"/>.
/// <br />- The Micro HID can be casted to <see cref="MicroHid"/>.
/// <br />- SCP-244 A and B variants can be casted to <see cref="Scp244"/>.
/// <br />- SCP-330 can be casted to <see cref="Scp330"/>.
/// <br />- SCP-2176 can be casted to the <see cref="Scp2176"/> class.
/// <br />- SCP-1576 can be casted to the <see cref="Scp1576"/> class.
/// <br />- Jailbird can be casted to the <see cref="Jailbird"/> class.
/// </para>
/// <para>
/// Items that are not listed above do not have a subclass, and can only use the base <see cref="Item"/> class.
/// </para>
/// </summary>
/// <param name="type">The <see cref="ItemType"/> of the item to create.</param>
/// <param name="owner">The <see cref="Player"/> who owns the item by default.</param>
/// <typeparam name="T">The specified <see cref="Item"/> type.</typeparam>
/// <returns>The <see cref="Item"/> created. This can be cast as a subclass.</returns>
public static Item Create<T>(ItemType type, Player owner = null)
where T : Item => Create(type, owner) as T;

/// <summary>
/// Gives this item to a <see cref="Player"/>.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion EXILED/Exiled.API/Features/Items/Scp018.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public Scp018Projectile SpawnActive(Vector3 position, Player owner = null)

ipb.Info = new PickupSyncInfo(Type, Weight, ItemSerialGenerator.GenerateNext());

Scp018Projectile grenade = (Scp018Projectile)Pickup.Get(ipb);
Scp018Projectile grenade = Pickup.Get<Scp018Projectile>(ipb);

grenade.Base.gameObject.SetActive(true);

Expand Down
2 changes: 1 addition & 1 deletion EXILED/Exiled.API/Features/Items/Scp2176.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public Scp2176Projectile SpawnActive(Vector3 position, Player owner = null)

ipb.Info = new PickupSyncInfo(Type, Weight, ItemSerialGenerator.GenerateNext());

Scp2176Projectile grenade = (Scp2176Projectile)Pickup.Get(ipb);
Scp2176Projectile grenade = Pickup.Get<Scp2176Projectile>(ipb);

grenade.Base.gameObject.SetActive(true);

Expand Down
4 changes: 2 additions & 2 deletions EXILED/Exiled.API/Features/Items/Scp330.cs
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ public IEnumerable<Scp330Pickup> DropCandy(CandyKindID type, bool dropAll = fals

ipb.Info = new(Type, Weight, ItemSerialGenerator.GenerateNext());

Scp330Pickup pickup = (Scp330Pickup)Pickup.Get(ipb);
Scp330Pickup pickup = Pickup.Get<Scp330Pickup>(ipb);

if (exposedType is not CandyKindID.None)
pickup.ExposedCandy = exposedType;
Expand All @@ -218,7 +218,7 @@ public IEnumerable<Scp330Pickup> DropCandy(CandyKindID type, bool dropAll = fals

ipb.Info = new(Type, Weight, ItemSerialGenerator.GenerateNext());

Scp330Pickup pickup = (Scp330Pickup)Pickup.Get(ipb);
Scp330Pickup pickup = Pickup.Get<Scp330Pickup>(ipb);

if (exposedType is not CandyKindID.None)
pickup.ExposedCandy = exposedType;
Expand Down
2 changes: 1 addition & 1 deletion EXILED/Exiled.API/Features/Items/Throwable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public Throwable(ThrowableItem itemBase)
{
Base = itemBase;
Base.Projectile.gameObject.SetActive(false);
Projectile = (Projectile)Pickup.Get(Object.Instantiate(Base.Projectile));
Projectile = Pickup.Get<Projectile>(Object.Instantiate(Base.Projectile));
Base.Projectile.gameObject.SetActive(true);
Projectile.Serial = Serial;
}
Expand Down
4 changes: 2 additions & 2 deletions EXILED/Exiled.API/Features/Lift.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ internal Lift(ElevatorChamber elevator)
/// <summary>
/// Gets a value of the internal doors list.
/// </summary>
public IReadOnlyCollection<Doors.ElevatorDoor> Doors => internalDoorsList.Select(x => Door.Get(x).As<Doors.ElevatorDoor>()).ToList();
public IReadOnlyCollection<Doors.ElevatorDoor> Doors => internalDoorsList.Select(x => Door.Get<Doors.ElevatorDoor>(x)).ToList();

/// <summary>
/// Gets a <see cref="IEnumerable{T}"/> of <see cref="Player"/> in the <see cref="Room"/>.
Expand Down Expand Up @@ -201,7 +201,7 @@ public float AnimationTime
/// <summary>
/// Gets the <see cref="CurrentDestination"/>.
/// </summary>
public Doors.ElevatorDoor CurrentDestination => Door.Get(Base.CurrentDestination).As<Doors.ElevatorDoor>();
public Doors.ElevatorDoor CurrentDestination => Door.Get<Doors.ElevatorDoor>(Base.CurrentDestination);

/// <summary>
/// Gets a <see cref="IEnumerable{T}"/> of <see cref="Lift"/> which contains all the <see cref="Lift"/> instances from the specified <see cref="Status"/>.
Expand Down
2 changes: 1 addition & 1 deletion EXILED/Exiled.API/Features/Map.cs
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ public static TantrumHazard PlaceTantrum(Vector3 position, bool isActive = true)

NetworkServer.Spawn(tantrum.gameObject);

return Hazard.Get(tantrum).Cast<TantrumHazard>();
return Hazard.Get<TantrumHazard>(tantrum);
}

/// <summary>
Expand Down
52 changes: 52 additions & 0 deletions EXILED/Exiled.API/Features/Pickups/Pickup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,15 @@ public static Pickup Get(ItemPickupBase pickupBase)
};
}

/// <summary>
/// Gets an existing <see cref="Pickup"/> or creates a new instance of one.
/// </summary>
/// <param name="pickupBase">The <see cref="ItemPickupBase"/> to convert into an pickup.</param>
/// <typeparam name="T">The specified <see cref="Pickup"/> type.</typeparam>
/// <returns>The pickup wrapper for the given <see cref="ItemPickupBase"/>.</returns>
public static T Get<T>(ItemPickupBase pickupBase)
where T : Pickup => Get(pickupBase) as T;

/// <summary>
/// Gets the <see cref="Pickup"/> given a <see cref="Serial"/>.
/// </summary>
Expand Down Expand Up @@ -487,6 +496,36 @@ public static IEnumerable<T> Get<T>(IEnumerable<GameObject> gameObjects)
_ => new Pickup(type),
};

/// <summary>
/// Creates and returns a new <see cref="Pickup"/> with the proper inherited subclass.
/// <para>
/// Based on the <paramref name="type"/>, the returned <see cref="Pickup"/> can be cast into a subclass to gain more control over the object.
/// <br />- All valid ammo should be cast to the <see cref="AmmoPickup"/> class.
/// <br />- All valid firearms (not including the Micro HID) should be cast to the <see cref="FirearmPickup"/> class.
/// <br />- All valid keycards should be cast to the <see cref="KeycardPickup"/> class.
/// <br />- All valid armor should be cast to the <see cref="BodyArmorPickup"/> class.
/// <br />- All grenades and throwables (not including SCP-018 and SCP-2176) should be cast to the <see cref="GrenadePickup"/> class.
/// </para>
/// <para>
/// <br />The following have their own respective classes:
/// <br />- Radios can be cast to <see cref="RadioPickup"/>.
/// <br />- The Micro HID can be cast to <see cref="MicroHIDPickup"/>.
/// <br />- SCP-244 A and B variants can be cast to <see cref="Scp244Pickup"/>.
/// <br />- SCP-330 can be cast to <see cref="Scp330Pickup"/>.
/// <br />- SCP-018 can be cast to <see cref="Projectiles.Scp018Projectile"/>.
/// <br />- SCP-2176 can be cast to <see cref="Projectiles.Scp2176Projectile"/>.
/// </para>
/// <para>
/// Items that are not listed above do not have a subclass, and can only use the base <see cref="Pickup"/> class.
/// </para>
/// </summary>
/// <param name="type">The <see cref="ItemType"/> of the pickup.</param>
/// <typeparam name="T">The specified <see cref="Pickup"/> type.</typeparam>
/// <returns>The created <see cref="Pickup"/>.</returns>
/// <seealso cref="Projectile.Create(Enums.ProjectileType)"/>
public static Pickup Create<T>(ItemType type)
where T : Pickup => Create(type) as T;

/// <summary>
/// Creates and spawns a <see cref="Pickup"/>.
/// </summary>
Expand All @@ -498,6 +537,19 @@ public static IEnumerable<T> Get<T>(IEnumerable<GameObject> gameObjects)
/// <seealso cref="Projectile.CreateAndSpawn(Enums.ProjectileType, Vector3, Quaternion, bool, Player)"/>
public static Pickup CreateAndSpawn(ItemType type, Vector3 position, Quaternion rotation, Player previousOwner = null) => Create(type).Spawn(position, rotation, previousOwner);

/// <summary>
/// Creates and spawns a <see cref="Pickup"/>.
/// </summary>
/// <param name="type">The <see cref="ItemType"/> of the pickup.</param>
/// <param name="position">The position to spawn the <see cref="Pickup"/> at.</param>
/// <param name="rotation">The rotation to spawn the <see cref="Pickup"/>.</param>
/// <param name="previousOwner">An optional previous owner of the item.</param>
/// <typeparam name="T">The specified <see cref="Pickup"/> type.</typeparam>
/// <returns>The <see cref="Pickup"/>. See documentation of <see cref="Create(ItemType)"/> for more information on casting.</returns>
/// <seealso cref="Projectile.CreateAndSpawn(Enums.ProjectileType, Vector3, Quaternion, bool, Player)"/>
public static Pickup CreateAndSpawn<T>(ItemType type, Vector3 position, Quaternion rotation, Player previousOwner = null)
where T : Pickup => CreateAndSpawn(type, position, rotation, previousOwner) as T;

/// <summary>
/// Spawns a <see cref="Pickup"/>.
/// </summary>
Expand Down
Loading

0 comments on commit 06cf2d7

Please sign in to comment.