From 752d39b628477ea028e563cf280c528308cef883 Mon Sep 17 00:00:00 2001
From: "@Someone" <45270312+Someone-193@users.noreply.github.com>
Date: Tue, 12 Aug 2025 19:40:08 -0400
Subject: [PATCH 01/38] Some stuff
---
.../Exiled.API/Extensions/MirrorExtensions.cs | 27 ++++++++
.../Features/Items/Keycards/Keycard.cs | 63 +++++++++++++++++++
.../Pickups/Keycards/KeycardPickup.cs | 46 ++++++++++++++
3 files changed, 136 insertions(+)
create mode 100644 EXILED/Exiled.API/Features/Items/Keycards/Keycard.cs
create mode 100644 EXILED/Exiled.API/Features/Pickups/Keycards/KeycardPickup.cs
diff --git a/EXILED/Exiled.API/Extensions/MirrorExtensions.cs b/EXILED/Exiled.API/Extensions/MirrorExtensions.cs
index a06cd5c294..63a9a4153c 100644
--- a/EXILED/Exiled.API/Extensions/MirrorExtensions.cs
+++ b/EXILED/Exiled.API/Extensions/MirrorExtensions.cs
@@ -25,6 +25,7 @@ namespace Exiled.API.Extensions
using InventorySystem.Items;
using InventorySystem.Items.Firearms;
using InventorySystem.Items.Firearms.Modules;
+ using InventorySystem.Items.Keycards;
using MEC;
using Mirror;
using PlayerRoles;
@@ -36,6 +37,8 @@ namespace Exiled.API.Extensions
using Respawning;
using UnityEngine;
+ using KeycardPickup = Exiled.API.Features.Pickups.Keycards.KeycardPickup;
+
///
/// A set of extensions for Networking.
///
@@ -401,6 +404,30 @@ public static void SendFakeEffectTo(this Player effectOwner, Player target, Effe
});
}
+ ///
+ /// Makes the server resend a message to all clients updating a keycards details to current values.
+ ///
+ /// The keycard to resync.
+ public static void ResyncKeycardItem(Features.Items.Keycards.Keycard keycard)
+ {
+ if (KeycardDetailSynchronizer.Database.Remove(keycard.Serial))
+ {
+ KeycardDetailSynchronizer.ServerProcessItem((KeycardItem)keycard.Base);
+ }
+ }
+
+ ///
+ /// Makes the server resend a message to all clients updating a keycards details to current values.
+ ///
+ /// The keycard to resync.
+ public static void ResyncKeycardPickup(KeycardPickup keycard)
+ {
+ if (KeycardDetailSynchronizer.Database.Remove(keycard.Serial))
+ {
+ KeycardDetailSynchronizer.ServerProcessPickup((InventorySystem.Items.Keycards.KeycardPickup)keycard.Base);
+ }
+ }
+
///
/// Send CASSIE announcement that only can hear.
///
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/Keycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/Keycard.cs
new file mode 100644
index 0000000000..e8f991a6eb
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Items/Keycards/Keycard.cs
@@ -0,0 +1,63 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+using InventorySystem.Items.Keycards;
+namespace Exiled.API.Features.Items.Keycards
+{
+ using Exiled.API.Enums;
+ using Exiled.API.Extensions;
+
+ using InventorySystem.Items;
+
+ ///
+ /// A base class for all keycard items.
+ ///
+ public class Keycard : Item
+ {
+ private CustomPermsDetail permsDetail;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The to encapsulate.
+ public Keycard(ItemBase itemBase)
+ : base(itemBase)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The of the item to create.
+ internal Keycard(ItemType type)
+ : base(type)
+ {
+ }
+
+ ///
+ /// Gets or sets a value indicating the permissions this keycard has.
+ ///
+ public KeycardPermissions Permissions
+ {
+ get => permsDetail;
+ set
+ {
+ permsDetail._customLevels.
+ Resync();
+ }
+ }
+
+ ///
+ /// Resyncs all properties of the keycard.
+ /// Gets called by all setters by default.
+ ///
+ public void Resync()
+ {
+ MirrorExtensions.ResyncKeycardItem(this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Pickups/Keycards/KeycardPickup.cs b/EXILED/Exiled.API/Features/Pickups/Keycards/KeycardPickup.cs
new file mode 100644
index 0000000000..ac968a4346
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Pickups/Keycards/KeycardPickup.cs
@@ -0,0 +1,46 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Pickups.Keycards
+{
+ using Exiled.API.Extensions;
+
+ using InventorySystem.Items.Pickups;
+
+ ///
+ /// A base class for all keycard pickups.
+ ///
+ public class KeycardPickup : Pickup
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The base class.
+ public KeycardPickup(ItemPickupBase pickupBase)
+ : base(pickupBase)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The of the pickup.
+ internal KeycardPickup(ItemType type)
+ : base(type)
+ {
+ }
+
+ ///
+ /// Resyncs all properties of the keycard.
+ /// Gets called by all setters by default.
+ ///
+ public void Resync()
+ {
+ MirrorExtensions.ResyncKeycardPickup(this);
+ }
+ }
+}
\ No newline at end of file
From dda9729a1aec7fbbfd1b4c91d11f71166d4060e4 Mon Sep 17 00:00:00 2001
From: "@Someone" <45270312+Someone-193@users.noreply.github.com>
Date: Wed, 20 Aug 2025 00:23:40 -0400
Subject: [PATCH 02/38] RELEASE MEEEEEEEEEEEEEEE
WHY MUST I SUFFERRRRRR
---
EXILED/Exiled.API/Exiled.API.csproj | 1 +
.../Exiled.API/Extensions/ItemExtensions.cs | 8 +
.../Exiled.API/Extensions/MirrorExtensions.cs | 8 +-
EXILED/Exiled.API/Features/Items/Item.cs | 4 +-
.../Features/Items/Keycards/CustomKeycard.cs | 184 ++++++++++++++++++
.../Features/Items/Keycards/Keycard.cs | 63 ------
.../Items/Keycards/ManagementKeycard.cs | 55 ++++++
.../Features/Items/Keycards/MetalKeycard.cs | 150 ++++++++++++++
.../Features/Items/Keycards/Site02Keycard.cs | 95 +++++++++
.../Items/Keycards/TaskForceKeycard.cs | 128 ++++++++++++
.../Interfaces/Keycards/ILabelKeycard.cs | 28 +++
.../Interfaces/Keycards/INameTagKeycard.cs | 22 +++
.../Interfaces/Keycards/IRankKeycard.cs | 23 +++
.../Keycards/ISerialLabelKeycard.cs | 23 +++
.../Interfaces/Keycards/IWearKeycard.cs | 22 +++
15 files changed, 746 insertions(+), 68 deletions(-)
create mode 100644 EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
delete mode 100644 EXILED/Exiled.API/Features/Items/Keycards/Keycard.cs
create mode 100644 EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs
create mode 100644 EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs
create mode 100644 EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
create mode 100644 EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs
create mode 100644 EXILED/Exiled.API/Interfaces/Keycards/ILabelKeycard.cs
create mode 100644 EXILED/Exiled.API/Interfaces/Keycards/INameTagKeycard.cs
create mode 100644 EXILED/Exiled.API/Interfaces/Keycards/IRankKeycard.cs
create mode 100644 EXILED/Exiled.API/Interfaces/Keycards/ISerialLabelKeycard.cs
create mode 100644 EXILED/Exiled.API/Interfaces/Keycards/IWearKeycard.cs
diff --git a/EXILED/Exiled.API/Exiled.API.csproj b/EXILED/Exiled.API/Exiled.API.csproj
index c8737a790c..3b2040da91 100644
--- a/EXILED/Exiled.API/Exiled.API.csproj
+++ b/EXILED/Exiled.API/Exiled.API.csproj
@@ -37,6 +37,7 @@
+
diff --git a/EXILED/Exiled.API/Extensions/ItemExtensions.cs b/EXILED/Exiled.API/Extensions/ItemExtensions.cs
index 1c03c97d9c..348f7e635f 100644
--- a/EXILED/Exiled.API/Extensions/ItemExtensions.cs
+++ b/EXILED/Exiled.API/Extensions/ItemExtensions.cs
@@ -84,6 +84,14 @@ public static class ItemExtensions
/// Returns whether the is a keycard.
public static bool IsKeycard(this ItemType type) => GetCategory(type) == ItemCategory.Keycard;
+ ///
+ /// Checks if an is a custom keycard.
+ ///
+ /// The item to be checked.
+ /// Returns where the is a custom keycard.
+ /// This just signifies whether the ItemType represents a keycard that has modifiable properties.
+ public static bool IsCustomKeycard(this ItemType type) => type is ItemType.KeycardCustomTaskForce or ItemType.KeycardCustomSite02 or ItemType.KeycardCustomManagement or ItemType.KeycardCustomMetalCase;
+
///
/// Given an , returns the matching .
///
diff --git a/EXILED/Exiled.API/Extensions/MirrorExtensions.cs b/EXILED/Exiled.API/Extensions/MirrorExtensions.cs
index 63a9a4153c..20b0ce06a2 100644
--- a/EXILED/Exiled.API/Extensions/MirrorExtensions.cs
+++ b/EXILED/Exiled.API/Extensions/MirrorExtensions.cs
@@ -407,12 +407,12 @@ public static void SendFakeEffectTo(this Player effectOwner, Player target, Effe
///
/// Makes the server resend a message to all clients updating a keycards details to current values.
///
- /// The keycard to resync.
- public static void ResyncKeycardItem(Features.Items.Keycards.Keycard keycard)
+ /// The keycard to resync.
+ public static void ResyncKeycardItem(Features.Items.Keycards.CustomKeycard customKeycard)
{
- if (KeycardDetailSynchronizer.Database.Remove(keycard.Serial))
+ if (KeycardDetailSynchronizer.Database.Remove(customKeycard.Serial))
{
- KeycardDetailSynchronizer.ServerProcessItem((KeycardItem)keycard.Base);
+ KeycardDetailSynchronizer.ServerProcessItem((KeycardItem)customKeycard.Base);
}
}
diff --git a/EXILED/Exiled.API/Features/Items/Item.cs b/EXILED/Exiled.API/Features/Items/Item.cs
index 839585d0c9..13ec2a7c2a 100644
--- a/EXILED/Exiled.API/Features/Items/Item.cs
+++ b/EXILED/Exiled.API/Features/Items/Item.cs
@@ -12,6 +12,7 @@ namespace Exiled.API.Features.Items
using Exiled.API.Extensions;
using Exiled.API.Features.Core;
+ using Exiled.API.Features.Items.Keycards;
using Exiled.API.Features.Pickups;
using Exiled.API.Interfaces;
using InventorySystem;
@@ -217,7 +218,8 @@ public static Item Get(ItemBase itemBase)
return itemBase switch
{
InventorySystem.Items.Firearms.Firearm firearm => new Firearm(firearm),
- KeycardItem keycard => new Keycard(keycard),
+ KeycardItem keycard when !itemBase.ItemTypeId.IsCustomKeycard() => new Keycard(keycard),
+ KeycardItem customKeycard => CustomKeycard.GetKeycard(customKeycard),
UsableItem usable => usable switch
{
Scp330Bag scp330Bag => new Scp330(scp330Bag),
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
new file mode 100644
index 0000000000..260e1aa0cc
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
@@ -0,0 +1,184 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Items.Keycards
+{
+ using System;
+ using System.Linq;
+
+ using Exiled.API.Enums;
+ using Exiled.API.Extensions;
+ using Exiled.API.Interfaces.Keycards;
+
+ using Interactables.Interobjects.DoorUtils;
+ using InventorySystem.Items;
+ using InventorySystem.Items.Keycards;
+
+ using UnityEngine;
+
+ ///
+ /// A base class for all keycard items.
+ ///
+ public abstract class CustomKeycard : Item
+ {
+ private CustomItemNameDetail itemNameDetail;
+ private bool itemNameSet;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The to encapsulate.
+ internal CustomKeycard(KeycardItem itemBase)
+ : base(itemBase)
+ {
+ }
+
+ ///
+ /// Gets or sets the permissions this keycard has.
+ ///
+ public KeycardPermissions Permissions
+ {
+ get => CustomPermsDetail.CustomPermissions.TryGetValue(Serial, out DoorPermissionFlags flags) ? (KeycardPermissions)flags : KeycardPermissions.None;
+
+ set
+ {
+ CustomPermsDetail.CustomPermissions[Serial] = (DoorPermissionFlags)value;
+
+ Resync();
+ }
+ }
+
+ ///
+ /// Gets or sets the color of this keycard's permissions.
+ ///
+ public Color PermissionsColor
+ {
+ get => Gfx.Material.Instance.GetColor(KeycardGfx.PermsColorHash);
+
+ set
+ {
+ Gfx.Material.Instance.SetColor(KeycardGfx.PermsColorHash, value);
+
+ Resync();
+ }
+ }
+
+ ///
+ /// Gets or sets the name of this keycard within the inventory.
+ ///
+ public string ItemName
+ {
+ get
+ {
+ if (!itemNameSet)
+ {
+ itemNameDetail = GetDetail();
+ itemNameSet = true;
+ }
+
+ return itemNameDetail.Name;
+ }
+
+ set
+ {
+ if (!itemNameSet)
+ {
+ itemNameDetail = GetDetail();
+ itemNameSet = true;
+ }
+
+ itemNameDetail.Name = value;
+
+ Resync();
+ }
+ }
+
+ ///
+ /// Gets or sets the color of this keycard.
+ ///
+ public Color Color
+ {
+ get => Gfx.Material.Instance.GetColor(KeycardGfx.TintColorHash);
+
+ set
+ {
+ Gfx.Material.Instance.SetColor(KeycardGfx.TintColorHash, value);
+
+ Resync();
+ }
+ }
+
+ ///
+ /// Gets the of this .
+ ///
+ public KeycardGfx Gfx => ((KeycardItem)Base).KeycardGfx;
+
+ ///
+ /// Resyncs all properties of the keycard.
+ /// Gets called by all setters by default.
+ ///
+ public void Resync()
+ {
+ // we loveeeeeeeeeeeee NW static fields trusttttttttttttttt I'm not mad at allllllllllll
+ CustomPermsDetail._customLevels = new KeycardLevels((DoorPermissionFlags)Permissions);
+ CustomPermsDetail._customColor = PermissionsColor;
+
+ CustomItemNameDetail._customText = ItemName;
+ CustomTintDetail._customColor = Color;
+
+ if (this is ILabelKeycard label)
+ {
+ CustomLabelDetail._customText = label.Label;
+ CustomLabelDetail._customColor = label.LabelColor;
+ }
+
+ if (this is INameTagKeycard holder)
+ NametagDetail._customNametag = holder.NameTag;
+
+ if (this is IWearKeycard wear)
+ CustomWearDetail._customWearLevel = wear.Wear;
+
+ if (this is ISerialLabelKeycard serial)
+ {
+ CustomSerialNumberDetail._customVal = serial.SerialLabel;
+ }
+
+ MirrorExtensions.ResyncKeycardItem(this);
+ }
+
+ ///
+ /// Gets a specific detail from a .
+ ///
+ /// The Type of SyncedDetail.
+ /// The first detail of the desired type. null if not found.
+ public T GetDetail()
+ where T : DetailBase
+ {
+ if (Base is not KeycardItem keycardItem)
+ return null;
+
+ return (T)keycardItem.Details.FirstOrDefault(detail => detail is T);
+ }
+
+ ///
+ /// Creates a based on its ItemType.
+ ///
+ /// The item to create the wrapper from.
+ /// The newly created .
+ internal static CustomKeycard GetKeycard(KeycardItem itemBase)
+ {
+ return itemBase.ItemTypeId switch
+ {
+ ItemType.KeycardCustomTaskForce => new TaskForceKeycard(itemBase),
+ ItemType.KeycardCustomSite02 => new Site02Keycard(itemBase),
+ ItemType.KeycardCustomManagement => new ManagementKeycard(itemBase),
+ ItemType.KeycardCustomMetalCase => new MetalKeycard(itemBase),
+ _ => throw new ArgumentOutOfRangeException(nameof(ItemType), itemBase.ItemTypeId.ToString()),
+ };
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/Keycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/Keycard.cs
deleted file mode 100644
index e8f991a6eb..0000000000
--- a/EXILED/Exiled.API/Features/Items/Keycards/Keycard.cs
+++ /dev/null
@@ -1,63 +0,0 @@
-// -----------------------------------------------------------------------
-//
-// Copyright (c) ExMod Team. All rights reserved.
-// Licensed under the CC BY-SA 3.0 license.
-//
-// -----------------------------------------------------------------------
-
-using InventorySystem.Items.Keycards;
-namespace Exiled.API.Features.Items.Keycards
-{
- using Exiled.API.Enums;
- using Exiled.API.Extensions;
-
- using InventorySystem.Items;
-
- ///
- /// A base class for all keycard items.
- ///
- public class Keycard : Item
- {
- private CustomPermsDetail permsDetail;
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The to encapsulate.
- public Keycard(ItemBase itemBase)
- : base(itemBase)
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The of the item to create.
- internal Keycard(ItemType type)
- : base(type)
- {
- }
-
- ///
- /// Gets or sets a value indicating the permissions this keycard has.
- ///
- public KeycardPermissions Permissions
- {
- get => permsDetail;
- set
- {
- permsDetail._customLevels.
- Resync();
- }
- }
-
- ///
- /// Resyncs all properties of the keycard.
- /// Gets called by all setters by default.
- ///
- public void Resync()
- {
- MirrorExtensions.ResyncKeycardItem(this);
- }
- }
-}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs
new file mode 100644
index 0000000000..f13862dbb1
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs
@@ -0,0 +1,55 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Items.Keycards
+{
+ using Exiled.API.Interfaces.Keycards;
+
+ using InventorySystem.Items;
+ using InventorySystem.Items.Keycards;
+
+ using UnityEngine;
+
+ ///
+ /// Represents the Management Custom Keycard.
+ ///
+ public class ManagementKeycard : CustomKeycard, ILabelKeycard
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The to encapsulate.
+ internal ManagementKeycard(KeycardItem itemBase)
+ : base(itemBase)
+ {
+ }
+
+ ///
+ public string Label
+ {
+ get => Gfx.KeycardLabels[0].text;
+
+ set
+ {
+ Gfx.KeycardLabels[0].text = value;
+ Resync();
+ }
+ }
+
+ ///
+ public Color LabelColor
+ {
+ get => Gfx.KeycardLabels[0].color;
+
+ set
+ {
+ Gfx.KeycardLabels[0].color = value;
+ Resync();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs
new file mode 100644
index 0000000000..d440f34a77
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs
@@ -0,0 +1,150 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Items.Keycards
+{
+ using System.Text;
+
+ using Exiled.API.Features.Pools;
+ using Exiled.API.Interfaces.Keycards;
+
+ using InventorySystem.Items;
+ using InventorySystem.Items.Keycards;
+
+ using UnityEngine;
+
+ ///
+ /// Represents the Metal Custom Keycard.
+ ///
+ public class MetalKeycard : CustomKeycard, INameTagKeycard, ILabelKeycard, IWearKeycard, ISerialLabelKeycard
+ {
+ private CustomSerialNumberDetail serialNumberDetail;
+ private bool serialNumberSet;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The to encapsulate.
+ internal MetalKeycard(KeycardItem itemBase)
+ : base(itemBase)
+ {
+ }
+
+ ///
+ public string NameTag
+ {
+ get => Gfx.NameFields[0].text;
+
+ set
+ {
+ Gfx.NameFields[0].text = value;
+ Resync();
+ }
+ }
+
+ ///
+ public string Label
+ {
+ get => Gfx.KeycardLabels[0].text;
+
+ set
+ {
+ Gfx.KeycardLabels[0].text = value;
+ Resync();
+ }
+ }
+
+ ///
+ public Color LabelColor
+ {
+ get => Gfx.KeycardLabels[0].color;
+
+ set
+ {
+ Gfx.KeycardLabels[0].color = value;
+ Resync();
+ }
+ }
+
+ ///
+ /// Capped from 0-4 for Site-02 keycards, returns 255 if no wear level is found.
+ public byte Wear
+ {
+ get
+ {
+ for (byte i = 0; i < Gfx.ElementVariants.Length; i++)
+ {
+ GameObject obj = Gfx.ElementVariants[i];
+
+ if (obj.activeSelf)
+ return i;
+ }
+
+ return byte.MaxValue;
+ }
+
+ set
+ {
+ for (byte i = 0; i < Gfx.ElementVariants.Length; i++)
+ {
+ Gfx.ElementVariants[i].SetActive(i == value);
+ }
+
+ Resync();
+ }
+ }
+
+ ///
+ public string SerialLabel
+ {
+ get
+ {
+ if (!serialNumberSet)
+ {
+ serialNumberDetail = GetDetail();
+ serialNumberSet = true;
+ }
+
+ StringBuilder builder = StringBuilderPool.Pool.Get(12);
+
+ foreach (Renderer digit in Gfx.SerialNumberDigits)
+ {
+ int index = SerialNumberDetail.DigitMats[serialNumberDetail._sourceMaterial].IndexOf(digit.sharedMaterial);
+
+ if (index is 10)
+ {
+ builder.Append('-');
+ continue;
+ }
+
+ builder.Append(index);
+ }
+
+ return StringBuilderPool.Pool.ToStringReturn(builder);
+ }
+
+ set
+ {
+ if (!serialNumberSet)
+ {
+ serialNumberDetail = GetDetail();
+ serialNumberSet = true;
+ }
+
+ if (value.Length > 12)
+ value = value.Substring(0, 12);
+
+ foreach (Renderer digit in Gfx.SerialNumberDigits)
+ {
+ digit.sharedMaterial = serialNumberDetail.GetDigitMaterial(value[0] - 48);
+ }
+
+ Resync();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
new file mode 100644
index 0000000000..29256dd34b
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
@@ -0,0 +1,95 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Items.Keycards
+{
+ using Exiled.API.Interfaces.Keycards;
+
+ using InventorySystem.Items;
+ using InventorySystem.Items.Keycards;
+
+ using UnityEngine;
+
+ ///
+ /// Represents the Site-02 Custom Keycard.
+ ///
+ public class Site02Keycard : CustomKeycard, INameTagKeycard, ILabelKeycard, IWearKeycard
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The to encapsulate.
+ internal Site02Keycard(KeycardItem itemBase)
+ : base(itemBase)
+ {
+ }
+
+ ///
+ public string NameTag
+ {
+ get => Gfx.NameFields[0].text;
+
+ set
+ {
+ Gfx.NameFields[0].text = value;
+ Resync();
+ }
+ }
+
+ ///
+ public string Label
+ {
+ get => Gfx.KeycardLabels[0].text;
+
+ set
+ {
+ Gfx.KeycardLabels[0].text = value;
+ Resync();
+ }
+ }
+
+ ///
+ public Color LabelColor
+ {
+ get => Gfx.KeycardLabels[0].color;
+
+ set
+ {
+ Gfx.KeycardLabels[0].color = value;
+ Resync();
+ }
+ }
+
+ ///
+ /// Capped from 0-4 for Site-02 keycards, returns 255 if no wear level is found.
+ public byte Wear
+ {
+ get
+ {
+ for (byte i = 0; i < Gfx.ElementVariants.Length; i++)
+ {
+ GameObject obj = Gfx.ElementVariants[i];
+
+ if (obj.activeSelf)
+ return i;
+ }
+
+ return byte.MaxValue;
+ }
+
+ set
+ {
+ for (byte i = 0; i < Gfx.ElementVariants.Length; i++)
+ {
+ Gfx.ElementVariants[i].SetActive(i == value);
+ }
+
+ Resync();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs
new file mode 100644
index 0000000000..cf45549706
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs
@@ -0,0 +1,128 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Items.Keycards
+{
+ using System.Text;
+
+ using Exiled.API.Features.Pools;
+ using Exiled.API.Interfaces.Keycards;
+
+ using InventorySystem.Items;
+ using InventorySystem.Items.Keycards;
+
+ using UnityEngine;
+
+ ///
+ /// Represents the Task Force Custom Keycard.
+ ///
+ public class TaskForceKeycard : CustomKeycard, INameTagKeycard, ISerialLabelKeycard, IRankKeycard
+ {
+ private CustomSerialNumberDetail serialNumberDetail;
+ private bool serialNumberSet;
+
+ private CustomRankDetail rankDetail;
+ private bool rankDetailSet;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The to encapsulate.
+ internal TaskForceKeycard(KeycardItem itemBase)
+ : base(itemBase)
+ {
+ }
+
+ ///
+ public string NameTag
+ {
+ get => Gfx.NameFields[0].text;
+
+ set
+ {
+ Gfx.NameFields[0].text = value;
+ Resync();
+ }
+ }
+
+ ///
+ public string SerialLabel
+ {
+ get
+ {
+ if (!serialNumberSet)
+ {
+ serialNumberDetail = GetDetail();
+ serialNumberSet = true;
+ }
+
+ StringBuilder builder = StringBuilderPool.Pool.Get(12);
+
+ foreach (Renderer digit in Gfx.SerialNumberDigits)
+ {
+ int index = SerialNumberDetail.DigitMats[serialNumberDetail._sourceMaterial].IndexOf(digit.sharedMaterial);
+
+ if (index is 10)
+ {
+ builder.Append('-');
+ continue;
+ }
+
+ builder.Append(index);
+ }
+
+ return StringBuilderPool.Pool.ToStringReturn(builder);
+ }
+
+ set
+ {
+ if (!serialNumberSet)
+ {
+ serialNumberDetail = GetDetail();
+ serialNumberSet = true;
+ }
+
+ if (value.Length > 12)
+ value = value.Substring(0, 12);
+
+ foreach (Renderer digit in Gfx.SerialNumberDigits)
+ {
+ digit.sharedMaterial = serialNumberDetail.GetDigitMaterial(value[0] - 48);
+ }
+
+ Resync();
+ }
+ }
+
+ ///
+ public int Rank
+ {
+ get
+ {
+ if (!rankDetailSet)
+ {
+ rankDetail = GetDetail();
+ rankDetailSet = true;
+ }
+
+ return rankDetail._options.IndexOf(Gfx.RankFilter.sharedMesh);
+ }
+
+ set
+ {
+ if (!rankDetailSet)
+ {
+ rankDetail = GetDetail();
+ rankDetailSet = true;
+ }
+
+ Gfx.RankFilter.sharedMesh = rankDetail._options[Mathf.Clamp(value, 0, 3)];
+ Resync();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Interfaces/Keycards/ILabelKeycard.cs b/EXILED/Exiled.API/Interfaces/Keycards/ILabelKeycard.cs
new file mode 100644
index 0000000000..b5f9dcc0a6
--- /dev/null
+++ b/EXILED/Exiled.API/Interfaces/Keycards/ILabelKeycard.cs
@@ -0,0 +1,28 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Interfaces.Keycards
+{
+ using Exiled.API.Features.Items.Keycards;
+ using UnityEngine;
+
+ ///
+ /// An interface for 's with the property.
+ ///
+ public interface ILabelKeycard
+ {
+ ///
+ /// Gets or sets the label of this .
+ ///
+ public string Label { get; set; }
+
+ ///
+ /// Gets or sets the of this .
+ ///
+ public Color LabelColor { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Interfaces/Keycards/INameTagKeycard.cs b/EXILED/Exiled.API/Interfaces/Keycards/INameTagKeycard.cs
new file mode 100644
index 0000000000..4b035fdb28
--- /dev/null
+++ b/EXILED/Exiled.API/Interfaces/Keycards/INameTagKeycard.cs
@@ -0,0 +1,22 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Interfaces.Keycards
+{
+ using Exiled.API.Features.Items.Keycards;
+
+ ///
+ /// An interface for 's with the property.
+ ///
+ public interface INameTagKeycard
+ {
+ ///
+ /// Gets or sets the name of the owner of this .
+ ///
+ public string NameTag { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Interfaces/Keycards/IRankKeycard.cs b/EXILED/Exiled.API/Interfaces/Keycards/IRankKeycard.cs
new file mode 100644
index 0000000000..e0ad339a3f
--- /dev/null
+++ b/EXILED/Exiled.API/Interfaces/Keycards/IRankKeycard.cs
@@ -0,0 +1,23 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Interfaces.Keycards
+{
+ using Exiled.API.Features.Items.Keycards;
+
+ ///
+ /// An interface for 's with the property.
+ ///
+ public interface IRankKeycard
+ {
+ ///
+ /// Gets or sets the rank of this .
+ ///
+ /// Capped from 0-3.
+ public int Rank { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Interfaces/Keycards/ISerialLabelKeycard.cs b/EXILED/Exiled.API/Interfaces/Keycards/ISerialLabelKeycard.cs
new file mode 100644
index 0000000000..7c3c9b1846
--- /dev/null
+++ b/EXILED/Exiled.API/Interfaces/Keycards/ISerialLabelKeycard.cs
@@ -0,0 +1,23 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Interfaces.Keycards
+{
+ using Exiled.API.Features.Items.Keycards;
+
+ ///
+ /// An interface for 's with the property.
+ ///
+ public interface ISerialLabelKeycard
+ {
+ ///
+ /// Gets or sets the serial label of this .
+ ///
+ /// Can only hold 12 numbers. Non-numerical chars will be replaced with "-".
+ public string SerialLabel { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Interfaces/Keycards/IWearKeycard.cs b/EXILED/Exiled.API/Interfaces/Keycards/IWearKeycard.cs
new file mode 100644
index 0000000000..8a29572a5a
--- /dev/null
+++ b/EXILED/Exiled.API/Interfaces/Keycards/IWearKeycard.cs
@@ -0,0 +1,22 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Interfaces.Keycards
+{
+ using Exiled.API.Features.Items.Keycards;
+
+ ///
+ /// An interface for 's with the property.
+ ///
+ public interface IWearKeycard
+ {
+ ///
+ /// Gets or sets the wear on this .
+ ///
+ public byte Wear { get; set; }
+ }
+}
\ No newline at end of file
From 002e540e7ca177c22391678d9e0f89aaadea9c43 Mon Sep 17 00:00:00 2001
From: "@Someone" <45270312+Someone-193@users.noreply.github.com>
Date: Wed, 20 Aug 2025 14:07:47 -0400
Subject: [PATCH 03/38] Fix stuff
---
EXILED/Exiled.API/Features/Items/Item.cs | 3 +-
.../Features/Items/Keycards/CustomKeycard.cs | 35 ++++++++++++++++---
.../Items/Keycards/ManagementKeycard.cs | 9 +++++
.../Features/Items/Keycards/MetalKeycard.cs | 9 +++++
.../Features/Items/Keycards/Site02Keycard.cs | 9 +++++
.../Items/Keycards/TaskForceKeycard.cs | 9 +++++
6 files changed, 68 insertions(+), 6 deletions(-)
diff --git a/EXILED/Exiled.API/Features/Items/Item.cs b/EXILED/Exiled.API/Features/Items/Item.cs
index 13ec2a7c2a..38c7669cea 100644
--- a/EXILED/Exiled.API/Features/Items/Item.cs
+++ b/EXILED/Exiled.API/Features/Items/Item.cs
@@ -306,7 +306,8 @@ public static T Get(ushort serial)
public static Item Create(ItemType type, Player owner = null) => type.GetTemplate() switch
{
InventorySystem.Items.Firearms.Firearm => new Firearm(type),
- KeycardItem => new Keycard(type),
+ KeycardItem when !type.IsCustomKeycard() => new Keycard(type),
+ KeycardItem => CustomKeycard.GetKeycard(type),
UsableItem usable => usable switch
{
Scp330Bag => new Scp330(),
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
index 260e1aa0cc..765caa728b 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
@@ -10,7 +10,6 @@ namespace Exiled.API.Features.Items.Keycards
using System;
using System.Linq;
- using Exiled.API.Enums;
using Exiled.API.Extensions;
using Exiled.API.Interfaces.Keycards;
@@ -37,16 +36,25 @@ internal CustomKeycard(KeycardItem itemBase)
{
}
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The of the item to create.
+ internal CustomKeycard(ItemType itemType)
+ : base(itemType)
+ {
+ }
+
///
/// Gets or sets the permissions this keycard has.
///
- public KeycardPermissions Permissions
+ public KeycardLevels Permissions
{
- get => CustomPermsDetail.CustomPermissions.TryGetValue(Serial, out DoorPermissionFlags flags) ? (KeycardPermissions)flags : KeycardPermissions.None;
+ get => CustomPermsDetail.CustomPermissions.TryGetValue(Serial, out DoorPermissionFlags flags) ? new KeycardLevels(flags) : new KeycardLevels(0, 0, 0);
set
{
- CustomPermsDetail.CustomPermissions[Serial] = (DoorPermissionFlags)value;
+ CustomPermsDetail.CustomPermissions[Serial] = value.Permissions;
Resync();
}
@@ -124,7 +132,7 @@ public Color Color
public void Resync()
{
// we loveeeeeeeeeeeee NW static fields trusttttttttttttttt I'm not mad at allllllllllll
- CustomPermsDetail._customLevels = new KeycardLevels((DoorPermissionFlags)Permissions);
+ CustomPermsDetail._customLevels = Permissions;
CustomPermsDetail._customColor = PermissionsColor;
CustomItemNameDetail._customText = ItemName;
@@ -180,5 +188,22 @@ internal static CustomKeycard GetKeycard(KeycardItem itemBase)
_ => throw new ArgumentOutOfRangeException(nameof(ItemType), itemBase.ItemTypeId.ToString()),
};
}
+
+ ///
+ /// Creates a based on its ItemType.
+ ///
+ /// The type to create the wrapper from.
+ /// The newly created .
+ internal static CustomKeycard GetKeycard(ItemType type)
+ {
+ return type switch
+ {
+ ItemType.KeycardCustomTaskForce => new TaskForceKeycard(type),
+ ItemType.KeycardCustomSite02 => new Site02Keycard(type),
+ ItemType.KeycardCustomManagement => new ManagementKeycard(type),
+ ItemType.KeycardCustomMetalCase => new MetalKeycard(type),
+ _ => throw new ArgumentOutOfRangeException(nameof(ItemType), type.ToString()),
+ };
+ }
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs
index f13862dbb1..5480050714 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs
@@ -28,6 +28,15 @@ internal ManagementKeycard(KeycardItem itemBase)
{
}
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The of the item to create.
+ internal ManagementKeycard(ItemType itemType)
+ : base(itemType)
+ {
+ }
+
///
public string Label
{
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs
index d440f34a77..b9ec3e023b 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs
@@ -34,6 +34,15 @@ internal MetalKeycard(KeycardItem itemBase)
{
}
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The of the item to create.
+ internal MetalKeycard(ItemType itemType)
+ : base(itemType)
+ {
+ }
+
///
public string NameTag
{
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
index 29256dd34b..14b761151f 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
@@ -28,6 +28,15 @@ internal Site02Keycard(KeycardItem itemBase)
{
}
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The of the item to create.
+ internal Site02Keycard(ItemType itemType)
+ : base(itemType)
+ {
+ }
+
///
public string NameTag
{
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs
index cf45549706..0e2d703de7 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs
@@ -37,6 +37,15 @@ internal TaskForceKeycard(KeycardItem itemBase)
{
}
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The of the item to create.
+ internal TaskForceKeycard(ItemType itemType)
+ : base(itemType)
+ {
+ }
+
///
public string NameTag
{
From de1ada97b0bc3abb70eb638325db2e023a0f1399 Mon Sep 17 00:00:00 2001
From: "@Someone" <45270312+Someone-193@users.noreply.github.com>
Date: Wed, 20 Aug 2025 14:56:32 -0400
Subject: [PATCH 04/38] Add Create methods
---
.../Items/Keycards/ManagementKeycard.cs | 24 ++++++++++++++
.../Features/Items/Keycards/MetalKeycard.cs | 32 ++++++++++++++++++-
.../Features/Items/Keycards/Site02Keycard.cs | 28 ++++++++++++++++
.../Items/Keycards/TaskForceKeycard.cs | 26 +++++++++++++++
4 files changed, 109 insertions(+), 1 deletion(-)
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs
index 5480050714..fbfb269770 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs
@@ -9,6 +9,8 @@ namespace Exiled.API.Features.Items.Keycards
{
using Exiled.API.Interfaces.Keycards;
+ using Interactables.Interobjects.DoorUtils;
+
using InventorySystem.Items;
using InventorySystem.Items.Keycards;
@@ -60,5 +62,27 @@ public Color LabelColor
Resync();
}
}
+
+ ///
+ /// Creates a .
+ ///
+ /// The permissions of the keycard.
+ /// The color of the permissions of the keycard.
+ /// The inventory name of the keycard.
+ /// The color of the keycard.
+ /// The label on the keycard.
+ /// The color of the label on the keycard.
+ /// The new .
+ public static ManagementKeycard Create(KeycardLevels permissions, Color permissionsColor, string itemName, Color color, string label, Color labelColor)
+ {
+ ManagementKeycard keycard = (ManagementKeycard)Item.Create(ItemType.KeycardCustomManagement);
+ keycard.Permissions = permissions;
+ keycard.PermissionsColor = permissionsColor;
+ keycard.ItemName = itemName;
+ keycard.Color = color;
+ keycard.Label = label;
+ keycard.LabelColor = labelColor;
+ return keycard;
+ }
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs
index b9ec3e023b..fcd35934b7 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs
@@ -12,6 +12,8 @@ namespace Exiled.API.Features.Items.Keycards
using Exiled.API.Features.Pools;
using Exiled.API.Interfaces.Keycards;
+ using Interactables.Interobjects.DoorUtils;
+
using InventorySystem.Items;
using InventorySystem.Items.Keycards;
@@ -80,7 +82,7 @@ public Color LabelColor
}
///
- /// Capped from 0-4 for Site-02 keycards, returns 255 if no wear level is found.
+ /// Capped from 0-5 for Site-02 keycards, returns 255 if no wear level is found.
public byte Wear
{
get
@@ -155,5 +157,33 @@ public string SerialLabel
Resync();
}
}
+
+ ///
+ /// Creates a .
+ ///
+ /// The permissions of the keycard.
+ /// The color of the permissions of the keycard.
+ /// The inventory name of the keycard.
+ /// The color of the keycard.
+ /// The name of the owner of the keycard.
+ /// The label on the keycard.
+ /// The color of the label on the keycard.
+ /// How worn the keycard looks (capped from 0-5).
+ /// The serial label of the keycard (numbers only, 12 max).
+ /// The new .
+ public static MetalKeycard Create(KeycardLevels permissions, Color permissionsColor, string itemName, Color color, string nameTag, string label, Color labelColor, byte wear, string serialLabel)
+ {
+ MetalKeycard keycard = (MetalKeycard)Item.Create(ItemType.KeycardCustomManagement);
+ keycard.Permissions = permissions;
+ keycard.PermissionsColor = permissionsColor;
+ keycard.ItemName = itemName;
+ keycard.Color = color;
+ keycard.NameTag = nameTag;
+ keycard.Label = label;
+ keycard.LabelColor = labelColor;
+ keycard.Wear = wear;
+ keycard.SerialLabel = serialLabel;
+ return keycard;
+ }
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
index 14b761151f..eb1d25bca7 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
@@ -9,6 +9,8 @@ namespace Exiled.API.Features.Items.Keycards
{
using Exiled.API.Interfaces.Keycards;
+ using Interactables.Interobjects.DoorUtils;
+
using InventorySystem.Items;
using InventorySystem.Items.Keycards;
@@ -100,5 +102,31 @@ public byte Wear
Resync();
}
}
+
+ ///
+ /// Creates a .
+ ///
+ /// The permissions of the keycard.
+ /// The color of the permissions of the keycard.
+ /// The inventory name of the keycard.
+ /// The color of the keycard.
+ /// The name of the owner of the keycard.
+ /// The label on the keycard.
+ /// The color of the label on the keycard.
+ /// How worn the keycard looks (capped from 0-5).
+ /// The new .
+ public static Site02Keycard Create(KeycardLevels permissions, Color permissionsColor, string itemName, Color color, string nameTag, string label, Color labelColor, byte wear)
+ {
+ Site02Keycard keycard = (Site02Keycard)Item.Create(ItemType.KeycardCustomManagement);
+ keycard.Permissions = permissions;
+ keycard.PermissionsColor = permissionsColor;
+ keycard.ItemName = itemName;
+ keycard.Color = color;
+ keycard.NameTag = nameTag;
+ keycard.Label = label;
+ keycard.LabelColor = labelColor;
+ keycard.Wear = wear;
+ return keycard;
+ }
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs
index 0e2d703de7..3fdfccdbb4 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs
@@ -12,6 +12,8 @@ namespace Exiled.API.Features.Items.Keycards
using Exiled.API.Features.Pools;
using Exiled.API.Interfaces.Keycards;
+ using Interactables.Interobjects.DoorUtils;
+
using InventorySystem.Items;
using InventorySystem.Items.Keycards;
@@ -133,5 +135,29 @@ public int Rank
Resync();
}
}
+
+ ///
+ /// Creates a .
+ ///
+ /// The permissions of the keycard.
+ /// The color of the permissions of the keycard.
+ /// The inventory name of the keycard.
+ /// The color of the keycard.
+ /// The name of the owner of the keycard.
+ /// The serial label of the keycard (numbers only, 12 max).
+ /// The rank of the keycard (capped from 0-3).
+ /// The new .
+ public static TaskForceKeycard Create(KeycardLevels permissions, Color permissionsColor, string itemName, Color color, string nameTag, string serialLabel, int rank)
+ {
+ TaskForceKeycard keycard = (TaskForceKeycard)Item.Create(ItemType.KeycardCustomManagement);
+ keycard.Permissions = permissions;
+ keycard.PermissionsColor = permissionsColor;
+ keycard.ItemName = itemName;
+ keycard.Color = color;
+ keycard.NameTag = nameTag;
+ keycard.SerialLabel = serialLabel;
+ keycard.Rank = rank;
+ return keycard;
+ }
}
}
\ No newline at end of file
From 6ec426b31a16d385b23ab487190573b71640f079 Mon Sep 17 00:00:00 2001
From: Yamato
Date: Fri, 22 Aug 2025 21:17:35 +0200
Subject: [PATCH 05/38] I am Exceptionnally allowing this breaking change
---
EXILED/Exiled.API/Features/Items/Item.cs | 2 +-
EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs | 4 ++--
EXILED/Exiled.API/Features/Pickups/Pickup.cs | 4 ++--
EXILED/Exiled.API/Features/Pickups/Projectiles/Projectile.cs | 4 ++--
4 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/EXILED/Exiled.API/Features/Items/Item.cs b/EXILED/Exiled.API/Features/Items/Item.cs
index 38c7669cea..e8ebf3cfe8 100644
--- a/EXILED/Exiled.API/Features/Items/Item.cs
+++ b/EXILED/Exiled.API/Features/Items/Item.cs
@@ -366,7 +366,7 @@ public static T Get(ushort serial)
/// The who owns the item by default.
/// The specified type.
/// The created. This can be cast as a subclass.
- public static Item Create(ItemType type, Player owner = null) // TODO modify return type to "T"
+ public static T Create(ItemType type, Player owner = null)
where T : Item => Create(type, owner) as T;
///
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs
index 3fdfccdbb4..f2155686a3 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs
@@ -1,4 +1,4 @@
-// -----------------------------------------------------------------------
+// -----------------------------------------------------------------------
//
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
@@ -149,7 +149,7 @@ public int Rank
/// The new .
public static TaskForceKeycard Create(KeycardLevels permissions, Color permissionsColor, string itemName, Color color, string nameTag, string serialLabel, int rank)
{
- TaskForceKeycard keycard = (TaskForceKeycard)Item.Create(ItemType.KeycardCustomManagement);
+ TaskForceKeycard keycard = Create(ItemType.KeycardCustomManagement);
keycard.Permissions = permissions;
keycard.PermissionsColor = permissionsColor;
keycard.ItemName = itemName;
diff --git a/EXILED/Exiled.API/Features/Pickups/Pickup.cs b/EXILED/Exiled.API/Features/Pickups/Pickup.cs
index ab635fa81b..a610217fb3 100644
--- a/EXILED/Exiled.API/Features/Pickups/Pickup.cs
+++ b/EXILED/Exiled.API/Features/Pickups/Pickup.cs
@@ -532,7 +532,7 @@ public static IEnumerable Get(IEnumerable gameObjects)
/// The specified type.
/// The created .
///
- public static Pickup Create(ItemType type) // TODO modify return type to "T"
+ public static T Create(ItemType type)
where T : Pickup => Create(type) as T;
///
@@ -556,7 +556,7 @@ public static IEnumerable Get(IEnumerable gameObjects)
/// The specified type.
/// The . See documentation of for more information on casting.
///
- public static Pickup CreateAndSpawn(ItemType type, Vector3 position, Quaternion? rotation = null, Player previousOwner = null)
+ public static T CreateAndSpawn(ItemType type, Vector3 position, Quaternion? rotation = null, Player previousOwner = null)
where T : Pickup => CreateAndSpawn(type, position, rotation, previousOwner) as T;
///
diff --git a/EXILED/Exiled.API/Features/Pickups/Projectiles/Projectile.cs b/EXILED/Exiled.API/Features/Pickups/Projectiles/Projectile.cs
index 80a129eb67..f9d5b4f10d 100644
--- a/EXILED/Exiled.API/Features/Pickups/Projectiles/Projectile.cs
+++ b/EXILED/Exiled.API/Features/Pickups/Projectiles/Projectile.cs
@@ -111,7 +111,7 @@ internal Projectile(ItemType type)
/// The of the projectile.
/// The specified type.
/// The created .
- public static Projectile Create(ProjectileType projectiletype) // TODO modify return type to "T"
+ public static T Create(ProjectileType projectiletype)
where T : Projectile => Create(projectiletype) as T;
///
@@ -135,7 +135,7 @@ internal Projectile(ItemType type)
/// An optional previous owner of the item.
/// The specified type.
/// The . See documentation of for more information on casting.
- public static Projectile CreateAndSpawn(ProjectileType type, Vector3 position, Quaternion? rotation = null, bool shouldBeActive = true, Player previousOwner = null)
+ public static T CreateAndSpawn(ProjectileType type, Vector3 position, Quaternion? rotation = null, bool shouldBeActive = true, Player previousOwner = null)
where T : Projectile => CreateAndSpawn(type, position, rotation, shouldBeActive, previousOwner) as T;
///
From 869ed268e2cf54b413d13cfe1009114ed33643b3 Mon Sep 17 00:00:00 2001
From: Yamato
Date: Fri, 22 Aug 2025 21:20:18 +0200
Subject: [PATCH 06/38] do not look this
---
EXILED/Exiled.API/Features/Core/UserSettings/SettingBase.cs | 2 +-
EXILED/Exiled.API/Features/Items/Firearm.cs | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/EXILED/Exiled.API/Features/Core/UserSettings/SettingBase.cs b/EXILED/Exiled.API/Features/Core/UserSettings/SettingBase.cs
index b95b57b344..38b5132ec7 100644
--- a/EXILED/Exiled.API/Features/Core/UserSettings/SettingBase.cs
+++ b/EXILED/Exiled.API/Features/Core/UserSettings/SettingBase.cs
@@ -219,7 +219,7 @@ public static bool TryGetSetting(Player player, int id, out T setting)
/// New setting won't be synced with players.
///
public static T Create(ServerSpecificSettingBase settingBase)
- where T : SettingBase => (T)Create(settingBase);
+ where T : SettingBase => Create(settingBase) as T;
///
/// Syncs setting with all players.
diff --git a/EXILED/Exiled.API/Features/Items/Firearm.cs b/EXILED/Exiled.API/Features/Items/Firearm.cs
index 576ebf78ae..56215591af 100644
--- a/EXILED/Exiled.API/Features/Items/Firearm.cs
+++ b/EXILED/Exiled.API/Features/Items/Firearm.cs
@@ -361,7 +361,7 @@ public RecoilSettings Recoil
/// The type of firearm to create.
/// The newly created firearm.
public static Firearm Create(FirearmType type)
- => type is not FirearmType.None ? (Firearm)Create(type.GetItemType()) : null;
+ => type is not FirearmType.None ? Create(type.GetItemType()) : null;
///
/// Adds a to the firearm.
From 88fcf308eece2754147a91d23e0fbaaf5dcbeea5 Mon Sep 17 00:00:00 2001
From: Yamato
Date: Sat, 23 Aug 2025 14:43:35 +0200
Subject: [PATCH 07/38] Refactor keycard item creation logic
Moved custom keycard instantiation logic from CustomKeycard.cs to Item.cs, simplifying the process and removing redundant internal methods. Keycard creation now uses direct type checks and switch expressions for improved clarity and maintainability.
---
EXILED/Exiled.API/Features/Items/Item.cs | 37 +++++++++++++++----
.../Features/Items/Keycards/CustomKeycard.cs | 36 +-----------------
2 files changed, 30 insertions(+), 43 deletions(-)
diff --git a/EXILED/Exiled.API/Features/Items/Item.cs b/EXILED/Exiled.API/Features/Items/Item.cs
index e8ebf3cfe8..a44ac071e2 100644
--- a/EXILED/Exiled.API/Features/Items/Item.cs
+++ b/EXILED/Exiled.API/Features/Items/Item.cs
@@ -7,9 +7,6 @@
namespace Exiled.API.Features.Items
{
- using System.Collections.Generic;
- using System.Linq;
-
using Exiled.API.Extensions;
using Exiled.API.Features.Core;
using Exiled.API.Features.Items.Keycards;
@@ -32,8 +29,10 @@ namespace Exiled.API.Features.Items
using InventorySystem.Items.Usables.Scp1576;
using InventorySystem.Items.Usables.Scp244;
using InventorySystem.Items.Usables.Scp330;
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
using UnityEngine;
-
using BaseConsumable = InventorySystem.Items.Usables.Consumable;
///
@@ -218,8 +217,19 @@ public static Item Get(ItemBase itemBase)
return itemBase switch
{
InventorySystem.Items.Firearms.Firearm firearm => new Firearm(firearm),
- KeycardItem keycard when !itemBase.ItemTypeId.IsCustomKeycard() => new Keycard(keycard),
- KeycardItem customKeycard => CustomKeycard.GetKeycard(customKeycard),
+ KeycardItem keycard => keycard switch
+ {
+ ChaosKeycardItem chaosKeycardItem => new Keycard(chaosKeycardItem),
+ SingleUseKeycardItem singleUseKeycardItem => new Keycard(singleUseKeycardItem),
+ _ => keycard.ItemTypeId switch
+ {
+ ItemType.KeycardCustomTaskForce => new TaskForceKeycard(keycard),
+ ItemType.KeycardCustomSite02 => new Site02Keycard(keycard),
+ ItemType.KeycardCustomManagement => new ManagementKeycard(keycard),
+ ItemType.KeycardCustomMetalCase => new MetalKeycard(keycard),
+ _ => new Keycard(keycard),
+ }
+ },
UsableItem usable => usable switch
{
Scp330Bag scp330Bag => new Scp330(scp330Bag),
@@ -306,8 +316,19 @@ public static T Get(ushort serial)
public static Item Create(ItemType type, Player owner = null) => type.GetTemplate() switch
{
InventorySystem.Items.Firearms.Firearm => new Firearm(type),
- KeycardItem when !type.IsCustomKeycard() => new Keycard(type),
- KeycardItem => CustomKeycard.GetKeycard(type),
+ KeycardItem keycard => keycard switch
+ {
+ ChaosKeycardItem => new Keycard(type),
+ SingleUseKeycardItem => new Keycard(type),
+ _ => keycard.ItemTypeId switch
+ {
+ ItemType.KeycardCustomTaskForce => new TaskForceKeycard(type),
+ ItemType.KeycardCustomSite02 => new Site02Keycard(type),
+ ItemType.KeycardCustomManagement => new ManagementKeycard(type),
+ ItemType.KeycardCustomMetalCase => new MetalKeycard(type),
+ _ => new Keycard(type),
+ }
+ },
UsableItem usable => usable switch
{
Scp330Bag => new Scp330(),
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
index 765caa728b..a0ac9360ba 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
@@ -1,4 +1,4 @@
-// -----------------------------------------------------------------------
+// -----------------------------------------------------------------------
//
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
@@ -171,39 +171,5 @@ public T GetDetail()
return (T)keycardItem.Details.FirstOrDefault(detail => detail is T);
}
-
- ///
- /// Creates a based on its ItemType.
- ///
- /// The item to create the wrapper from.
- /// The newly created .
- internal static CustomKeycard GetKeycard(KeycardItem itemBase)
- {
- return itemBase.ItemTypeId switch
- {
- ItemType.KeycardCustomTaskForce => new TaskForceKeycard(itemBase),
- ItemType.KeycardCustomSite02 => new Site02Keycard(itemBase),
- ItemType.KeycardCustomManagement => new ManagementKeycard(itemBase),
- ItemType.KeycardCustomMetalCase => new MetalKeycard(itemBase),
- _ => throw new ArgumentOutOfRangeException(nameof(ItemType), itemBase.ItemTypeId.ToString()),
- };
- }
-
- ///
- /// Creates a based on its ItemType.
- ///
- /// The type to create the wrapper from.
- /// The newly created .
- internal static CustomKeycard GetKeycard(ItemType type)
- {
- return type switch
- {
- ItemType.KeycardCustomTaskForce => new TaskForceKeycard(type),
- ItemType.KeycardCustomSite02 => new Site02Keycard(type),
- ItemType.KeycardCustomManagement => new ManagementKeycard(type),
- ItemType.KeycardCustomMetalCase => new MetalKeycard(type),
- _ => throw new ArgumentOutOfRangeException(nameof(ItemType), type.ToString()),
- };
- }
}
}
\ No newline at end of file
From 471811a30592458c1a6ac4e86cfa02abd295dc47 Mon Sep 17 00:00:00 2001
From: Yamato
Date: Sat, 23 Aug 2025 15:08:31 +0200
Subject: [PATCH 08/38] Fix using error
---
EXILED/Exiled.API/Features/Items/Item.cs | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/EXILED/Exiled.API/Features/Items/Item.cs b/EXILED/Exiled.API/Features/Items/Item.cs
index a44ac071e2..f910af56c5 100644
--- a/EXILED/Exiled.API/Features/Items/Item.cs
+++ b/EXILED/Exiled.API/Features/Items/Item.cs
@@ -7,6 +7,9 @@
namespace Exiled.API.Features.Items
{
+ using System.Collections.Generic;
+ using System.Linq;
+
using Exiled.API.Extensions;
using Exiled.API.Features.Core;
using Exiled.API.Features.Items.Keycards;
@@ -29,10 +32,8 @@ namespace Exiled.API.Features.Items
using InventorySystem.Items.Usables.Scp1576;
using InventorySystem.Items.Usables.Scp244;
using InventorySystem.Items.Usables.Scp330;
- using System;
- using System.Collections.Generic;
- using System.Linq;
using UnityEngine;
+
using BaseConsumable = InventorySystem.Items.Usables.Consumable;
///
From 30c87515d4d5d7d0d6f33b9b9fd2d00da1ca9bde Mon Sep 17 00:00:00 2001
From: "@Someone" <45270312+Someone-193@users.noreply.github.com>
Date: Tue, 26 Aug 2025 19:09:51 -0400
Subject: [PATCH 09/38] Many headaches
WE LOVEE NWWW I LOVE NON-INSTANCED GFX YIPEEEEEEEEE
(things might be still borked btw)
---
.../Features/Items/Keycards/CustomKeycard.cs | 74 +++++++++++----
.../Items/Keycards/ManagementKeycard.cs | 14 +--
.../Features/Items/Keycards/MetalKeycard.cs | 94 ++++---------------
.../Features/Items/Keycards/Site02Keycard.cs | 36 +++----
.../Items/Keycards/TaskForceKeycard.cs | 91 ++++--------------
.../Interfaces/Keycards/IRankKeycard.cs | 4 +-
...abelKeycard.cs => ISerialNumberKeycard.cs} | 10 +-
.../Patches/Fixes/NameTagDetailFix.cs | 57 +++++++++++
.../KeycardDetails/CustomLabelDetailData.cs | 84 +++++++++++++++++
.../KeycardDetails/CustomPermsDetailData.cs | 48 ++++++++++
.../KeycardDetails/CustomRankDetailData.cs | 87 +++++++++++++++++
.../CustomSerialNumberDetailData.cs | 68 ++++++++++++++
.../KeycardDetails/CustomTintDetailData.cs | 71 ++++++++++++++
.../KeycardDetails/CustomWearDetailData.cs | 70 ++++++++++++++
.../KeycardDetails/NameTagDetailData.cs | 71 ++++++++++++++
15 files changed, 673 insertions(+), 206 deletions(-)
rename EXILED/Exiled.API/Interfaces/Keycards/{ISerialLabelKeycard.cs => ISerialNumberKeycard.cs} (69%)
create mode 100644 EXILED/Exiled.Events/Patches/Fixes/NameTagDetailFix.cs
create mode 100644 EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomLabelDetailData.cs
create mode 100644 EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomPermsDetailData.cs
create mode 100644 EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomRankDetailData.cs
create mode 100644 EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomSerialNumberDetailData.cs
create mode 100644 EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomTintDetailData.cs
create mode 100644 EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomWearDetailData.cs
create mode 100644 EXILED/Exiled.Events/Patches/Generic/KeycardDetails/NameTagDetailData.cs
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
index a0ac9360ba..c6f517c02d 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
@@ -7,13 +7,15 @@
namespace Exiled.API.Features.Items.Keycards
{
- using System;
+ using System.Collections.Generic;
using System.Linq;
using Exiled.API.Extensions;
+ using Exiled.API.Interfaces;
using Exiled.API.Interfaces.Keycards;
using Interactables.Interobjects.DoorUtils;
+
using InventorySystem.Items;
using InventorySystem.Items.Keycards;
@@ -22,7 +24,7 @@ namespace Exiled.API.Features.Items.Keycards
///
/// A base class for all keycard items.
///
- public abstract class CustomKeycard : Item
+ public abstract class CustomKeycard : Item, IWrapper
{
private CustomItemNameDetail itemNameDetail;
private bool itemNameSet;
@@ -34,17 +36,23 @@ public abstract class CustomKeycard : Item
internal CustomKeycard(KeycardItem itemBase)
: base(itemBase)
{
+ Base = itemBase;
}
///
/// Initializes a new instance of the class.
///
- /// The of the item to create.
- internal CustomKeycard(ItemType itemType)
- : base(itemType)
+ /// The of the item to create.
+ internal CustomKeycard(ItemType type)
+ : this((KeycardItem)Server.Host.Inventory.CreateItemInstance(new(type, 0), false))
{
}
+ ///
+ /// Gets the this encapsulates.
+ ///
+ public new KeycardItem Base { get; }
+
///
/// Gets or sets the permissions this keycard has.
///
@@ -65,11 +73,11 @@ public KeycardLevels Permissions
///
public Color PermissionsColor
{
- get => Gfx.Material.Instance.GetColor(KeycardGfx.PermsColorHash);
+ get => PermsColorDict.TryGetValue(Serial, out Color value) ? value : Color.black;
set
{
- Gfx.Material.Instance.SetColor(KeycardGfx.PermsColorHash, value);
+ PermsColorDict[Serial] = value;
Resync();
}
@@ -110,20 +118,55 @@ public string ItemName
///
public Color Color
{
- get => Gfx.Material.Instance.GetColor(KeycardGfx.TintColorHash);
+ get => ColorDict.TryGetValue(Serial, out Color value) ? value : Color.black;
set
{
- Gfx.Material.Instance.SetColor(KeycardGfx.TintColorHash, value);
+ ColorDict[Serial] = value;
Resync();
}
}
///
- /// Gets the of this .
+ /// Gets a dictionary of item serials to their permissions color.
+ ///
+ internal static Dictionary PermsColorDict { get; } = new();
+
+ ///
+ /// Gets a dictionary of item serials to their color.
+ ///
+ internal static Dictionary ColorDict { get; } = new();
+
+ ///
+ /// Gets a dictionary of item serials to their name tag.
+ ///
+ internal static Dictionary NameTagDict { get; } = new();
+
+ ///
+ /// Gets a dictionary of item serials to their label.
///
- public KeycardGfx Gfx => ((KeycardItem)Base).KeycardGfx;
+ internal static Dictionary LabelDict { get; } = new();
+
+ ///
+ /// Gets a dictionary of item serials to their label's color.
+ ///
+ internal static Dictionary LabelColorDict { get; } = new();
+
+ ///
+ /// Gets a dictionary of item serials to their wear.
+ ///
+ internal static Dictionary WearDict { get; } = new();
+
+ ///
+ /// Gets a dictionary of item serials to their serial number.
+ ///
+ internal static Dictionary SerialNumberDict { get; } = new();
+
+ ///
+ /// Gets a dictionary of item serials to their serial number.
+ ///
+ internal static Dictionary RankDict { get; } = new();
///
/// Resyncs all properties of the keycard.
@@ -150,9 +193,9 @@ public void Resync()
if (this is IWearKeycard wear)
CustomWearDetail._customWearLevel = wear.Wear;
- if (this is ISerialLabelKeycard serial)
+ if (this is ISerialNumberKeycard serial)
{
- CustomSerialNumberDetail._customVal = serial.SerialLabel;
+ CustomSerialNumberDetail._customVal = serial.SerialNumber;
}
MirrorExtensions.ResyncKeycardItem(this);
@@ -166,10 +209,7 @@ public void Resync()
public T GetDetail()
where T : DetailBase
{
- if (Base is not KeycardItem keycardItem)
- return null;
-
- return (T)keycardItem.Details.FirstOrDefault(detail => detail is T);
+ return (T)Base.Details.First(detail => detail is T);
}
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs
index fbfb269770..b84702d766 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs
@@ -33,20 +33,20 @@ internal ManagementKeycard(KeycardItem itemBase)
///
/// Initializes a new instance of the class.
///
- /// The of the item to create.
- internal ManagementKeycard(ItemType itemType)
- : base(itemType)
+ /// The of the item to create.
+ internal ManagementKeycard(ItemType type)
+ : base(type)
{
}
///
public string Label
{
- get => Gfx.KeycardLabels[0].text;
+ get => LabelDict.TryGetValue(Serial, out string value) ? value : string.Empty;
set
{
- Gfx.KeycardLabels[0].text = value;
+ LabelDict[Serial] = value;
Resync();
}
}
@@ -54,11 +54,11 @@ public string Label
///
public Color LabelColor
{
- get => Gfx.KeycardLabels[0].color;
+ get => LabelColorDict.TryGetValue(Serial, out Color value) ? value : Color.black;
set
{
- Gfx.KeycardLabels[0].color = value;
+ LabelColorDict[Serial] = value;
Resync();
}
}
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs
index fcd35934b7..eb1c8eebe7 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs
@@ -7,9 +7,6 @@
namespace Exiled.API.Features.Items.Keycards
{
- using System.Text;
-
- using Exiled.API.Features.Pools;
using Exiled.API.Interfaces.Keycards;
using Interactables.Interobjects.DoorUtils;
@@ -22,11 +19,8 @@ namespace Exiled.API.Features.Items.Keycards
///
/// Represents the Metal Custom Keycard.
///
- public class MetalKeycard : CustomKeycard, INameTagKeycard, ILabelKeycard, IWearKeycard, ISerialLabelKeycard
+ public class MetalKeycard : CustomKeycard, INameTagKeycard, ILabelKeycard, IWearKeycard, ISerialNumberKeycard
{
- private CustomSerialNumberDetail serialNumberDetail;
- private bool serialNumberSet;
-
///
/// Initializes a new instance of the class.
///
@@ -39,20 +33,20 @@ internal MetalKeycard(KeycardItem itemBase)
///
/// Initializes a new instance of the class.
///
- /// The of the item to create.
- internal MetalKeycard(ItemType itemType)
- : base(itemType)
+ /// The of the item to create.
+ internal MetalKeycard(ItemType type)
+ : base(type)
{
}
///
public string NameTag
{
- get => Gfx.NameFields[0].text;
+ get => NameTagDict.TryGetValue(Serial, out string value) ? value : string.Empty;
set
{
- Gfx.NameFields[0].text = value;
+ NameTagDict[Serial] = value;
Resync();
}
}
@@ -60,11 +54,11 @@ public string NameTag
///
public string Label
{
- get => Gfx.KeycardLabels[0].text;
+ get => LabelDict.TryGetValue(Serial, out string value) ? value : string.Empty;
set
{
- Gfx.KeycardLabels[0].text = value;
+ LabelDict[Serial] = value;
Resync();
}
}
@@ -72,11 +66,11 @@ public string Label
///
public Color LabelColor
{
- get => Gfx.KeycardLabels[0].color;
+ get => LabelColorDict.TryGetValue(Serial, out Color value) ? value : Color.black;
set
{
- Gfx.KeycardLabels[0].color = value;
+ LabelColorDict[Serial] = value;
Resync();
}
}
@@ -85,74 +79,24 @@ public Color LabelColor
/// Capped from 0-5 for Site-02 keycards, returns 255 if no wear level is found.
public byte Wear
{
- get
- {
- for (byte i = 0; i < Gfx.ElementVariants.Length; i++)
- {
- GameObject obj = Gfx.ElementVariants[i];
-
- if (obj.activeSelf)
- return i;
- }
-
- return byte.MaxValue;
- }
+ get => WearDict.TryGetValue(Serial, out byte value) ? value : (byte)255;
set
{
- for (byte i = 0; i < Gfx.ElementVariants.Length; i++)
- {
- Gfx.ElementVariants[i].SetActive(i == value);
- }
+ WearDict[Serial] = value;
Resync();
}
}
- ///
- public string SerialLabel
+ ///
+ public string SerialNumber
{
- get
- {
- if (!serialNumberSet)
- {
- serialNumberDetail = GetDetail();
- serialNumberSet = true;
- }
-
- StringBuilder builder = StringBuilderPool.Pool.Get(12);
-
- foreach (Renderer digit in Gfx.SerialNumberDigits)
- {
- int index = SerialNumberDetail.DigitMats[serialNumberDetail._sourceMaterial].IndexOf(digit.sharedMaterial);
-
- if (index is 10)
- {
- builder.Append('-');
- continue;
- }
-
- builder.Append(index);
- }
-
- return StringBuilderPool.Pool.ToStringReturn(builder);
- }
+ get => SerialNumberDict.TryGetValue(Serial, out string value) ? value : string.Empty;
set
{
- if (!serialNumberSet)
- {
- serialNumberDetail = GetDetail();
- serialNumberSet = true;
- }
-
- if (value.Length > 12)
- value = value.Substring(0, 12);
-
- foreach (Renderer digit in Gfx.SerialNumberDigits)
- {
- digit.sharedMaterial = serialNumberDetail.GetDigitMaterial(value[0] - 48);
- }
+ SerialNumberDict[Serial] = value;
Resync();
}
@@ -169,9 +113,9 @@ public string SerialLabel
/// The label on the keycard.
/// The color of the label on the keycard.
/// How worn the keycard looks (capped from 0-5).
- /// The serial label of the keycard (numbers only, 12 max).
+ /// The serial number of the keycard (numbers only, 12 max).
/// The new .
- public static MetalKeycard Create(KeycardLevels permissions, Color permissionsColor, string itemName, Color color, string nameTag, string label, Color labelColor, byte wear, string serialLabel)
+ public static MetalKeycard Create(KeycardLevels permissions, Color permissionsColor, string itemName, Color color, string nameTag, string label, Color labelColor, byte wear, string serialNumber)
{
MetalKeycard keycard = (MetalKeycard)Item.Create(ItemType.KeycardCustomManagement);
keycard.Permissions = permissions;
@@ -182,7 +126,7 @@ public static MetalKeycard Create(KeycardLevels permissions, Color permissionsCo
keycard.Label = label;
keycard.LabelColor = labelColor;
keycard.Wear = wear;
- keycard.SerialLabel = serialLabel;
+ keycard.SerialNumber = serialNumber;
return keycard;
}
}
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
index eb1d25bca7..cd0fd967b1 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
@@ -33,20 +33,20 @@ internal Site02Keycard(KeycardItem itemBase)
///
/// Initializes a new instance of the class.
///
- /// The of the item to create.
- internal Site02Keycard(ItemType itemType)
- : base(itemType)
+ /// The of the item to create.
+ internal Site02Keycard(ItemType type)
+ : base(type)
{
}
///
public string NameTag
{
- get => Gfx.NameFields[0].text;
+ get => NameTagDict.TryGetValue(Serial, out string value) ? value : string.Empty;
set
{
- Gfx.NameFields[0].text = value;
+ NameTagDict[Serial] = value;
Resync();
}
}
@@ -54,11 +54,11 @@ public string NameTag
///
public string Label
{
- get => Gfx.KeycardLabels[0].text;
+ get => LabelDict.TryGetValue(Serial, out string value) ? value : string.Empty;
set
{
- Gfx.KeycardLabels[0].text = value;
+ LabelDict[Serial] = value;
Resync();
}
}
@@ -66,11 +66,11 @@ public string Label
///
public Color LabelColor
{
- get => Gfx.KeycardLabels[0].color;
+ get => LabelColorDict.TryGetValue(Serial, out Color value) ? value : Color.black;
set
{
- Gfx.KeycardLabels[0].color = value;
+ LabelColorDict[Serial] = value;
Resync();
}
}
@@ -79,25 +79,11 @@ public Color LabelColor
/// Capped from 0-4 for Site-02 keycards, returns 255 if no wear level is found.
public byte Wear
{
- get
- {
- for (byte i = 0; i < Gfx.ElementVariants.Length; i++)
- {
- GameObject obj = Gfx.ElementVariants[i];
-
- if (obj.activeSelf)
- return i;
- }
-
- return byte.MaxValue;
- }
+ get => WearDict.TryGetValue(Serial, out byte value) ? value : (byte)255;
set
{
- for (byte i = 0; i < Gfx.ElementVariants.Length; i++)
- {
- Gfx.ElementVariants[i].SetActive(i == value);
- }
+ WearDict[Serial] = value;
Resync();
}
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs
index f2155686a3..d840267461 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs
@@ -7,9 +7,6 @@
namespace Exiled.API.Features.Items.Keycards
{
- using System.Text;
-
- using Exiled.API.Features.Pools;
using Exiled.API.Interfaces.Keycards;
using Interactables.Interobjects.DoorUtils;
@@ -22,14 +19,8 @@ namespace Exiled.API.Features.Items.Keycards
///
/// Represents the Task Force Custom Keycard.
///
- public class TaskForceKeycard : CustomKeycard, INameTagKeycard, ISerialLabelKeycard, IRankKeycard
+ public class TaskForceKeycard : CustomKeycard, INameTagKeycard, ISerialNumberKeycard, IRankKeycard
{
- private CustomSerialNumberDetail serialNumberDetail;
- private bool serialNumberSet;
-
- private CustomRankDetail rankDetail;
- private bool rankDetailSet;
-
///
/// Initializes a new instance of the class.
///
@@ -42,96 +33,46 @@ internal TaskForceKeycard(KeycardItem itemBase)
///
/// Initializes a new instance of the class.
///
- /// The of the item to create.
- internal TaskForceKeycard(ItemType itemType)
- : base(itemType)
+ /// The of the item to create.
+ internal TaskForceKeycard(ItemType type)
+ : base(type)
{
}
///
public string NameTag
{
- get => Gfx.NameFields[0].text;
+ get => NameTagDict.TryGetValue(Serial, out string value) ? value : string.Empty;
set
{
- Gfx.NameFields[0].text = value;
+ NameTagDict[Serial] = value;
Resync();
}
}
- ///
- public string SerialLabel
+ ///
+ public string SerialNumber
{
- get
- {
- if (!serialNumberSet)
- {
- serialNumberDetail = GetDetail();
- serialNumberSet = true;
- }
-
- StringBuilder builder = StringBuilderPool.Pool.Get(12);
-
- foreach (Renderer digit in Gfx.SerialNumberDigits)
- {
- int index = SerialNumberDetail.DigitMats[serialNumberDetail._sourceMaterial].IndexOf(digit.sharedMaterial);
-
- if (index is 10)
- {
- builder.Append('-');
- continue;
- }
-
- builder.Append(index);
- }
-
- return StringBuilderPool.Pool.ToStringReturn(builder);
- }
+ get => SerialNumberDict.TryGetValue(Serial, out string value) ? value : string.Empty;
set
{
- if (!serialNumberSet)
- {
- serialNumberDetail = GetDetail();
- serialNumberSet = true;
- }
-
- if (value.Length > 12)
- value = value.Substring(0, 12);
-
- foreach (Renderer digit in Gfx.SerialNumberDigits)
- {
- digit.sharedMaterial = serialNumberDetail.GetDigitMaterial(value[0] - 48);
- }
+ SerialNumberDict[Serial] = value;
Resync();
}
}
///
- public int Rank
+ public byte Rank
{
- get
- {
- if (!rankDetailSet)
- {
- rankDetail = GetDetail();
- rankDetailSet = true;
- }
-
- return rankDetail._options.IndexOf(Gfx.RankFilter.sharedMesh);
- }
+ get => RankDict.TryGetValue(Serial, out byte value) ? value : (byte)255;
set
{
- if (!rankDetailSet)
- {
- rankDetail = GetDetail();
- rankDetailSet = true;
- }
+ RankDict[Serial] = value;
- Gfx.RankFilter.sharedMesh = rankDetail._options[Mathf.Clamp(value, 0, 3)];
Resync();
}
}
@@ -144,10 +85,10 @@ public int Rank
/// The inventory name of the keycard.
/// The color of the keycard.
/// The name of the owner of the keycard.
- /// The serial label of the keycard (numbers only, 12 max).
+ /// The serial number of the keycard (numbers only, 12 max).
/// The rank of the keycard (capped from 0-3).
/// The new .
- public static TaskForceKeycard Create(KeycardLevels permissions, Color permissionsColor, string itemName, Color color, string nameTag, string serialLabel, int rank)
+ public static TaskForceKeycard Create(KeycardLevels permissions, Color permissionsColor, string itemName, Color color, string nameTag, string serialNumber, byte rank)
{
TaskForceKeycard keycard = Create(ItemType.KeycardCustomManagement);
keycard.Permissions = permissions;
@@ -155,7 +96,7 @@ public static TaskForceKeycard Create(KeycardLevels permissions, Color permissio
keycard.ItemName = itemName;
keycard.Color = color;
keycard.NameTag = nameTag;
- keycard.SerialLabel = serialLabel;
+ keycard.SerialNumber = serialNumber;
keycard.Rank = rank;
return keycard;
}
diff --git a/EXILED/Exiled.API/Interfaces/Keycards/IRankKeycard.cs b/EXILED/Exiled.API/Interfaces/Keycards/IRankKeycard.cs
index e0ad339a3f..0f8e7e74e1 100644
--- a/EXILED/Exiled.API/Interfaces/Keycards/IRankKeycard.cs
+++ b/EXILED/Exiled.API/Interfaces/Keycards/IRankKeycard.cs
@@ -17,7 +17,7 @@ public interface IRankKeycard
///
/// Gets or sets the rank of this .
///
- /// Capped from 0-3.
- public int Rank { get; set; }
+ /// Capped from 0-3, returns 255 if no value was found.
+ public byte Rank { get; set; }
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Interfaces/Keycards/ISerialLabelKeycard.cs b/EXILED/Exiled.API/Interfaces/Keycards/ISerialNumberKeycard.cs
similarity index 69%
rename from EXILED/Exiled.API/Interfaces/Keycards/ISerialLabelKeycard.cs
rename to EXILED/Exiled.API/Interfaces/Keycards/ISerialNumberKeycard.cs
index 7c3c9b1846..1bf0a1ba90 100644
--- a/EXILED/Exiled.API/Interfaces/Keycards/ISerialLabelKeycard.cs
+++ b/EXILED/Exiled.API/Interfaces/Keycards/ISerialNumberKeycard.cs
@@ -1,5 +1,5 @@
// -----------------------------------------------------------------------
-//
+//
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
//
@@ -10,14 +10,14 @@ namespace Exiled.API.Interfaces.Keycards
using Exiled.API.Features.Items.Keycards;
///
- /// An interface for 's with the property.
+ /// An interface for 's with the property.
///
- public interface ISerialLabelKeycard
+ public interface ISerialNumberKeycard
{
///
- /// Gets or sets the serial label of this .
+ /// Gets or sets the serial number of this .
///
/// Can only hold 12 numbers. Non-numerical chars will be replaced with "-".
- public string SerialLabel { get; set; }
+ public string SerialNumber { get; set; }
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Fixes/NameTagDetailFix.cs b/EXILED/Exiled.Events/Patches/Fixes/NameTagDetailFix.cs
new file mode 100644
index 0000000000..4f766c9b4f
--- /dev/null
+++ b/EXILED/Exiled.Events/Patches/Fixes/NameTagDetailFix.cs
@@ -0,0 +1,57 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.Patches.Fixes
+{
+ using System.Collections.Generic;
+ using System.Reflection.Emit;
+
+ using Exiled.API.Extensions;
+ using Exiled.API.Features.Pools;
+ using HarmonyLib;
+ using InventorySystem.Items;
+ using InventorySystem.Items.Keycards;
+ using Mirror;
+
+ using static HarmonyLib.AccessTools;
+
+ ///
+ /// Fixes NameTagDetail not using custom value if Custom Keycard was spawned as pickup.
+ ///
+ [HarmonyPatch(typeof(NametagDetail), nameof(NametagDetail.WriteNewPickup))]
+ public class NameTagDetailFix
+ {
+ private static IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator)
+ {
+ List newInstructions = ListPool.Pool.Get(instructions);
+
+ Label label = generator.DefineLabel();
+
+ newInstructions[0].WithLabels(label);
+ newInstructions.InsertRange(0, new CodeInstruction[]
+ {
+ // if (pickup.ItemId.TypeId.IsCustomKeycard)
+ new(OpCodes.Ldarg_1),
+ new(OpCodes.Callvirt, PropertyGetter(typeof(KeycardPickup), nameof(KeycardPickup.ItemId))),
+ new(OpCodes.Ldfld, Field(typeof(ItemIdentifier), nameof(ItemIdentifier.TypeId))),
+ new(OpCodes.Call, Method(typeof(ItemExtensions), nameof(ItemExtensions.IsCustomKeycard))),
+ new(OpCodes.Brfalse, label),
+
+ // writer.WriteString(_customNametag);
+ new(OpCodes.Ldarg_2),
+ new(OpCodes.Ldsfld, Field(typeof(NametagDetail), nameof(NametagDetail._customNametag))),
+ new(OpCodes.Call, Method(typeof(NetworkWriterExtensions), nameof(NetworkWriterExtensions.WriteString))),
+ new(OpCodes.Ret),
+ });
+
+ for (int i = 0; i < newInstructions.Count; i++)
+ yield return newInstructions[i];
+
+ ListPool.Pool.Return(newInstructions);
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomLabelDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomLabelDetailData.cs
new file mode 100644
index 0000000000..6195c60841
--- /dev/null
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomLabelDetailData.cs
@@ -0,0 +1,84 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.Patches.Generic.KeycardDetails
+{
+ using System.Collections.Generic;
+ using System.Reflection.Emit;
+
+ using Exiled.API.Features.Items.Keycards;
+ using Exiled.API.Features.Pools;
+ using HarmonyLib;
+ using InventorySystem.Items;
+ using InventorySystem.Items.Keycards;
+ using UnityEngine;
+
+ using static HarmonyLib.AccessTools;
+
+ ///
+ /// Patch for storing label and label color from custom keycards.
+ ///
+ [HarmonyPatch(typeof(CustomLabelDetail))]
+ public class CustomLabelDetailData
+ {
+ [HarmonyPatch(nameof(CustomLabelDetail.WriteNewItem))]
+ [HarmonyTranspiler]
+ private static IEnumerable Transpiler1(IEnumerable instructions)
+ {
+ List newInstructions = ListPool.Pool.Get(instructions);
+
+ newInstructions.InsertRange(0, new CodeInstruction[]
+ {
+ new(OpCodes.Call, PropertyGetter(typeof(CustomKeycard), nameof(CustomKeycard.LabelDict))),
+ new(OpCodes.Ldarg_1),
+ new(OpCodes.Callvirt, PropertyGetter(typeof(KeycardItem), nameof(KeycardItem.ItemSerial))),
+ new(OpCodes.Ldsfld, Field(typeof(CustomLabelDetail), nameof(CustomLabelDetail._customText))),
+ new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
+
+ new(OpCodes.Call, PropertyGetter(typeof(CustomKeycard), nameof(CustomKeycard.LabelColorDict))),
+ new(OpCodes.Ldarg_1),
+ new(OpCodes.Callvirt, PropertyGetter(typeof(KeycardItem), nameof(KeycardItem.ItemSerial))),
+ new(OpCodes.Ldsfld, Field(typeof(CustomLabelDetail), nameof(CustomLabelDetail._customColor))),
+ new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
+ });
+
+ for (int i = 0; i < newInstructions.Count; i++)
+ yield return newInstructions[i];
+
+ ListPool.Pool.Return(newInstructions);
+ }
+
+ [HarmonyPatch(nameof(CustomLabelDetail.WriteNewPickup))]
+ [HarmonyTranspiler]
+ private static IEnumerable Transpiler2(IEnumerable instructions)
+ {
+ List newInstructions = ListPool.Pool.Get(instructions);
+
+ newInstructions.InsertRange(0, new CodeInstruction[]
+ {
+ new(OpCodes.Call, PropertyGetter(typeof(CustomKeycard), nameof(CustomKeycard.LabelDict))),
+ new(OpCodes.Ldarg_1),
+ new(OpCodes.Callvirt, PropertyGetter(typeof(KeycardPickup), nameof(KeycardPickup.ItemId))),
+ new(OpCodes.Ldfld, Field(typeof(ItemIdentifier), nameof(ItemIdentifier.SerialNumber))),
+ new(OpCodes.Ldsfld, Field(typeof(CustomLabelDetail), nameof(CustomLabelDetail._customText))),
+ new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
+
+ new(OpCodes.Call, PropertyGetter(typeof(CustomKeycard), nameof(CustomKeycard.LabelColorDict))),
+ new(OpCodes.Ldarg_1),
+ new(OpCodes.Callvirt, PropertyGetter(typeof(KeycardPickup), nameof(KeycardPickup.ItemId))),
+ new(OpCodes.Ldfld, Field(typeof(ItemIdentifier), nameof(ItemIdentifier.SerialNumber))),
+ new(OpCodes.Ldsfld, Field(typeof(CustomLabelDetail), nameof(CustomLabelDetail._customColor))),
+ new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
+ });
+
+ for (int i = 0; i < newInstructions.Count; i++)
+ yield return newInstructions[i];
+
+ ListPool.Pool.Return(newInstructions);
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomPermsDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomPermsDetailData.cs
new file mode 100644
index 0000000000..c8f8e69fc1
--- /dev/null
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomPermsDetailData.cs
@@ -0,0 +1,48 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.Patches.Generic.KeycardDetails
+{
+ using System.Collections.Generic;
+ using System.Reflection.Emit;
+
+ using Exiled.API.Features.Items.Keycards;
+ using Exiled.API.Features.Pools;
+ using HarmonyLib;
+ using InventorySystem.Items;
+ using InventorySystem.Items.Keycards;
+ using UnityEngine;
+
+ using static HarmonyLib.AccessTools;
+
+ ///
+ /// Patch for storing permission colors from custom keycards.
+ ///
+ [HarmonyPatch(typeof(CustomPermsDetail), nameof(CustomPermsDetail.WriteCustom))]
+ public class CustomPermsDetailData
+ {
+ private static IEnumerable Transpiler(IEnumerable instructions)
+ {
+ List newInstructions = ListPool.Pool.Get(instructions);
+
+ newInstructions.InsertRange(0, new CodeInstruction[]
+ {
+ new(OpCodes.Call, PropertyGetter(typeof(CustomKeycard), nameof(CustomKeycard.PermsColorDict))),
+ new(OpCodes.Ldarg_1),
+ new(OpCodes.Callvirt, PropertyGetter(typeof(IIdentifierProvider), nameof(IIdentifierProvider.ItemId))),
+ new(OpCodes.Ldfld, Field(typeof(ItemIdentifier), nameof(ItemIdentifier.SerialNumber))),
+ new(OpCodes.Ldsfld, Field(typeof(CustomPermsDetail), nameof(CustomPermsDetail._customColor))),
+ new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
+ });
+
+ for (int i = 0; i < newInstructions.Count; i++)
+ yield return newInstructions[i];
+
+ ListPool.Pool.Return(newInstructions);
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomRankDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomRankDetailData.cs
new file mode 100644
index 0000000000..31ccb0c2c6
--- /dev/null
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomRankDetailData.cs
@@ -0,0 +1,87 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.Patches.Generic.KeycardDetails
+{
+ using System.Collections.Generic;
+ using System.Reflection.Emit;
+
+ using Exiled.API.Features.Items.Keycards;
+ using Exiled.API.Features.Pools;
+ using HarmonyLib;
+ using InventorySystem.Items;
+ using InventorySystem.Items.Keycards;
+ using UnityEngine;
+
+ using static HarmonyLib.AccessTools;
+
+ ///
+ /// Patch for storing rank from custom keycards.
+ ///
+ [HarmonyPatch(typeof(CustomRankDetail))]
+ public class CustomRankDetailData
+ {
+ [HarmonyPatch(nameof(CustomRankDetail.WriteNewItem))]
+ private static IEnumerable Transpiler1(IEnumerable instructions)
+ {
+ List newInstructions = ListPool.Pool.Get(instructions);
+
+ newInstructions.InsertRange(0, new CodeInstruction[]
+ {
+ new(OpCodes.Call, PropertyGetter(typeof(CustomKeycard), nameof(CustomKeycard.RankDict))),
+ new(OpCodes.Ldarg_1),
+ new(OpCodes.Callvirt, PropertyGetter(typeof(KeycardItem), nameof(KeycardItem.ItemSerial))),
+ new(OpCodes.Ldsfld, Field(typeof(CustomRankDetail), nameof(CustomRankDetail._index))),
+
+ new(OpCodes.Call, Method(typeof(Mathf), nameof(Mathf.Abs))),
+ new(OpCodes.Ldarg_0),
+ new(OpCodes.Ldfld, Field(typeof(CustomRankDetail), nameof(CustomRankDetail._options))),
+ new(OpCodes.Ldlen),
+ new(OpCodes.Conv_I4),
+ new(OpCodes.Rem),
+ new(OpCodes.Conv_U1),
+
+ new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
+ });
+
+ for (int i = 0; i < newInstructions.Count; i++)
+ yield return newInstructions[i];
+
+ ListPool.Pool.Return(newInstructions);
+ }
+
+ [HarmonyPatch(nameof(CustomRankDetail.WriteNewPickup))]
+ private static IEnumerable Transpiler2(IEnumerable instructions)
+ {
+ List newInstructions = ListPool.Pool.Get(instructions);
+
+ newInstructions.InsertRange(0, new CodeInstruction[]
+ {
+ new(OpCodes.Call, PropertyGetter(typeof(CustomKeycard), nameof(CustomKeycard.RankDict))),
+ new(OpCodes.Ldarg_1),
+ new(OpCodes.Callvirt, PropertyGetter(typeof(KeycardPickup), nameof(KeycardPickup.ItemId))),
+ new(OpCodes.Ldfld, Field(typeof(ItemIdentifier), nameof(ItemIdentifier.SerialNumber))),
+ new(OpCodes.Ldsfld, Field(typeof(CustomRankDetail), nameof(CustomRankDetail._index))),
+
+ new(OpCodes.Call, Method(typeof(Mathf), nameof(Mathf.Abs))),
+ new(OpCodes.Ldarg_0),
+ new(OpCodes.Ldfld, Field(typeof(CustomRankDetail), nameof(CustomRankDetail._options))),
+ new(OpCodes.Ldlen),
+ new(OpCodes.Conv_I4),
+ new(OpCodes.Rem),
+ new(OpCodes.Conv_U1),
+
+ new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
+ });
+
+ for (int i = 0; i < newInstructions.Count; i++)
+ yield return newInstructions[i];
+
+ ListPool.Pool.Return(newInstructions);
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomSerialNumberDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomSerialNumberDetailData.cs
new file mode 100644
index 0000000000..6e9bf24c9a
--- /dev/null
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomSerialNumberDetailData.cs
@@ -0,0 +1,68 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.Patches.Generic.KeycardDetails
+{
+ using System.Collections.Generic;
+ using System.Reflection.Emit;
+
+ using Exiled.API.Features.Items.Keycards;
+ using Exiled.API.Features.Pools;
+ using HarmonyLib;
+ using InventorySystem.Items;
+ using InventorySystem.Items.Keycards;
+
+ using static HarmonyLib.AccessTools;
+
+ ///
+ /// Patch for storing serial numbers from custom keycards.
+ ///
+ [HarmonyPatch(typeof(CustomSerialNumberDetail))]
+ public class CustomSerialNumberDetailData
+ {
+ [HarmonyPatch(nameof(NametagDetail.WriteNewItem))]
+ private static IEnumerable Transpiler1(IEnumerable instructions)
+ {
+ List newInstructions = ListPool.Pool.Get(instructions);
+
+ newInstructions.InsertRange(0, new CodeInstruction[]
+ {
+ new(OpCodes.Call, PropertyGetter(typeof(CustomKeycard), nameof(CustomKeycard.SerialNumberDict))),
+ new(OpCodes.Ldarg_1),
+ new(OpCodes.Callvirt, PropertyGetter(typeof(KeycardItem), nameof(KeycardItem.ItemSerial))),
+ new(OpCodes.Ldsfld, Field(typeof(CustomSerialNumberDetail), nameof(CustomSerialNumberDetail._customVal))),
+ new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
+ });
+
+ for (int i = 0; i < newInstructions.Count; i++)
+ yield return newInstructions[i];
+
+ ListPool.Pool.Return(newInstructions);
+ }
+
+ [HarmonyPatch(nameof(NametagDetail.WriteNewPickup))]
+ private static IEnumerable Transpiler2(IEnumerable instructions)
+ {
+ List newInstructions = ListPool.Pool.Get(instructions);
+
+ newInstructions.InsertRange(0, new CodeInstruction[]
+ {
+ new(OpCodes.Call, PropertyGetter(typeof(CustomKeycard), nameof(CustomKeycard.SerialNumberDict))),
+ new(OpCodes.Ldarg_1),
+ new(OpCodes.Callvirt, PropertyGetter(typeof(KeycardPickup), nameof(KeycardPickup.ItemId))),
+ new(OpCodes.Ldfld, Field(typeof(ItemIdentifier), nameof(ItemIdentifier.SerialNumber))),
+ new(OpCodes.Ldsfld, Field(typeof(CustomSerialNumberDetail), nameof(CustomSerialNumberDetail._customVal))),
+ new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
+ });
+
+ for (int i = 0; i < newInstructions.Count; i++)
+ yield return newInstructions[i];
+
+ ListPool.Pool.Return(newInstructions);
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomTintDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomTintDetailData.cs
new file mode 100644
index 0000000000..d109222dac
--- /dev/null
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomTintDetailData.cs
@@ -0,0 +1,71 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.Patches.Generic.KeycardDetails
+{
+ using System.Collections.Generic;
+ using System.Reflection.Emit;
+
+ using Exiled.API.Features.Items.Keycards;
+ using Exiled.API.Features.Pools;
+ using HarmonyLib;
+ using InventorySystem.Items;
+ using InventorySystem.Items.Keycards;
+ using UnityEngine;
+
+ using static HarmonyLib.AccessTools;
+
+ ///
+ /// Patch for storing colors from custom keycards.
+ ///
+ [HarmonyPatch(typeof(CustomTintDetail))]
+ public class CustomTintDetailData
+ {
+ [HarmonyPatch(nameof(CustomTintDetail.WriteNewItem))]
+ [HarmonyTranspiler]
+ private static IEnumerable Transpiler1(IEnumerable instructions)
+ {
+ List newInstructions = ListPool.Pool.Get(instructions);
+
+ newInstructions.InsertRange(0, new CodeInstruction[]
+ {
+ new(OpCodes.Call, PropertyGetter(typeof(CustomKeycard), nameof(CustomKeycard.ColorDict))),
+ new(OpCodes.Ldarg_1),
+ new(OpCodes.Callvirt, PropertyGetter(typeof(KeycardItem), nameof(KeycardItem.ItemSerial))),
+ new(OpCodes.Ldsfld, Field(typeof(CustomTintDetail), nameof(CustomTintDetail._customColor))),
+ new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
+ });
+
+ for (int i = 0; i < newInstructions.Count; i++)
+ yield return newInstructions[i];
+
+ ListPool.Pool.Return(newInstructions);
+ }
+
+ [HarmonyPatch(nameof(CustomTintDetail.WriteNewPickup))]
+ [HarmonyTranspiler]
+ private static IEnumerable Transpiler2(IEnumerable instructions)
+ {
+ List newInstructions = ListPool.Pool.Get(instructions);
+
+ newInstructions.InsertRange(0, new CodeInstruction[]
+ {
+ new(OpCodes.Call, PropertyGetter(typeof(CustomKeycard), nameof(CustomKeycard.ColorDict))),
+ new(OpCodes.Ldarg_1),
+ new(OpCodes.Callvirt, PropertyGetter(typeof(KeycardPickup), nameof(KeycardPickup.ItemId))),
+ new(OpCodes.Ldfld, Field(typeof(ItemIdentifier), nameof(ItemIdentifier.SerialNumber))),
+ new(OpCodes.Ldsfld, Field(typeof(CustomTintDetail), nameof(CustomTintDetail._customColor))),
+ new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
+ });
+
+ for (int i = 0; i < newInstructions.Count; i++)
+ yield return newInstructions[i];
+
+ ListPool.Pool.Return(newInstructions);
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomWearDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomWearDetailData.cs
new file mode 100644
index 0000000000..15827da01a
--- /dev/null
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomWearDetailData.cs
@@ -0,0 +1,70 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.Patches.Generic.KeycardDetails
+{
+ using System.Collections.Generic;
+ using System.Reflection.Emit;
+
+ using Exiled.API.Features.Items.Keycards;
+ using Exiled.API.Features.Pools;
+ using HarmonyLib;
+ using InventorySystem.Items;
+ using InventorySystem.Items.Keycards;
+
+ using static HarmonyLib.AccessTools;
+
+ ///
+ /// Patch for storing wear from custom keycards.
+ ///
+ [HarmonyPatch(typeof(CustomWearDetail))]
+ public class CustomWearDetailData
+ {
+ [HarmonyPatch(nameof(CustomWearDetail.WriteNewItem))]
+ [HarmonyTranspiler]
+ private static IEnumerable Transpiler1(IEnumerable instructions)
+ {
+ List newInstructions = ListPool.Pool.Get(instructions);
+
+ newInstructions.InsertRange(0, new CodeInstruction[]
+ {
+ new(OpCodes.Call, PropertyGetter(typeof(CustomKeycard), nameof(CustomKeycard.WearDict))),
+ new(OpCodes.Ldarg_1),
+ new(OpCodes.Callvirt, PropertyGetter(typeof(KeycardItem), nameof(KeycardItem.ItemSerial))),
+ new(OpCodes.Ldsfld, Field(typeof(CustomWearDetail), nameof(CustomWearDetail._customWearLevel))),
+ new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
+ });
+
+ for (int i = 0; i < newInstructions.Count; i++)
+ yield return newInstructions[i];
+
+ ListPool.Pool.Return(newInstructions);
+ }
+
+ [HarmonyPatch(nameof(CustomWearDetail.WriteNewPickup))]
+ [HarmonyTranspiler]
+ private static IEnumerable Transpiler2(IEnumerable instructions)
+ {
+ List newInstructions = ListPool.Pool.Get(instructions);
+
+ newInstructions.InsertRange(0, new CodeInstruction[]
+ {
+ new(OpCodes.Call, PropertyGetter(typeof(CustomKeycard), nameof(CustomKeycard.WearDict))),
+ new(OpCodes.Ldarg_1),
+ new(OpCodes.Callvirt, PropertyGetter(typeof(KeycardPickup), nameof(KeycardPickup.ItemId))),
+ new(OpCodes.Ldfld, Field(typeof(ItemIdentifier), nameof(ItemIdentifier.SerialNumber))),
+ new(OpCodes.Ldsfld, Field(typeof(CustomWearDetail), nameof(CustomWearDetail._customWearLevel))),
+ new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
+ });
+
+ for (int i = 0; i < newInstructions.Count; i++)
+ yield return newInstructions[i];
+
+ ListPool.Pool.Return(newInstructions);
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/NameTagDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/NameTagDetailData.cs
new file mode 100644
index 0000000000..3a056f7780
--- /dev/null
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/NameTagDetailData.cs
@@ -0,0 +1,71 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.Patches.Generic.KeycardDetails
+{
+ using System.Collections.Generic;
+ using System.Reflection.Emit;
+
+ using Exiled.API.Features.Items.Keycards;
+ using Exiled.API.Features.Pools;
+ using Exiled.Events.Patches.Fixes;
+ using HarmonyLib;
+ using InventorySystem.Items;
+ using InventorySystem.Items.Keycards;
+
+ using static HarmonyLib.AccessTools;
+
+ ///
+ /// Patch for storing name tags from custom keycards.
+ ///
+ /// There's a fix for () so I set the priority of this patch 1 lower than default to avoid errors.
+ [HarmonyPatch(typeof(NametagDetail))]
+ [HarmonyPriority(399)]
+ public class NameTagDetailData
+ {
+ [HarmonyPatch(nameof(NametagDetail.WriteNewItem))]
+ private static IEnumerable Transpiler1(IEnumerable instructions)
+ {
+ List newInstructions = ListPool.Pool.Get(instructions);
+
+ newInstructions.InsertRange(0, new CodeInstruction[]
+ {
+ new(OpCodes.Call, PropertyGetter(typeof(CustomKeycard), nameof(CustomKeycard.NameTagDict))),
+ new(OpCodes.Ldarg_1),
+ new(OpCodes.Callvirt, PropertyGetter(typeof(KeycardItem), nameof(KeycardItem.ItemSerial))),
+ new(OpCodes.Ldsfld, Field(typeof(NametagDetail), nameof(NametagDetail._customNametag))),
+ new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
+ });
+
+ for (int i = 0; i < newInstructions.Count; i++)
+ yield return newInstructions[i];
+
+ ListPool.Pool.Return(newInstructions);
+ }
+
+ [HarmonyPatch(nameof(NametagDetail.WriteNewPickup))]
+ private static IEnumerable Transpiler2(IEnumerable instructions)
+ {
+ List newInstructions = ListPool.Pool.Get(instructions);
+
+ newInstructions.InsertRange(0, new CodeInstruction[]
+ {
+ new(OpCodes.Call, PropertyGetter(typeof(CustomKeycard), nameof(CustomKeycard.NameTagDict))),
+ new(OpCodes.Ldarg_1),
+ new(OpCodes.Callvirt, PropertyGetter(typeof(KeycardPickup), nameof(KeycardPickup.ItemId))),
+ new(OpCodes.Ldfld, Field(typeof(ItemIdentifier), nameof(ItemIdentifier.SerialNumber))),
+ new(OpCodes.Ldsfld, Field(typeof(NametagDetail), nameof(NametagDetail._customNametag))),
+ new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
+ });
+
+ for (int i = 0; i < newInstructions.Count; i++)
+ yield return newInstructions[i];
+
+ ListPool.Pool.Return(newInstructions);
+ }
+ }
+}
\ No newline at end of file
From 2788ee3187e40db689daa042edeb32a61d2eb3d3 Mon Sep 17 00:00:00 2001
From: "@Someone" <45270312+Someone-193@users.noreply.github.com>
Date: Tue, 26 Aug 2025 20:14:54 -0400
Subject: [PATCH 10/38] Fix color and CustomKeycards using old values,
---
.../Features/Items/Keycards/CustomKeycard.cs | 14 +++++++-------
.../Features/Items/Keycards/ManagementKeycard.cs | 2 +-
.../Features/Items/Keycards/MetalKeycard.cs | 4 ++--
.../Features/Items/Keycards/Site02Keycard.cs | 4 ++--
.../Features/Items/Keycards/TaskForceKeycard.cs | 2 +-
.../KeycardDetails/CustomLabelDetailData.cs | 4 ++--
.../KeycardDetails/CustomPermsDetailData.cs | 2 +-
.../Generic/KeycardDetails/CustomTintDetailData.cs | 4 ++--
8 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
index c6f517c02d..f38790223f 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
@@ -37,6 +37,8 @@ internal CustomKeycard(KeycardItem itemBase)
: base(itemBase)
{
Base = itemBase;
+
+ Resync();
}
///
@@ -73,7 +75,7 @@ public KeycardLevels Permissions
///
public Color PermissionsColor
{
- get => PermsColorDict.TryGetValue(Serial, out Color value) ? value : Color.black;
+ get => PermsColorDict.TryGetValue(Serial, out Color32 value) ? value : Color.black;
set
{
@@ -118,7 +120,7 @@ public string ItemName
///
public Color Color
{
- get => ColorDict.TryGetValue(Serial, out Color value) ? value : Color.black;
+ get => ColorDict.TryGetValue(Serial, out Color32 value) ? value : Color.black;
set
{
@@ -131,12 +133,12 @@ public Color Color
///
/// Gets a dictionary of item serials to their permissions color.
///
- internal static Dictionary PermsColorDict { get; } = new();
+ internal static Dictionary PermsColorDict { get; } = new();
///
/// Gets a dictionary of item serials to their color.
///
- internal static Dictionary ColorDict { get; } = new();
+ internal static Dictionary ColorDict { get; } = new();
///
/// Gets a dictionary of item serials to their name tag.
@@ -151,7 +153,7 @@ public Color Color
///
/// Gets a dictionary of item serials to their label's color.
///
- internal static Dictionary LabelColorDict { get; } = new();
+ internal static Dictionary LabelColorDict { get; } = new();
///
/// Gets a dictionary of item serials to their wear.
@@ -194,9 +196,7 @@ public void Resync()
CustomWearDetail._customWearLevel = wear.Wear;
if (this is ISerialNumberKeycard serial)
- {
CustomSerialNumberDetail._customVal = serial.SerialNumber;
- }
MirrorExtensions.ResyncKeycardItem(this);
}
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs
index b84702d766..4654cd4b1a 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs
@@ -54,7 +54,7 @@ public string Label
///
public Color LabelColor
{
- get => LabelColorDict.TryGetValue(Serial, out Color value) ? value : Color.black;
+ get => LabelColorDict.TryGetValue(Serial, out Color32 value) ? value : Color.black;
set
{
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs
index eb1c8eebe7..04fc122a05 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs
@@ -66,7 +66,7 @@ public string Label
///
public Color LabelColor
{
- get => LabelColorDict.TryGetValue(Serial, out Color value) ? value : Color.black;
+ get => LabelColorDict.TryGetValue(Serial, out Color32 value) ? value : Color.black;
set
{
@@ -79,7 +79,7 @@ public Color LabelColor
/// Capped from 0-5 for Site-02 keycards, returns 255 if no wear level is found.
public byte Wear
{
- get => WearDict.TryGetValue(Serial, out byte value) ? value : (byte)255;
+ get => WearDict.TryGetValue(Serial, out byte value) ? value : byte.MaxValue;
set
{
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
index cd0fd967b1..9a71ce56a0 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
@@ -66,7 +66,7 @@ public string Label
///
public Color LabelColor
{
- get => LabelColorDict.TryGetValue(Serial, out Color value) ? value : Color.black;
+ get => LabelColorDict.TryGetValue(Serial, out Color32 value) ? value : Color.black;
set
{
@@ -79,7 +79,7 @@ public Color LabelColor
/// Capped from 0-4 for Site-02 keycards, returns 255 if no wear level is found.
public byte Wear
{
- get => WearDict.TryGetValue(Serial, out byte value) ? value : (byte)255;
+ get => WearDict.TryGetValue(Serial, out byte value) ? value : byte.MaxValue;
set
{
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs
index d840267461..4a7fccb6a6 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs
@@ -67,7 +67,7 @@ public string SerialNumber
///
public byte Rank
{
- get => RankDict.TryGetValue(Serial, out byte value) ? value : (byte)255;
+ get => RankDict.TryGetValue(Serial, out byte value) ? value : byte.MaxValue;
set
{
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomLabelDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomLabelDetailData.cs
index 6195c60841..e3ef46a00f 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomLabelDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomLabelDetailData.cs
@@ -43,7 +43,7 @@ private static IEnumerable Transpiler1(IEnumerable), "set_Item")),
+ new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
});
for (int i = 0; i < newInstructions.Count; i++)
@@ -72,7 +72,7 @@ private static IEnumerable Transpiler2(IEnumerable), "set_Item")),
+ new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
});
for (int i = 0; i < newInstructions.Count; i++)
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomPermsDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomPermsDetailData.cs
index c8f8e69fc1..787c4db9d4 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomPermsDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomPermsDetailData.cs
@@ -36,7 +36,7 @@ private static IEnumerable Transpiler(IEnumerable), "set_Item")),
+ new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
});
for (int i = 0; i < newInstructions.Count; i++)
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomTintDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomTintDetailData.cs
index d109222dac..fdefc74f30 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomTintDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomTintDetailData.cs
@@ -37,7 +37,7 @@ private static IEnumerable Transpiler1(IEnumerable), "set_Item")),
+ new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
});
for (int i = 0; i < newInstructions.Count; i++)
@@ -59,7 +59,7 @@ private static IEnumerable Transpiler2(IEnumerable), "set_Item")),
+ new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
});
for (int i = 0; i < newInstructions.Count; i++)
From 3e6e63a1e2b0f7ab5570622c139edeee30b39727 Mon Sep 17 00:00:00 2001
From: Yamato
Date: Wed, 27 Aug 2025 12:35:56 +0200
Subject: [PATCH 11/38] Modification on KeycardCustom being Inherited by
Keycard
---
EXILED/Exiled.API/Features/Items/Keycard.cs | 7 ++--
.../Features/Items/Keycards/CustomKeycard.cs | 32 +++++++++++++------
.../Items/Keycards/ManagementKeycard.cs | 10 +++---
.../Features/Items/Keycards/MetalKeycard.cs | 10 +++---
.../Features/Items/Keycards/Site02Keycard.cs | 8 ++---
.../Items/Keycards/TaskForceKeycard.cs | 4 +--
6 files changed, 42 insertions(+), 29 deletions(-)
diff --git a/EXILED/Exiled.API/Features/Items/Keycard.cs b/EXILED/Exiled.API/Features/Items/Keycard.cs
index 4e68dd60a5..2cff5d2e4d 100644
--- a/EXILED/Exiled.API/Features/Items/Keycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycard.cs
@@ -45,7 +45,7 @@ internal Keycard(ItemType type)
///
/// Gets or sets the of the keycard.
///
- public KeycardPermissions Permissions
+ public virtual KeycardPermissions Permissions
{
get
{
@@ -63,8 +63,9 @@ public KeycardPermissions Permissions
return KeycardPermissions.None;
}
- [Obsolete("Not functional anymore", true)]
- set => _ = value;
+ set
+ {
+ }
}
///
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
index f38790223f..c13464a39c 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
@@ -7,24 +7,21 @@
namespace Exiled.API.Features.Items.Keycards
{
- using System.Collections.Generic;
- using System.Linq;
-
+ using Exiled.API.Enums;
using Exiled.API.Extensions;
using Exiled.API.Interfaces;
using Exiled.API.Interfaces.Keycards;
-
using Interactables.Interobjects.DoorUtils;
-
using InventorySystem.Items;
using InventorySystem.Items.Keycards;
-
+ using System.Collections.Generic;
+ using System.Linq;
using UnityEngine;
///
/// A base class for all keycard items.
///
- public abstract class CustomKeycard : Item, IWrapper
+ public abstract class CustomKeycard : Keycard
{
private CustomItemNameDetail itemNameDetail;
private bool itemNameSet;
@@ -58,9 +55,24 @@ internal CustomKeycard(ItemType type)
///
/// Gets or sets the permissions this keycard has.
///
- public KeycardLevels Permissions
+ public override KeycardPermissions Permissions
+ {
+ get => CustomPermsDetail.CustomPermissions.TryGetValue(Serial, out DoorPermissionFlags flags) ? (KeycardPermissions)flags : KeycardPermissions.None;
+
+ set
+ {
+ CustomPermsDetail.CustomPermissions[Serial] = (DoorPermissionFlags)value;
+
+ Resync();
+ }
+ }
+
+ ///
+ /// Gets or sets the permissions this keycard has.
+ ///
+ public KeycardLevels KeycardLevels
{
- get => CustomPermsDetail.CustomPermissions.TryGetValue(Serial, out DoorPermissionFlags flags) ? new KeycardLevels(flags) : new KeycardLevels(0, 0, 0);
+ get => new((DoorPermissionFlags)Permissions);
set
{
@@ -177,7 +189,7 @@ public Color Color
public void Resync()
{
// we loveeeeeeeeeeeee NW static fields trusttttttttttttttt I'm not mad at allllllllllll
- CustomPermsDetail._customLevels = Permissions;
+ CustomPermsDetail._customLevels = KeycardLevels;
CustomPermsDetail._customColor = PermissionsColor;
CustomItemNameDetail._customText = ItemName;
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs
index 4654cd4b1a..82b603aea1 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs
@@ -1,4 +1,4 @@
-// -----------------------------------------------------------------------
+// -----------------------------------------------------------------------
//
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
@@ -66,17 +66,17 @@ public Color LabelColor
///
/// Creates a .
///
- /// The permissions of the keycard.
+ /// The permissions of the keycard.
/// The color of the permissions of the keycard.
/// The inventory name of the keycard.
/// The color of the keycard.
/// The label on the keycard.
/// The color of the label on the keycard.
/// The new .
- public static ManagementKeycard Create(KeycardLevels permissions, Color permissionsColor, string itemName, Color color, string label, Color labelColor)
+ public static ManagementKeycard Create(KeycardLevels keycardLevels, Color permissionsColor, string itemName, Color color, string label, Color labelColor)
{
- ManagementKeycard keycard = (ManagementKeycard)Item.Create(ItemType.KeycardCustomManagement);
- keycard.Permissions = permissions;
+ ManagementKeycard keycard = Create(ItemType.KeycardCustomManagement);
+ keycard.KeycardLevels = keycardLevels;
keycard.PermissionsColor = permissionsColor;
keycard.ItemName = itemName;
keycard.Color = color;
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs
index 04fc122a05..178f9d1f06 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs
@@ -1,4 +1,4 @@
-// -----------------------------------------------------------------------
+// -----------------------------------------------------------------------
//
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
@@ -105,7 +105,7 @@ public string SerialNumber
///
/// Creates a .
///
- /// The permissions of the keycard.
+ /// The permissions of the keycard.
/// The color of the permissions of the keycard.
/// The inventory name of the keycard.
/// The color of the keycard.
@@ -115,10 +115,10 @@ public string SerialNumber
/// How worn the keycard looks (capped from 0-5).
/// The serial number of the keycard (numbers only, 12 max).
/// The new .
- public static MetalKeycard Create(KeycardLevels permissions, Color permissionsColor, string itemName, Color color, string nameTag, string label, Color labelColor, byte wear, string serialNumber)
+ public static MetalKeycard Create(KeycardLevels keycardLevels, Color permissionsColor, string itemName, Color color, string nameTag, string label, Color labelColor, byte wear, string serialNumber)
{
- MetalKeycard keycard = (MetalKeycard)Item.Create(ItemType.KeycardCustomManagement);
- keycard.Permissions = permissions;
+ MetalKeycard keycard = Create(ItemType.KeycardCustomManagement);
+ keycard.KeycardLevels = keycardLevels;
keycard.PermissionsColor = permissionsColor;
keycard.ItemName = itemName;
keycard.Color = color;
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
index 9a71ce56a0..c18bb3d75c 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
@@ -1,4 +1,4 @@
-// -----------------------------------------------------------------------
+// -----------------------------------------------------------------------
//
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
@@ -101,10 +101,10 @@ public byte Wear
/// The color of the label on the keycard.
/// How worn the keycard looks (capped from 0-5).
/// The new .
- public static Site02Keycard Create(KeycardLevels permissions, Color permissionsColor, string itemName, Color color, string nameTag, string label, Color labelColor, byte wear)
+ public static Site02Keycard Create(KeycardLevels keycardLevels, Color permissionsColor, string itemName, Color color, string nameTag, string label, Color labelColor, byte wear)
{
- Site02Keycard keycard = (Site02Keycard)Item.Create(ItemType.KeycardCustomManagement);
- keycard.Permissions = permissions;
+ Site02Keycard keycard = Create(ItemType.KeycardCustomManagement);
+ keycard.KeycardLevels = keycardLevels;
keycard.PermissionsColor = permissionsColor;
keycard.ItemName = itemName;
keycard.Color = color;
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs
index 4a7fccb6a6..a287d08fd3 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs
@@ -88,10 +88,10 @@ public byte Rank
/// The serial number of the keycard (numbers only, 12 max).
/// The rank of the keycard (capped from 0-3).
/// The new .
- public static TaskForceKeycard Create(KeycardLevels permissions, Color permissionsColor, string itemName, Color color, string nameTag, string serialNumber, byte rank)
+ public static TaskForceKeycard Create(KeycardLevels keycardLevels, Color permissionsColor, string itemName, Color color, string nameTag, string serialNumber, byte rank)
{
TaskForceKeycard keycard = Create(ItemType.KeycardCustomManagement);
- keycard.Permissions = permissions;
+ keycard.KeycardLevels = keycardLevels;
keycard.PermissionsColor = permissionsColor;
keycard.ItemName = itemName;
keycard.Color = color;
From 3ced522a877718969f6647d4e76eabeedd04c417 Mon Sep 17 00:00:00 2001
From: Yamato
Date: Wed, 27 Aug 2025 12:39:53 +0200
Subject: [PATCH 12/38] Fix build error
---
EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs | 6 +++---
EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs | 2 +-
.../Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
index c13464a39c..2906635b6d 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
@@ -7,15 +7,15 @@
namespace Exiled.API.Features.Items.Keycards
{
+ using System.Collections.Generic;
+ using System.Linq;
+
using Exiled.API.Enums;
using Exiled.API.Extensions;
- using Exiled.API.Interfaces;
using Exiled.API.Interfaces.Keycards;
using Interactables.Interobjects.DoorUtils;
using InventorySystem.Items;
using InventorySystem.Items.Keycards;
- using System.Collections.Generic;
- using System.Linq;
using UnityEngine;
///
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
index c18bb3d75c..4a350dd284 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
@@ -92,7 +92,7 @@ public byte Wear
///
/// Creates a .
///
- /// The permissions of the keycard.
+ /// The permissions of the keycard.
/// The color of the permissions of the keycard.
/// The inventory name of the keycard.
/// The color of the keycard.
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs
index a287d08fd3..d10f4db69c 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs
@@ -80,7 +80,7 @@ public byte Rank
///
/// Creates a .
///
- /// The permissions of the keycard.
+ /// The permissions of the keycard.
/// The color of the permissions of the keycard.
/// The inventory name of the keycard.
/// The color of the keycard.
From f384d80d30c781ab24007da30335d5fa5cb5f70c Mon Sep 17 00:00:00 2001
From: Yamato
Date: Wed, 27 Aug 2025 14:18:03 +0200
Subject: [PATCH 13/38] Using Color32 and use of void Prefix
---
.../Features/Items/Keycards/CustomKeycard.cs | 18 ++---
.../Items/Keycards/ManagementKeycard.cs | 4 +-
.../Features/Items/Keycards/MetalKeycard.cs | 4 +-
.../Features/Items/Keycards/Site02Keycard.cs | 4 +-
.../Interfaces/Keycards/ILabelKeycard.cs | 4 +-
.../KeycardDetails/CustomLabelDetailData.cs | 66 +++----------------
.../KeycardDetails/CustomPermsDetailData.cs | 28 +-------
.../KeycardDetails/CustomRankDetailData.cs | 66 +++----------------
.../CustomSerialNumberDetailData.cs | 48 ++------------
.../KeycardDetails/CustomTintDetailData.cs | 51 ++------------
.../KeycardDetails/CustomWearDetailData.cs | 46 ++-----------
.../KeycardDetails/NameTagDetailData.cs | 51 +++-----------
12 files changed, 64 insertions(+), 326 deletions(-)
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
index 2906635b6d..5864bf4f0d 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
@@ -85,9 +85,9 @@ public KeycardLevels KeycardLevels
///
/// Gets or sets the color of this keycard's permissions.
///
- public Color PermissionsColor
+ public Color32? PermissionsColor
{
- get => PermsColorDict.TryGetValue(Serial, out Color32 value) ? value : Color.black;
+ get => PermsColorDict.TryGetValue(Serial, out Color32? value) ? value : null;
set
{
@@ -130,9 +130,9 @@ public string ItemName
///
/// Gets or sets the color of this keycard.
///
- public Color Color
+ public Color32? Color
{
- get => ColorDict.TryGetValue(Serial, out Color32 value) ? value : Color.black;
+ get => ColorDict.TryGetValue(Serial, out Color32? value) ? value : null;
set
{
@@ -145,12 +145,12 @@ public Color Color
///
/// Gets a dictionary of item serials to their permissions color.
///
- internal static Dictionary PermsColorDict { get; } = new();
+ internal static Dictionary PermsColorDict { get; } = new();
///
/// Gets a dictionary of item serials to their color.
///
- internal static Dictionary ColorDict { get; } = new();
+ internal static Dictionary ColorDict { get; } = new();
///
/// Gets a dictionary of item serials to their name tag.
@@ -165,7 +165,7 @@ public Color Color
///
/// Gets a dictionary of item serials to their label's color.
///
- internal static Dictionary LabelColorDict { get; } = new();
+ internal static Dictionary LabelColorDict { get; } = new();
///
/// Gets a dictionary of item serials to their wear.
@@ -193,12 +193,12 @@ public void Resync()
CustomPermsDetail._customColor = PermissionsColor;
CustomItemNameDetail._customText = ItemName;
- CustomTintDetail._customColor = Color;
+ CustomTintDetail._customColor = Color.GetValueOrDefault();
if (this is ILabelKeycard label)
{
CustomLabelDetail._customText = label.Label;
- CustomLabelDetail._customColor = label.LabelColor;
+ CustomLabelDetail._customColor = label.LabelColor.GetValueOrDefault();
}
if (this is INameTagKeycard holder)
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs
index 82b603aea1..ed58ed67c6 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs
@@ -52,9 +52,9 @@ public string Label
}
///
- public Color LabelColor
+ public Color32? LabelColor
{
- get => LabelColorDict.TryGetValue(Serial, out Color32 value) ? value : Color.black;
+ get => LabelColorDict.TryGetValue(Serial, out Color32? value) ? value : null;
set
{
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs
index 178f9d1f06..4226d8da0d 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs
@@ -64,9 +64,9 @@ public string Label
}
///
- public Color LabelColor
+ public Color32? LabelColor
{
- get => LabelColorDict.TryGetValue(Serial, out Color32 value) ? value : Color.black;
+ get => LabelColorDict.TryGetValue(Serial, out Color32? value) ? value : null;
set
{
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
index 4a350dd284..40e8e5328f 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
@@ -64,9 +64,9 @@ public string Label
}
///
- public Color LabelColor
+ public Color32? LabelColor
{
- get => LabelColorDict.TryGetValue(Serial, out Color32 value) ? value : Color.black;
+ get => LabelColorDict.TryGetValue(Serial, out Color32? value) ? value : null;
set
{
diff --git a/EXILED/Exiled.API/Interfaces/Keycards/ILabelKeycard.cs b/EXILED/Exiled.API/Interfaces/Keycards/ILabelKeycard.cs
index b5f9dcc0a6..f2a78f6d6a 100644
--- a/EXILED/Exiled.API/Interfaces/Keycards/ILabelKeycard.cs
+++ b/EXILED/Exiled.API/Interfaces/Keycards/ILabelKeycard.cs
@@ -1,4 +1,4 @@
-// -----------------------------------------------------------------------
+// -----------------------------------------------------------------------
//
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
@@ -23,6 +23,6 @@ public interface ILabelKeycard
///
/// Gets or sets the of this .
///
- public Color LabelColor { get; set; }
+ public Color32? LabelColor { get; set; }
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomLabelDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomLabelDetailData.cs
index e3ef46a00f..83f0e38c3c 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomLabelDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomLabelDetailData.cs
@@ -1,4 +1,4 @@
-// -----------------------------------------------------------------------
+// -----------------------------------------------------------------------
//
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
@@ -7,17 +7,9 @@
namespace Exiled.Events.Patches.Generic.KeycardDetails
{
- using System.Collections.Generic;
- using System.Reflection.Emit;
-
using Exiled.API.Features.Items.Keycards;
- using Exiled.API.Features.Pools;
using HarmonyLib;
- using InventorySystem.Items;
using InventorySystem.Items.Keycards;
- using UnityEngine;
-
- using static HarmonyLib.AccessTools;
///
/// Patch for storing label and label color from custom keycards.
@@ -26,59 +18,19 @@ namespace Exiled.Events.Patches.Generic.KeycardDetails
public class CustomLabelDetailData
{
[HarmonyPatch(nameof(CustomLabelDetail.WriteNewItem))]
- [HarmonyTranspiler]
- private static IEnumerable Transpiler1(IEnumerable instructions)
+ [HarmonyPrefix]
+ private static void Prefix(KeycardItem item)
{
- List newInstructions = ListPool.Pool.Get(instructions);
-
- newInstructions.InsertRange(0, new CodeInstruction[]
- {
- new(OpCodes.Call, PropertyGetter(typeof(CustomKeycard), nameof(CustomKeycard.LabelDict))),
- new(OpCodes.Ldarg_1),
- new(OpCodes.Callvirt, PropertyGetter(typeof(KeycardItem), nameof(KeycardItem.ItemSerial))),
- new(OpCodes.Ldsfld, Field(typeof(CustomLabelDetail), nameof(CustomLabelDetail._customText))),
- new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
-
- new(OpCodes.Call, PropertyGetter(typeof(CustomKeycard), nameof(CustomKeycard.LabelColorDict))),
- new(OpCodes.Ldarg_1),
- new(OpCodes.Callvirt, PropertyGetter(typeof(KeycardItem), nameof(KeycardItem.ItemSerial))),
- new(OpCodes.Ldsfld, Field(typeof(CustomLabelDetail), nameof(CustomLabelDetail._customColor))),
- new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
- });
-
- for (int i = 0; i < newInstructions.Count; i++)
- yield return newInstructions[i];
-
- ListPool.Pool.Return(newInstructions);
+ CustomKeycard.LabelDict[item.ItemSerial] = CustomLabelDetail._customText;
+ CustomKeycard.LabelColorDict[item.ItemSerial] = CustomLabelDetail._customColor;
}
[HarmonyPatch(nameof(CustomLabelDetail.WriteNewPickup))]
- [HarmonyTranspiler]
- private static IEnumerable Transpiler2(IEnumerable instructions)
+ [HarmonyPrefix]
+ private static void Prefix(KeycardPickup pickup)
{
- List newInstructions = ListPool.Pool.Get(instructions);
-
- newInstructions.InsertRange(0, new CodeInstruction[]
- {
- new(OpCodes.Call, PropertyGetter(typeof(CustomKeycard), nameof(CustomKeycard.LabelDict))),
- new(OpCodes.Ldarg_1),
- new(OpCodes.Callvirt, PropertyGetter(typeof(KeycardPickup), nameof(KeycardPickup.ItemId))),
- new(OpCodes.Ldfld, Field(typeof(ItemIdentifier), nameof(ItemIdentifier.SerialNumber))),
- new(OpCodes.Ldsfld, Field(typeof(CustomLabelDetail), nameof(CustomLabelDetail._customText))),
- new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
-
- new(OpCodes.Call, PropertyGetter(typeof(CustomKeycard), nameof(CustomKeycard.LabelColorDict))),
- new(OpCodes.Ldarg_1),
- new(OpCodes.Callvirt, PropertyGetter(typeof(KeycardPickup), nameof(KeycardPickup.ItemId))),
- new(OpCodes.Ldfld, Field(typeof(ItemIdentifier), nameof(ItemIdentifier.SerialNumber))),
- new(OpCodes.Ldsfld, Field(typeof(CustomLabelDetail), nameof(CustomLabelDetail._customColor))),
- new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
- });
-
- for (int i = 0; i < newInstructions.Count; i++)
- yield return newInstructions[i];
-
- ListPool.Pool.Return(newInstructions);
+ CustomKeycard.LabelDict[pickup.ItemId.SerialNumber] = CustomLabelDetail._customText;
+ CustomKeycard.LabelColorDict[pickup.ItemId.SerialNumber] = CustomLabelDetail._customColor;
}
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomPermsDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomPermsDetailData.cs
index 787c4db9d4..1254408737 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomPermsDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomPermsDetailData.cs
@@ -1,4 +1,4 @@
-// -----------------------------------------------------------------------
+// -----------------------------------------------------------------------
//
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
@@ -7,17 +7,10 @@
namespace Exiled.Events.Patches.Generic.KeycardDetails
{
- using System.Collections.Generic;
- using System.Reflection.Emit;
-
using Exiled.API.Features.Items.Keycards;
- using Exiled.API.Features.Pools;
using HarmonyLib;
using InventorySystem.Items;
using InventorySystem.Items.Keycards;
- using UnityEngine;
-
- using static HarmonyLib.AccessTools;
///
/// Patch for storing permission colors from custom keycards.
@@ -25,24 +18,9 @@ namespace Exiled.Events.Patches.Generic.KeycardDetails
[HarmonyPatch(typeof(CustomPermsDetail), nameof(CustomPermsDetail.WriteCustom))]
public class CustomPermsDetailData
{
- private static IEnumerable Transpiler(IEnumerable instructions)
+ private static void Prefix(IIdentifierProvider target)
{
- List newInstructions = ListPool.Pool.Get(instructions);
-
- newInstructions.InsertRange(0, new CodeInstruction[]
- {
- new(OpCodes.Call, PropertyGetter(typeof(CustomKeycard), nameof(CustomKeycard.PermsColorDict))),
- new(OpCodes.Ldarg_1),
- new(OpCodes.Callvirt, PropertyGetter(typeof(IIdentifierProvider), nameof(IIdentifierProvider.ItemId))),
- new(OpCodes.Ldfld, Field(typeof(ItemIdentifier), nameof(ItemIdentifier.SerialNumber))),
- new(OpCodes.Ldsfld, Field(typeof(CustomPermsDetail), nameof(CustomPermsDetail._customColor))),
- new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
- });
-
- for (int i = 0; i < newInstructions.Count; i++)
- yield return newInstructions[i];
-
- ListPool.Pool.Return(newInstructions);
+ CustomKeycard.PermsColorDict[target.ItemId.SerialNumber] = CustomPermsDetail._customColor;
}
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomRankDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomRankDetailData.cs
index 31ccb0c2c6..a63f0fa517 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomRankDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomRankDetailData.cs
@@ -1,4 +1,4 @@
-// -----------------------------------------------------------------------
+// -----------------------------------------------------------------------
//
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
@@ -7,17 +7,12 @@
namespace Exiled.Events.Patches.Generic.KeycardDetails
{
- using System.Collections.Generic;
- using System.Reflection.Emit;
-
using Exiled.API.Features.Items.Keycards;
- using Exiled.API.Features.Pools;
using HarmonyLib;
- using InventorySystem.Items;
using InventorySystem.Items.Keycards;
using UnityEngine;
- using static HarmonyLib.AccessTools;
+#pragma warning disable SA1313 // Parameter names should begin with lower-case letter
///
/// Patch for storing rank from custom keycards.
@@ -26,62 +21,17 @@ namespace Exiled.Events.Patches.Generic.KeycardDetails
public class CustomRankDetailData
{
[HarmonyPatch(nameof(CustomRankDetail.WriteNewItem))]
- private static IEnumerable Transpiler1(IEnumerable instructions)
+ [HarmonyPrefix]
+ private static void PrefixItem(CustomRankDetail __instance, KeycardItem item)
{
- List newInstructions = ListPool.Pool.Get(instructions);
-
- newInstructions.InsertRange(0, new CodeInstruction[]
- {
- new(OpCodes.Call, PropertyGetter(typeof(CustomKeycard), nameof(CustomKeycard.RankDict))),
- new(OpCodes.Ldarg_1),
- new(OpCodes.Callvirt, PropertyGetter(typeof(KeycardItem), nameof(KeycardItem.ItemSerial))),
- new(OpCodes.Ldsfld, Field(typeof(CustomRankDetail), nameof(CustomRankDetail._index))),
-
- new(OpCodes.Call, Method(typeof(Mathf), nameof(Mathf.Abs))),
- new(OpCodes.Ldarg_0),
- new(OpCodes.Ldfld, Field(typeof(CustomRankDetail), nameof(CustomRankDetail._options))),
- new(OpCodes.Ldlen),
- new(OpCodes.Conv_I4),
- new(OpCodes.Rem),
- new(OpCodes.Conv_U1),
-
- new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
- });
-
- for (int i = 0; i < newInstructions.Count; i++)
- yield return newInstructions[i];
-
- ListPool.Pool.Return(newInstructions);
+ CustomKeycard.RankDict[item.ItemSerial] = (byte)(Mathf.Abs(CustomRankDetail._index) % __instance._options.Length);
}
[HarmonyPatch(nameof(CustomRankDetail.WriteNewPickup))]
- private static IEnumerable Transpiler2(IEnumerable instructions)
+ [HarmonyPrefix]
+ private static void PrefixPickup(CustomRankDetail __instance, KeycardPickup pickup)
{
- List newInstructions = ListPool.Pool.Get(instructions);
-
- newInstructions.InsertRange(0, new CodeInstruction[]
- {
- new(OpCodes.Call, PropertyGetter(typeof(CustomKeycard), nameof(CustomKeycard.RankDict))),
- new(OpCodes.Ldarg_1),
- new(OpCodes.Callvirt, PropertyGetter(typeof(KeycardPickup), nameof(KeycardPickup.ItemId))),
- new(OpCodes.Ldfld, Field(typeof(ItemIdentifier), nameof(ItemIdentifier.SerialNumber))),
- new(OpCodes.Ldsfld, Field(typeof(CustomRankDetail), nameof(CustomRankDetail._index))),
-
- new(OpCodes.Call, Method(typeof(Mathf), nameof(Mathf.Abs))),
- new(OpCodes.Ldarg_0),
- new(OpCodes.Ldfld, Field(typeof(CustomRankDetail), nameof(CustomRankDetail._options))),
- new(OpCodes.Ldlen),
- new(OpCodes.Conv_I4),
- new(OpCodes.Rem),
- new(OpCodes.Conv_U1),
-
- new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
- });
-
- for (int i = 0; i < newInstructions.Count; i++)
- yield return newInstructions[i];
-
- ListPool.Pool.Return(newInstructions);
+ CustomKeycard.RankDict[pickup.ItemId.SerialNumber] = (byte)(Mathf.Abs(CustomRankDetail._index) % __instance._options.Length);
}
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomSerialNumberDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomSerialNumberDetailData.cs
index 6e9bf24c9a..dffdf1eb64 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomSerialNumberDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomSerialNumberDetailData.cs
@@ -1,4 +1,4 @@
-// -----------------------------------------------------------------------
+// -----------------------------------------------------------------------
//
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
@@ -7,17 +7,10 @@
namespace Exiled.Events.Patches.Generic.KeycardDetails
{
- using System.Collections.Generic;
- using System.Reflection.Emit;
-
using Exiled.API.Features.Items.Keycards;
- using Exiled.API.Features.Pools;
using HarmonyLib;
- using InventorySystem.Items;
using InventorySystem.Items.Keycards;
- using static HarmonyLib.AccessTools;
-
///
/// Patch for storing serial numbers from custom keycards.
///
@@ -25,44 +18,17 @@ namespace Exiled.Events.Patches.Generic.KeycardDetails
public class CustomSerialNumberDetailData
{
[HarmonyPatch(nameof(NametagDetail.WriteNewItem))]
- private static IEnumerable Transpiler1(IEnumerable instructions)
+ [HarmonyPrefix]
+ private static void PrefixItem(KeycardItem item)
{
- List newInstructions = ListPool.Pool.Get(instructions);
-
- newInstructions.InsertRange(0, new CodeInstruction[]
- {
- new(OpCodes.Call, PropertyGetter(typeof(CustomKeycard), nameof(CustomKeycard.SerialNumberDict))),
- new(OpCodes.Ldarg_1),
- new(OpCodes.Callvirt, PropertyGetter(typeof(KeycardItem), nameof(KeycardItem.ItemSerial))),
- new(OpCodes.Ldsfld, Field(typeof(CustomSerialNumberDetail), nameof(CustomSerialNumberDetail._customVal))),
- new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
- });
-
- for (int i = 0; i < newInstructions.Count; i++)
- yield return newInstructions[i];
-
- ListPool.Pool.Return(newInstructions);
+ CustomKeycard.SerialNumberDict[item.ItemSerial] = CustomSerialNumberDetail._customVal;
}
[HarmonyPatch(nameof(NametagDetail.WriteNewPickup))]
- private static IEnumerable Transpiler2(IEnumerable instructions)
+ [HarmonyPrefix]
+ private static void PrefixPickup(KeycardPickup pickup)
{
- List newInstructions = ListPool.Pool.Get(instructions);
-
- newInstructions.InsertRange(0, new CodeInstruction[]
- {
- new(OpCodes.Call, PropertyGetter(typeof(CustomKeycard), nameof(CustomKeycard.SerialNumberDict))),
- new(OpCodes.Ldarg_1),
- new(OpCodes.Callvirt, PropertyGetter(typeof(KeycardPickup), nameof(KeycardPickup.ItemId))),
- new(OpCodes.Ldfld, Field(typeof(ItemIdentifier), nameof(ItemIdentifier.SerialNumber))),
- new(OpCodes.Ldsfld, Field(typeof(CustomSerialNumberDetail), nameof(CustomSerialNumberDetail._customVal))),
- new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
- });
-
- for (int i = 0; i < newInstructions.Count; i++)
- yield return newInstructions[i];
-
- ListPool.Pool.Return(newInstructions);
+ CustomKeycard.SerialNumberDict[pickup.ItemId.SerialNumber] = CustomSerialNumberDetail._customVal;
}
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomTintDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomTintDetailData.cs
index fdefc74f30..1ea428bca4 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomTintDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomTintDetailData.cs
@@ -1,4 +1,4 @@
-// -----------------------------------------------------------------------
+// -----------------------------------------------------------------------
//
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
@@ -7,17 +7,9 @@
namespace Exiled.Events.Patches.Generic.KeycardDetails
{
- using System.Collections.Generic;
- using System.Reflection.Emit;
-
using Exiled.API.Features.Items.Keycards;
- using Exiled.API.Features.Pools;
using HarmonyLib;
- using InventorySystem.Items;
using InventorySystem.Items.Keycards;
- using UnityEngine;
-
- using static HarmonyLib.AccessTools;
///
/// Patch for storing colors from custom keycards.
@@ -26,46 +18,17 @@ namespace Exiled.Events.Patches.Generic.KeycardDetails
public class CustomTintDetailData
{
[HarmonyPatch(nameof(CustomTintDetail.WriteNewItem))]
- [HarmonyTranspiler]
- private static IEnumerable Transpiler1(IEnumerable instructions)
+ [HarmonyPrefix]
+ private static void PrefixItem(KeycardItem item)
{
- List newInstructions = ListPool.Pool.Get(instructions);
-
- newInstructions.InsertRange(0, new CodeInstruction[]
- {
- new(OpCodes.Call, PropertyGetter(typeof(CustomKeycard), nameof(CustomKeycard.ColorDict))),
- new(OpCodes.Ldarg_1),
- new(OpCodes.Callvirt, PropertyGetter(typeof(KeycardItem), nameof(KeycardItem.ItemSerial))),
- new(OpCodes.Ldsfld, Field(typeof(CustomTintDetail), nameof(CustomTintDetail._customColor))),
- new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
- });
-
- for (int i = 0; i < newInstructions.Count; i++)
- yield return newInstructions[i];
-
- ListPool.Pool.Return(newInstructions);
+ CustomKeycard.ColorDict[item.ItemSerial] = CustomTintDetail._customColor;
}
[HarmonyPatch(nameof(CustomTintDetail.WriteNewPickup))]
- [HarmonyTranspiler]
- private static IEnumerable Transpiler2(IEnumerable instructions)
+ [HarmonyPrefix]
+ private static void PrefixPickup(KeycardPickup pickup)
{
- List newInstructions = ListPool.Pool.Get(instructions);
-
- newInstructions.InsertRange(0, new CodeInstruction[]
- {
- new(OpCodes.Call, PropertyGetter(typeof(CustomKeycard), nameof(CustomKeycard.ColorDict))),
- new(OpCodes.Ldarg_1),
- new(OpCodes.Callvirt, PropertyGetter(typeof(KeycardPickup), nameof(KeycardPickup.ItemId))),
- new(OpCodes.Ldfld, Field(typeof(ItemIdentifier), nameof(ItemIdentifier.SerialNumber))),
- new(OpCodes.Ldsfld, Field(typeof(CustomTintDetail), nameof(CustomTintDetail._customColor))),
- new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
- });
-
- for (int i = 0; i < newInstructions.Count; i++)
- yield return newInstructions[i];
-
- ListPool.Pool.Return(newInstructions);
+ CustomKeycard.ColorDict[pickup.ItemId.SerialNumber] = CustomTintDetail._customColor;
}
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomWearDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomWearDetailData.cs
index 15827da01a..ea1a838130 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomWearDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomWearDetailData.cs
@@ -1,4 +1,4 @@
-// -----------------------------------------------------------------------
+// -----------------------------------------------------------------------
//
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
@@ -7,17 +7,10 @@
namespace Exiled.Events.Patches.Generic.KeycardDetails
{
- using System.Collections.Generic;
- using System.Reflection.Emit;
-
using Exiled.API.Features.Items.Keycards;
- using Exiled.API.Features.Pools;
using HarmonyLib;
- using InventorySystem.Items;
using InventorySystem.Items.Keycards;
- using static HarmonyLib.AccessTools;
-
///
/// Patch for storing wear from custom keycards.
///
@@ -26,45 +19,16 @@ public class CustomWearDetailData
{
[HarmonyPatch(nameof(CustomWearDetail.WriteNewItem))]
[HarmonyTranspiler]
- private static IEnumerable Transpiler1(IEnumerable instructions)
+ private static void PrefixItem(KeycardItem item)
{
- List newInstructions = ListPool.Pool.Get(instructions);
-
- newInstructions.InsertRange(0, new CodeInstruction[]
- {
- new(OpCodes.Call, PropertyGetter(typeof(CustomKeycard), nameof(CustomKeycard.WearDict))),
- new(OpCodes.Ldarg_1),
- new(OpCodes.Callvirt, PropertyGetter(typeof(KeycardItem), nameof(KeycardItem.ItemSerial))),
- new(OpCodes.Ldsfld, Field(typeof(CustomWearDetail), nameof(CustomWearDetail._customWearLevel))),
- new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
- });
-
- for (int i = 0; i < newInstructions.Count; i++)
- yield return newInstructions[i];
-
- ListPool.Pool.Return(newInstructions);
+ CustomKeycard.WearDict[item.ItemSerial] = CustomWearDetail._customWearLevel;
}
[HarmonyPatch(nameof(CustomWearDetail.WriteNewPickup))]
[HarmonyTranspiler]
- private static IEnumerable Transpiler2(IEnumerable instructions)
+ private static void PrefixPickup(KeycardPickup pickup)
{
- List newInstructions = ListPool.Pool.Get(instructions);
-
- newInstructions.InsertRange(0, new CodeInstruction[]
- {
- new(OpCodes.Call, PropertyGetter(typeof(CustomKeycard), nameof(CustomKeycard.WearDict))),
- new(OpCodes.Ldarg_1),
- new(OpCodes.Callvirt, PropertyGetter(typeof(KeycardPickup), nameof(KeycardPickup.ItemId))),
- new(OpCodes.Ldfld, Field(typeof(ItemIdentifier), nameof(ItemIdentifier.SerialNumber))),
- new(OpCodes.Ldsfld, Field(typeof(CustomWearDetail), nameof(CustomWearDetail._customWearLevel))),
- new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
- });
-
- for (int i = 0; i < newInstructions.Count; i++)
- yield return newInstructions[i];
-
- ListPool.Pool.Return(newInstructions);
+ CustomKeycard.WearDict[pickup.ItemId.SerialNumber] = CustomWearDetail._customWearLevel;
}
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/NameTagDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/NameTagDetailData.cs
index 3a056f7780..74db357b95 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/NameTagDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/NameTagDetailData.cs
@@ -1,4 +1,4 @@
-// -----------------------------------------------------------------------
+// -----------------------------------------------------------------------
//
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
@@ -7,65 +7,30 @@
namespace Exiled.Events.Patches.Generic.KeycardDetails
{
- using System.Collections.Generic;
- using System.Reflection.Emit;
-
using Exiled.API.Features.Items.Keycards;
- using Exiled.API.Features.Pools;
using Exiled.Events.Patches.Fixes;
using HarmonyLib;
- using InventorySystem.Items;
using InventorySystem.Items.Keycards;
- using static HarmonyLib.AccessTools;
-
///
/// Patch for storing name tags from custom keycards.
///
- /// There's a fix for () so I set the priority of this patch 1 lower than default to avoid errors.
+ /// There's a fix for .
[HarmonyPatch(typeof(NametagDetail))]
- [HarmonyPriority(399)]
public class NameTagDetailData
{
[HarmonyPatch(nameof(NametagDetail.WriteNewItem))]
- private static IEnumerable Transpiler1(IEnumerable instructions)
+ [HarmonyTranspiler]
+ private static void PrefixItem(KeycardItem item)
{
- List newInstructions = ListPool.Pool.Get(instructions);
-
- newInstructions.InsertRange(0, new CodeInstruction[]
- {
- new(OpCodes.Call, PropertyGetter(typeof(CustomKeycard), nameof(CustomKeycard.NameTagDict))),
- new(OpCodes.Ldarg_1),
- new(OpCodes.Callvirt, PropertyGetter(typeof(KeycardItem), nameof(KeycardItem.ItemSerial))),
- new(OpCodes.Ldsfld, Field(typeof(NametagDetail), nameof(NametagDetail._customNametag))),
- new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
- });
-
- for (int i = 0; i < newInstructions.Count; i++)
- yield return newInstructions[i];
-
- ListPool.Pool.Return(newInstructions);
+ CustomKeycard.NameTagDict[item.ItemSerial] = NametagDetail._customNametag;
}
[HarmonyPatch(nameof(NametagDetail.WriteNewPickup))]
- private static IEnumerable Transpiler2(IEnumerable instructions)
+ [HarmonyTranspiler]
+ private static void PrefixPickup(KeycardPickup pickup)
{
- List newInstructions = ListPool.Pool.Get(instructions);
-
- newInstructions.InsertRange(0, new CodeInstruction[]
- {
- new(OpCodes.Call, PropertyGetter(typeof(CustomKeycard), nameof(CustomKeycard.NameTagDict))),
- new(OpCodes.Ldarg_1),
- new(OpCodes.Callvirt, PropertyGetter(typeof(KeycardPickup), nameof(KeycardPickup.ItemId))),
- new(OpCodes.Ldfld, Field(typeof(ItemIdentifier), nameof(ItemIdentifier.SerialNumber))),
- new(OpCodes.Ldsfld, Field(typeof(NametagDetail), nameof(NametagDetail._customNametag))),
- new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
- });
-
- for (int i = 0; i < newInstructions.Count; i++)
- yield return newInstructions[i];
-
- ListPool.Pool.Return(newInstructions);
+ CustomKeycard.NameTagDict[pickup.ItemId.SerialNumber] = NametagDetail._customNametag;
}
}
}
\ No newline at end of file
From 3d8900634a8b8c2e0ff04efe2b4a7dcf772e0dd5 Mon Sep 17 00:00:00 2001
From: Yamato
Date: Wed, 27 Aug 2025 14:50:32 +0200
Subject: [PATCH 14/38] Oups HarmonyPrefix
---
.../Patches/Generic/KeycardDetails/CustomWearDetailData.cs | 4 ++--
.../Patches/Generic/KeycardDetails/NameTagDetailData.cs | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomWearDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomWearDetailData.cs
index ea1a838130..21c345371a 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomWearDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomWearDetailData.cs
@@ -18,14 +18,14 @@ namespace Exiled.Events.Patches.Generic.KeycardDetails
public class CustomWearDetailData
{
[HarmonyPatch(nameof(CustomWearDetail.WriteNewItem))]
- [HarmonyTranspiler]
+ [HarmonyPrefix]
private static void PrefixItem(KeycardItem item)
{
CustomKeycard.WearDict[item.ItemSerial] = CustomWearDetail._customWearLevel;
}
[HarmonyPatch(nameof(CustomWearDetail.WriteNewPickup))]
- [HarmonyTranspiler]
+ [HarmonyPrefix]
private static void PrefixPickup(KeycardPickup pickup)
{
CustomKeycard.WearDict[pickup.ItemId.SerialNumber] = CustomWearDetail._customWearLevel;
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/NameTagDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/NameTagDetailData.cs
index 74db357b95..e649ecd3a9 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/NameTagDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/NameTagDetailData.cs
@@ -20,14 +20,14 @@ namespace Exiled.Events.Patches.Generic.KeycardDetails
public class NameTagDetailData
{
[HarmonyPatch(nameof(NametagDetail.WriteNewItem))]
- [HarmonyTranspiler]
+ [HarmonyPrefix]
private static void PrefixItem(KeycardItem item)
{
CustomKeycard.NameTagDict[item.ItemSerial] = NametagDetail._customNametag;
}
[HarmonyPatch(nameof(NametagDetail.WriteNewPickup))]
- [HarmonyTranspiler]
+ [HarmonyPrefix]
private static void PrefixPickup(KeycardPickup pickup)
{
CustomKeycard.NameTagDict[pickup.ItemId.SerialNumber] = NametagDetail._customNametag;
From 0eb41ba0ee27c311b0d833174d262786437050c3 Mon Sep 17 00:00:00 2001
From: Yamato
Date: Wed, 27 Aug 2025 14:51:46 +0200
Subject: [PATCH 15/38] CustomSerialNumberDetail
---
.../Generic/KeycardDetails/CustomSerialNumberDetailData.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomSerialNumberDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomSerialNumberDetailData.cs
index dffdf1eb64..86ad34ebc0 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomSerialNumberDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomSerialNumberDetailData.cs
@@ -17,14 +17,14 @@ namespace Exiled.Events.Patches.Generic.KeycardDetails
[HarmonyPatch(typeof(CustomSerialNumberDetail))]
public class CustomSerialNumberDetailData
{
- [HarmonyPatch(nameof(NametagDetail.WriteNewItem))]
+ [HarmonyPatch(nameof(CustomSerialNumberDetail.WriteNewItem))]
[HarmonyPrefix]
private static void PrefixItem(KeycardItem item)
{
CustomKeycard.SerialNumberDict[item.ItemSerial] = CustomSerialNumberDetail._customVal;
}
- [HarmonyPatch(nameof(NametagDetail.WriteNewPickup))]
+ [HarmonyPatch(nameof(CustomSerialNumberDetail.WriteNewPickup))]
[HarmonyPrefix]
private static void PrefixPickup(KeycardPickup pickup)
{
From a486d70e3f2c2896bb5f38d3b23c9037b5a8780c Mon Sep 17 00:00:00 2001
From: "@Someone" <45270312+Someone-193@users.noreply.github.com>
Date: Wed, 27 Aug 2025 15:07:31 -0400
Subject: [PATCH 16/38] Fix NW bug lol
---
.../Exiled.API/Extensions/MirrorExtensions.cs | 2 +-
.../Items/Keycards/PermissionsProvider.cs | 73 +++++++++++++
.../Patches/Fixes/ThrownCustomKeycardFix.cs | 101 ++++++++++++++++++
3 files changed, 175 insertions(+), 1 deletion(-)
create mode 100644 EXILED/Exiled.API/Features/Items/Keycards/PermissionsProvider.cs
create mode 100644 EXILED/Exiled.Events/Patches/Fixes/ThrownCustomKeycardFix.cs
diff --git a/EXILED/Exiled.API/Extensions/MirrorExtensions.cs b/EXILED/Exiled.API/Extensions/MirrorExtensions.cs
index 20b0ce06a2..83fc70caf4 100644
--- a/EXILED/Exiled.API/Extensions/MirrorExtensions.cs
+++ b/EXILED/Exiled.API/Extensions/MirrorExtensions.cs
@@ -412,7 +412,7 @@ public static void ResyncKeycardItem(Features.Items.Keycards.CustomKeycard custo
{
if (KeycardDetailSynchronizer.Database.Remove(customKeycard.Serial))
{
- KeycardDetailSynchronizer.ServerProcessItem((KeycardItem)customKeycard.Base);
+ KeycardDetailSynchronizer.ServerProcessItem(customKeycard.Base);
}
}
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/PermissionsProvider.cs b/EXILED/Exiled.API/Features/Items/Keycards/PermissionsProvider.cs
new file mode 100644
index 0000000000..bbf6b31de7
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Items/Keycards/PermissionsProvider.cs
@@ -0,0 +1,73 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Items.Keycards
+{
+ using Interactables.Interobjects.DoorUtils;
+ using InventorySystem.Items;
+ using InventorySystem.Items.Autosync;
+ using InventorySystem.Items.Keycards;
+ using Mirror;
+
+ ///
+ /// A simple class for providing permissions with .
+ ///
+ public class PermissionsProvider : IDoorPermissionProvider
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The flags of this provider.
+ /// The to imitate.
+ /// The serial to imitate.
+ public PermissionsProvider(DoorPermissionFlags flags, ItemType type, ushort serial)
+ {
+ Flags = flags;
+ Type = type;
+ Serial = serial;
+
+ PermissionsUsedCallback = (_, success) =>
+ {
+ using (new AutosyncRpc(new ItemIdentifier(Type, Serial), out NetworkWriter writer))
+ {
+ writer.WriteSubheader(KeycardItem.MsgType.OnKeycardUsed);
+ writer.WriteBool(success);
+ }
+ };
+ }
+
+ ///
+ /// Gets or sets the permissions of this provider.
+ ///
+ public DoorPermissionFlags Flags { get; set; }
+
+ ///
+ /// Gets or sets the this imitates.
+ ///
+ public ItemType Type { get; set; }
+
+ ///
+ /// Gets or sets the serial this imitates.
+ ///
+ public ushort Serial { get; set; }
+
+ ///
+ /// Gets the action called when this is used.
+ ///
+ public PermissionUsed PermissionsUsedCallback { get; }
+
+ ///
+ /// Gets the permissions of this .
+ ///
+ /// Not used.
+ /// The of this .
+ public DoorPermissionFlags GetPermissions(IDoorPermissionRequester requester)
+ {
+ return Flags;
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Fixes/ThrownCustomKeycardFix.cs b/EXILED/Exiled.Events/Patches/Fixes/ThrownCustomKeycardFix.cs
new file mode 100644
index 0000000000..1182705360
--- /dev/null
+++ b/EXILED/Exiled.Events/Patches/Fixes/ThrownCustomKeycardFix.cs
@@ -0,0 +1,101 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.Patches.Fixes
+{
+ using System.Collections.Generic;
+ using System.Reflection.Emit;
+
+ using Exiled.API.Extensions;
+ using Exiled.API.Features;
+ using Exiled.API.Features.Items.Keycards;
+ using Exiled.API.Features.Pools;
+ using HarmonyLib;
+ using Interactables.Interobjects.DoorUtils;
+ using InventorySystem.Items.Keycards;
+ using InventorySystem.Items.Pickups;
+
+ using static HarmonyLib.AccessTools;
+
+ ///
+ /// Patches to fix custom keycards with custom permissions not working.
+ /// Bug reported to NW (https://git.scpslgame.com/northwood-qa/scpsl-bug-reporting/-/issues/1625).
+ ///
+ [HarmonyPatch(typeof(KeycardPickup), nameof(KeycardPickup.ProcessCollision))]
+ public class ThrownCustomKeycardFix
+ {
+ private static IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator)
+ {
+ List newInstructions = ListPool.Pool.Get(instructions);
+
+ LocalBuilder permissions = generator.DeclareLocal(typeof(DoorPermissionFlags));
+
+ LocalBuilder type = generator.DeclareLocal(typeof(ItemType));
+ LocalBuilder serial = generator.DeclareLocal(typeof(ushort));
+
+ Label newDefault = generator.DefineLabel();
+
+ // index before this.Info.ItemId.TryGetTemplate(out provider);
+ int index = newInstructions.FindIndex(instruction => instruction.opcode == OpCodes.Ldflda) - 1;
+
+ // get label of start of TryGetTemplate from earlier brtrue
+ object runDefault = newInstructions[index - 2].operand;
+ newInstructions[index - 2].operand = newDefault;
+
+ // get label of after TryGetTemplate from later brtrue
+ object skipDefault = newInstructions[index + 5].operand;
+
+ newInstructions.InsertRange(index, new[]
+ {
+ // type = this.Info.ItemId;
+ new CodeInstruction(OpCodes.Ldarg_0).WithLabels(newDefault),
+ new(OpCodes.Ldflda, Field(typeof(KeycardPickup), nameof(KeycardPickup.Info))),
+ new(OpCodes.Ldfld, Field(typeof(PickupSyncInfo), nameof(PickupSyncInfo.ItemId))),
+ new(OpCodes.Stloc, type),
+
+ // type.IsCustomKeycard();
+ new(OpCodes.Ldloc, type),
+ new(OpCodes.Call, Method(typeof(ItemExtensions), nameof(ItemExtensions.IsCustomKeycard))),
+
+ // jump to default execution if keycard is not custom
+ new(OpCodes.Brfalse, runDefault),
+
+ // load dictionary
+ new(OpCodes.Ldsfld, Field(typeof(CustomPermsDetail), nameof(CustomPermsDetail.CustomPermissions))),
+
+ // serial = this.Info.Serial;
+ new(OpCodes.Ldarg_0),
+ new(OpCodes.Ldflda, Field(typeof(KeycardPickup), nameof(KeycardPickup.Info))),
+ new(OpCodes.Ldfld, Field(typeof(PickupSyncInfo), nameof(PickupSyncInfo.Serial))),
+ new(OpCodes.Stloc, serial),
+
+ // Dictionary.TryGetValue(serial, out DoorPermissionFlags permissions);
+ new(OpCodes.Ldloc, serial),
+ new(OpCodes.Ldloca, permissions),
+ new(OpCodes.Callvirt, Method(typeof(Dictionary), nameof(Dictionary.TryGetValue))),
+
+ // go to normal execution if no custom perms found
+ new(OpCodes.Brfalse, runDefault),
+
+ // provider = new PermissionsProvider(permissions, type, serial);
+ new(OpCodes.Ldloc, permissions),
+ new(OpCodes.Ldloc, type),
+ new(OpCodes.Ldloc, serial),
+ new(OpCodes.Newobj, Constructor(typeof(PermissionsProvider), new[] { typeof(DoorPermissionFlags), typeof(ItemType), typeof(ushort) })),
+ new(OpCodes.Stloc_2),
+
+ // skip past TryGetTemplate
+ new(OpCodes.Br, skipDefault),
+ });
+
+ for (int z = 0; z < newInstructions.Count; z++)
+ yield return newInstructions[z];
+
+ ListPool.Pool.Return(newInstructions);
+ }
+ }
+}
\ No newline at end of file
From c28f4263c3e65be72cdbdd6b5c551b00bf12b278 Mon Sep 17 00:00:00 2001
From: "@Someone" <45270312+Someone-193@users.noreply.github.com>
Date: Wed, 27 Aug 2025 15:24:08 -0400
Subject: [PATCH 17/38] Consolidate dictionaries + add clearing
---
.../Features/Items/Keycards/CustomKeycard.cs | 48 +++-------------
.../Features/Items/Keycards/KeycardData.cs | 57 +++++++++++++++++++
.../Items/Keycards/ManagementKeycard.cs | 8 +--
.../Features/Items/Keycards/MetalKeycard.cs | 20 +++----
.../Features/Items/Keycards/Site02Keycard.cs | 16 +++---
.../Items/Keycards/TaskForceKeycard.cs | 12 ++--
EXILED/Exiled.API/Features/Map.cs | 3 +
.../Patches/Fixes/ThrownCustomKeycardFix.cs | 1 -
.../KeycardDetails/CustomLabelDetailData.cs | 8 +--
.../KeycardDetails/CustomPermsDetailData.cs | 2 +-
.../KeycardDetails/CustomRankDetailData.cs | 4 +-
.../CustomSerialNumberDetailData.cs | 4 +-
.../KeycardDetails/CustomTintDetailData.cs | 4 +-
.../KeycardDetails/CustomWearDetailData.cs | 4 +-
.../KeycardDetails/NameTagDetailData.cs | 5 +-
15 files changed, 110 insertions(+), 86 deletions(-)
create mode 100644 EXILED/Exiled.API/Features/Items/Keycards/KeycardData.cs
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
index 5864bf4f0d..6ba1cd8d84 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
@@ -34,6 +34,7 @@ internal CustomKeycard(KeycardItem itemBase)
: base(itemBase)
{
Base = itemBase;
+ DataDict.Add(Serial, new KeycardData());
Resync();
}
@@ -87,11 +88,11 @@ public KeycardLevels KeycardLevels
///
public Color32? PermissionsColor
{
- get => PermsColorDict.TryGetValue(Serial, out Color32? value) ? value : null;
+ get => DataDict[Serial].PermissionsColor;
set
{
- PermsColorDict[Serial] = value;
+ DataDict[Serial].PermissionsColor = value;
Resync();
}
@@ -132,55 +133,20 @@ public string ItemName
///
public Color32? Color
{
- get => ColorDict.TryGetValue(Serial, out Color32? value) ? value : null;
+ get => DataDict[Serial].Color;
set
{
- ColorDict[Serial] = value;
+ DataDict[Serial].Color = value;
Resync();
}
}
///
- /// Gets a dictionary of item serials to their permissions color.
+ /// Gets a dictionary of item serials to their keycards data.
///
- internal static Dictionary PermsColorDict { get; } = new();
-
- ///
- /// Gets a dictionary of item serials to their color.
- ///
- internal static Dictionary ColorDict { get; } = new();
-
- ///
- /// Gets a dictionary of item serials to their name tag.
- ///
- internal static Dictionary NameTagDict { get; } = new();
-
- ///
- /// Gets a dictionary of item serials to their label.
- ///
- internal static Dictionary LabelDict { get; } = new();
-
- ///
- /// Gets a dictionary of item serials to their label's color.
- ///
- internal static Dictionary LabelColorDict { get; } = new();
-
- ///
- /// Gets a dictionary of item serials to their wear.
- ///
- internal static Dictionary WearDict { get; } = new();
-
- ///
- /// Gets a dictionary of item serials to their serial number.
- ///
- internal static Dictionary SerialNumberDict { get; } = new();
-
- ///
- /// Gets a dictionary of item serials to their serial number.
- ///
- internal static Dictionary RankDict { get; } = new();
+ internal static Dictionary DataDict { get; } = new();
///
/// Resyncs all properties of the keycard.
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/KeycardData.cs b/EXILED/Exiled.API/Features/Items/Keycards/KeycardData.cs
new file mode 100644
index 0000000000..e9da214c38
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Items/Keycards/KeycardData.cs
@@ -0,0 +1,57 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Items.Keycards
+{
+ using UnityEngine;
+
+ ///
+ /// A class containing all possible properties of any keycard that aren't stored by the server.
+ ///
+ public class KeycardData
+ {
+ ///
+ /// Gets or sets the permissions color of this .
+ ///
+ public Color32? PermissionsColor { get; set; }
+
+ ///
+ /// Gets or sets the color of this .
+ ///
+ public Color32? Color { get; set; }
+
+ ///
+ /// Gets or sets the name tag of this .
+ ///
+ public string NameTag { get; set; } = string.Empty;
+
+ ///
+ /// Gets or sets the label of this .
+ ///
+ public string Label { get; set; } = string.Empty;
+
+ ///
+ /// Gets or sets the label color of this .
+ ///
+ public Color32? LabelColor { get; set; }
+
+ ///
+ /// Gets or sets the wear of this .
+ ///
+ public byte Wear { get; set; } = 255;
+
+ ///
+ /// Gets or sets the serial number of this .
+ ///
+ public string SerialNumber { get; set; } = string.Empty;
+
+ ///
+ /// Gets or sets the rank of this .
+ ///
+ public byte Rank { get; set; } = 255;
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs
index ed58ed67c6..972627b5db 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs
@@ -42,11 +42,11 @@ internal ManagementKeycard(ItemType type)
///
public string Label
{
- get => LabelDict.TryGetValue(Serial, out string value) ? value : string.Empty;
+ get => DataDict[Serial].Label;
set
{
- LabelDict[Serial] = value;
+ DataDict[Serial].Label = value;
Resync();
}
}
@@ -54,11 +54,11 @@ public string Label
///
public Color32? LabelColor
{
- get => LabelColorDict.TryGetValue(Serial, out Color32? value) ? value : null;
+ get => DataDict[Serial].LabelColor;
set
{
- LabelColorDict[Serial] = value;
+ DataDict[Serial].LabelColor = value;
Resync();
}
}
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs
index 4226d8da0d..fa6400579a 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs
@@ -42,11 +42,11 @@ internal MetalKeycard(ItemType type)
///
public string NameTag
{
- get => NameTagDict.TryGetValue(Serial, out string value) ? value : string.Empty;
+ get => DataDict[Serial].NameTag;
set
{
- NameTagDict[Serial] = value;
+ DataDict[Serial].NameTag = value;
Resync();
}
}
@@ -54,11 +54,11 @@ public string NameTag
///
public string Label
{
- get => LabelDict.TryGetValue(Serial, out string value) ? value : string.Empty;
+ get => DataDict[Serial].Label;
set
{
- LabelDict[Serial] = value;
+ DataDict[Serial].Label = value;
Resync();
}
}
@@ -66,11 +66,11 @@ public string Label
///
public Color32? LabelColor
{
- get => LabelColorDict.TryGetValue(Serial, out Color32? value) ? value : null;
+ get => DataDict[Serial].LabelColor;
set
{
- LabelColorDict[Serial] = value;
+ DataDict[Serial].LabelColor = value;
Resync();
}
}
@@ -79,11 +79,11 @@ public Color32? LabelColor
/// Capped from 0-5 for Site-02 keycards, returns 255 if no wear level is found.
public byte Wear
{
- get => WearDict.TryGetValue(Serial, out byte value) ? value : byte.MaxValue;
+ get => DataDict[Serial].Wear;
set
{
- WearDict[Serial] = value;
+ DataDict[Serial].Wear = value;
Resync();
}
@@ -92,11 +92,11 @@ public byte Wear
///
public string SerialNumber
{
- get => SerialNumberDict.TryGetValue(Serial, out string value) ? value : string.Empty;
+ get => DataDict[Serial].SerialNumber;
set
{
- SerialNumberDict[Serial] = value;
+ DataDict[Serial].SerialNumber = value;
Resync();
}
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
index 40e8e5328f..aa63ab4d09 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
@@ -42,11 +42,11 @@ internal Site02Keycard(ItemType type)
///
public string NameTag
{
- get => NameTagDict.TryGetValue(Serial, out string value) ? value : string.Empty;
+ get => DataDict[Serial].NameTag;
set
{
- NameTagDict[Serial] = value;
+ DataDict[Serial].NameTag = value;
Resync();
}
}
@@ -54,11 +54,11 @@ public string NameTag
///
public string Label
{
- get => LabelDict.TryGetValue(Serial, out string value) ? value : string.Empty;
+ get => DataDict[Serial].Label;
set
{
- LabelDict[Serial] = value;
+ DataDict[Serial].Label = value;
Resync();
}
}
@@ -66,11 +66,11 @@ public string Label
///
public Color32? LabelColor
{
- get => LabelColorDict.TryGetValue(Serial, out Color32? value) ? value : null;
+ get => DataDict[Serial].LabelColor;
set
{
- LabelColorDict[Serial] = value;
+ DataDict[Serial].LabelColor = value;
Resync();
}
}
@@ -79,11 +79,11 @@ public Color32? LabelColor
/// Capped from 0-4 for Site-02 keycards, returns 255 if no wear level is found.
public byte Wear
{
- get => WearDict.TryGetValue(Serial, out byte value) ? value : byte.MaxValue;
+ get => DataDict[Serial].Wear;
set
{
- WearDict[Serial] = value;
+ DataDict[Serial].Wear = value;
Resync();
}
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs
index d10f4db69c..00b6f18fcf 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs
@@ -42,11 +42,11 @@ internal TaskForceKeycard(ItemType type)
///
public string NameTag
{
- get => NameTagDict.TryGetValue(Serial, out string value) ? value : string.Empty;
+ get => DataDict[Serial].NameTag;
set
{
- NameTagDict[Serial] = value;
+ DataDict[Serial].NameTag = value;
Resync();
}
}
@@ -54,11 +54,11 @@ public string NameTag
///
public string SerialNumber
{
- get => SerialNumberDict.TryGetValue(Serial, out string value) ? value : string.Empty;
+ get => DataDict[Serial].SerialNumber;
set
{
- SerialNumberDict[Serial] = value;
+ DataDict[Serial].SerialNumber = value;
Resync();
}
@@ -67,11 +67,11 @@ public string SerialNumber
///
public byte Rank
{
- get => RankDict.TryGetValue(Serial, out byte value) ? value : byte.MaxValue;
+ get => DataDict[Serial].Rank;
set
{
- RankDict[Serial] = value;
+ DataDict[Serial].Rank = value;
Resync();
}
diff --git a/EXILED/Exiled.API/Features/Map.cs b/EXILED/Exiled.API/Features/Map.cs
index 90ca019f81..295b60f7d2 100644
--- a/EXILED/Exiled.API/Features/Map.cs
+++ b/EXILED/Exiled.API/Features/Map.cs
@@ -5,6 +5,7 @@
//
// -----------------------------------------------------------------------
+using Exiled.API.Features.Items.Keycards;
namespace Exiled.API.Features
{
#pragma warning disable SA1401
@@ -417,6 +418,8 @@ internal static void ClearCache()
Firearm.BaseCodesValue.Clear();
Firearm.AvailableAttachmentsValue.Clear();
+ CustomKeycard.DataDict.Clear();
+
#pragma warning disable CS0618
Scp559.CakeToWrapper.Clear();
diff --git a/EXILED/Exiled.Events/Patches/Fixes/ThrownCustomKeycardFix.cs b/EXILED/Exiled.Events/Patches/Fixes/ThrownCustomKeycardFix.cs
index 1182705360..24feae442f 100644
--- a/EXILED/Exiled.Events/Patches/Fixes/ThrownCustomKeycardFix.cs
+++ b/EXILED/Exiled.Events/Patches/Fixes/ThrownCustomKeycardFix.cs
@@ -11,7 +11,6 @@ namespace Exiled.Events.Patches.Fixes
using System.Reflection.Emit;
using Exiled.API.Extensions;
- using Exiled.API.Features;
using Exiled.API.Features.Items.Keycards;
using Exiled.API.Features.Pools;
using HarmonyLib;
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomLabelDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomLabelDetailData.cs
index 83f0e38c3c..92aef090a1 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomLabelDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomLabelDetailData.cs
@@ -21,16 +21,16 @@ public class CustomLabelDetailData
[HarmonyPrefix]
private static void Prefix(KeycardItem item)
{
- CustomKeycard.LabelDict[item.ItemSerial] = CustomLabelDetail._customText;
- CustomKeycard.LabelColorDict[item.ItemSerial] = CustomLabelDetail._customColor;
+ CustomKeycard.DataDict[item.ItemSerial].Label = CustomLabelDetail._customText;
+ CustomKeycard.DataDict[item.ItemSerial].LabelColor = CustomLabelDetail._customColor;
}
[HarmonyPatch(nameof(CustomLabelDetail.WriteNewPickup))]
[HarmonyPrefix]
private static void Prefix(KeycardPickup pickup)
{
- CustomKeycard.LabelDict[pickup.ItemId.SerialNumber] = CustomLabelDetail._customText;
- CustomKeycard.LabelColorDict[pickup.ItemId.SerialNumber] = CustomLabelDetail._customColor;
+ CustomKeycard.DataDict[pickup.ItemId.SerialNumber].Label = CustomLabelDetail._customText;
+ CustomKeycard.DataDict[pickup.ItemId.SerialNumber].LabelColor = CustomLabelDetail._customColor;
}
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomPermsDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomPermsDetailData.cs
index 1254408737..4237bc1933 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomPermsDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomPermsDetailData.cs
@@ -20,7 +20,7 @@ public class CustomPermsDetailData
{
private static void Prefix(IIdentifierProvider target)
{
- CustomKeycard.PermsColorDict[target.ItemId.SerialNumber] = CustomPermsDetail._customColor;
+ CustomKeycard.DataDict[target.ItemId.SerialNumber].PermissionsColor = CustomPermsDetail._customColor;
}
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomRankDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomRankDetailData.cs
index a63f0fa517..9808e33216 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomRankDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomRankDetailData.cs
@@ -24,14 +24,14 @@ public class CustomRankDetailData
[HarmonyPrefix]
private static void PrefixItem(CustomRankDetail __instance, KeycardItem item)
{
- CustomKeycard.RankDict[item.ItemSerial] = (byte)(Mathf.Abs(CustomRankDetail._index) % __instance._options.Length);
+ CustomKeycard.DataDict[item.ItemSerial].Rank = (byte)(Mathf.Abs(CustomRankDetail._index) % __instance._options.Length);
}
[HarmonyPatch(nameof(CustomRankDetail.WriteNewPickup))]
[HarmonyPrefix]
private static void PrefixPickup(CustomRankDetail __instance, KeycardPickup pickup)
{
- CustomKeycard.RankDict[pickup.ItemId.SerialNumber] = (byte)(Mathf.Abs(CustomRankDetail._index) % __instance._options.Length);
+ CustomKeycard.DataDict[pickup.ItemId.SerialNumber].Rank = (byte)(Mathf.Abs(CustomRankDetail._index) % __instance._options.Length);
}
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomSerialNumberDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomSerialNumberDetailData.cs
index 86ad34ebc0..c48d55ab38 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomSerialNumberDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomSerialNumberDetailData.cs
@@ -21,14 +21,14 @@ public class CustomSerialNumberDetailData
[HarmonyPrefix]
private static void PrefixItem(KeycardItem item)
{
- CustomKeycard.SerialNumberDict[item.ItemSerial] = CustomSerialNumberDetail._customVal;
+ CustomKeycard.DataDict[item.ItemSerial].SerialNumber = CustomSerialNumberDetail._customVal;
}
[HarmonyPatch(nameof(CustomSerialNumberDetail.WriteNewPickup))]
[HarmonyPrefix]
private static void PrefixPickup(KeycardPickup pickup)
{
- CustomKeycard.SerialNumberDict[pickup.ItemId.SerialNumber] = CustomSerialNumberDetail._customVal;
+ CustomKeycard.DataDict[pickup.ItemId.SerialNumber].SerialNumber = CustomSerialNumberDetail._customVal;
}
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomTintDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomTintDetailData.cs
index 1ea428bca4..f26bb73e4a 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomTintDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomTintDetailData.cs
@@ -21,14 +21,14 @@ public class CustomTintDetailData
[HarmonyPrefix]
private static void PrefixItem(KeycardItem item)
{
- CustomKeycard.ColorDict[item.ItemSerial] = CustomTintDetail._customColor;
+ CustomKeycard.DataDict[item.ItemSerial].Color = CustomTintDetail._customColor;
}
[HarmonyPatch(nameof(CustomTintDetail.WriteNewPickup))]
[HarmonyPrefix]
private static void PrefixPickup(KeycardPickup pickup)
{
- CustomKeycard.ColorDict[pickup.ItemId.SerialNumber] = CustomTintDetail._customColor;
+ CustomKeycard.DataDict[pickup.ItemId.SerialNumber].Color = CustomTintDetail._customColor;
}
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomWearDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomWearDetailData.cs
index 21c345371a..3ed41c9900 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomWearDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomWearDetailData.cs
@@ -21,14 +21,14 @@ public class CustomWearDetailData
[HarmonyPrefix]
private static void PrefixItem(KeycardItem item)
{
- CustomKeycard.WearDict[item.ItemSerial] = CustomWearDetail._customWearLevel;
+ CustomKeycard.DataDict[item.ItemSerial].Wear = CustomWearDetail._customWearLevel;
}
[HarmonyPatch(nameof(CustomWearDetail.WriteNewPickup))]
[HarmonyPrefix]
private static void PrefixPickup(KeycardPickup pickup)
{
- CustomKeycard.WearDict[pickup.ItemId.SerialNumber] = CustomWearDetail._customWearLevel;
+ CustomKeycard.DataDict[pickup.ItemId.SerialNumber].Wear = CustomWearDetail._customWearLevel;
}
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/NameTagDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/NameTagDetailData.cs
index e649ecd3a9..9a746b682b 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/NameTagDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/NameTagDetailData.cs
@@ -8,7 +8,6 @@
namespace Exiled.Events.Patches.Generic.KeycardDetails
{
using Exiled.API.Features.Items.Keycards;
- using Exiled.Events.Patches.Fixes;
using HarmonyLib;
using InventorySystem.Items.Keycards;
@@ -23,14 +22,14 @@ public class NameTagDetailData
[HarmonyPrefix]
private static void PrefixItem(KeycardItem item)
{
- CustomKeycard.NameTagDict[item.ItemSerial] = NametagDetail._customNametag;
+ CustomKeycard.DataDict[item.ItemSerial].NameTag = NametagDetail._customNametag;
}
[HarmonyPatch(nameof(NametagDetail.WriteNewPickup))]
[HarmonyPrefix]
private static void PrefixPickup(KeycardPickup pickup)
{
- CustomKeycard.NameTagDict[pickup.ItemId.SerialNumber] = NametagDetail._customNametag;
+ CustomKeycard.DataDict[pickup.ItemId.SerialNumber].NameTag = NametagDetail._customNametag;
}
}
}
\ No newline at end of file
From a3abb2f1d485d411fdfd66a2dd1d683e1a5549ea Mon Sep 17 00:00:00 2001
From: "@Someone" <45270312+Someone-193@users.noreply.github.com>
Date: Wed, 27 Aug 2025 15:27:58 -0400
Subject: [PATCH 18/38] Poor choice of method (and using error)
---
EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs | 4 +++-
EXILED/Exiled.API/Features/Map.cs | 2 +-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
index 6ba1cd8d84..02bc23de80 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
@@ -34,7 +34,9 @@ internal CustomKeycard(KeycardItem itemBase)
: base(itemBase)
{
Base = itemBase;
- DataDict.Add(Serial, new KeycardData());
+
+ if (!DataDict.ContainsKey(Serial))
+ DataDict[Serial] = new KeycardData();
Resync();
}
diff --git a/EXILED/Exiled.API/Features/Map.cs b/EXILED/Exiled.API/Features/Map.cs
index 295b60f7d2..b019c65b7d 100644
--- a/EXILED/Exiled.API/Features/Map.cs
+++ b/EXILED/Exiled.API/Features/Map.cs
@@ -5,7 +5,6 @@
//
// -----------------------------------------------------------------------
-using Exiled.API.Features.Items.Keycards;
namespace Exiled.API.Features
{
#pragma warning disable SA1401
@@ -20,6 +19,7 @@ namespace Exiled.API.Features
using Enums;
using Exiled.API.Extensions;
using Exiled.API.Features.Hazards;
+ using Exiled.API.Features.Items.Keycards;
using Exiled.API.Features.Pickups;
using Exiled.API.Features.Toys;
using InventorySystem;
From 2639941b7b50b2d4cff337716e63cd72c61542e5 Mon Sep 17 00:00:00 2001
From: Yamato
Date: Wed, 27 Aug 2025 22:09:42 +0200
Subject: [PATCH 19/38] add ToString override
---
EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
index 02bc23de80..74e6a63329 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
@@ -191,5 +191,11 @@ public T GetDetail()
{
return (T)Base.Details.First(detail => detail is T);
}
+
+ ///
+ /// Returns the Keycard in a human readable format.
+ ///
+ /// A string containing Keycard-related data.
+ public override string ToString() => $"{Type} ={ItemName}= ({Serial}) [{Weight}] *{Scale}* |{Permissions}|";
}
}
\ No newline at end of file
From 05eed990ce6bda132286a9aff9d954658f4ab868 Mon Sep 17 00:00:00 2001
From: "@Someone" <45270312+Someone-193@users.noreply.github.com>
Date: Wed, 27 Aug 2025 18:11:20 -0400
Subject: [PATCH 20/38] I fix
---
.../Patches/Generic/KeycardDetails/NameTagDetailData.cs | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/NameTagDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/NameTagDetailData.cs
index 9a746b682b..5d2f33a956 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/NameTagDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/NameTagDetailData.cs
@@ -22,14 +22,16 @@ public class NameTagDetailData
[HarmonyPrefix]
private static void PrefixItem(KeycardItem item)
{
- CustomKeycard.DataDict[item.ItemSerial].NameTag = NametagDetail._customNametag;
+ if (CustomKeycard.DataDict.TryGetValue(item.ItemSerial, out KeycardData data))
+ data.NameTag = NametagDetail._customNametag;
}
[HarmonyPatch(nameof(NametagDetail.WriteNewPickup))]
[HarmonyPrefix]
private static void PrefixPickup(KeycardPickup pickup)
{
- CustomKeycard.DataDict[pickup.ItemId.SerialNumber].NameTag = NametagDetail._customNametag;
+ if (CustomKeycard.DataDict.TryGetValue(pickup.ItemId.SerialNumber, out KeycardData data))
+ data.NameTag = NametagDetail._customNametag;
}
}
}
\ No newline at end of file
From 5683e24dde269b4027accd2a1d924ec710829d00 Mon Sep 17 00:00:00 2001
From: "@Someone" <45270312+Someone-193@users.noreply.github.com>
Date: Wed, 27 Aug 2025 20:13:56 -0400
Subject: [PATCH 21/38] Rename stuff, revert to Color, add FindMatch and
CustomKeycardPickup stuff
---
.../Exiled.API/Extensions/MirrorExtensions.cs | 20 +-
...{CustomKeycard.cs => CustomKeycardItem.cs} | 149 +++++++----
.../Features/Items/Keycards/KeycardData.cs | 5 +
.../Items/Keycards/ManagementKeycard.cs | 6 +-
.../Features/Items/Keycards/MetalKeycard.cs | 7 +-
.../Features/Items/Keycards/Site02Keycard.cs | 6 +-
.../Items/Keycards/TaskForceKeycard.cs | 2 +-
EXILED/Exiled.API/Features/Map.cs | 2 +-
.../Features/Pickups/KeycardPickup.cs | 8 +-
.../Pickups/Keycards/CustomKeycardPickup.cs | 236 ++++++++++++++++++
.../Pickups/Keycards/KeycardPickup.cs | 46 ----
.../Keycards/ManagementKeycardPickup.cs | 86 +++++++
.../Pickups/Keycards/MetalKeycardPickup.cs | 131 ++++++++++
.../Pickups/Keycards/Site02KeycardPickup.cs | 116 +++++++++
.../Keycards/TaskForceKeycardPickup.cs | 102 ++++++++
EXILED/Exiled.API/Features/Pickups/Pickup.cs | 19 +-
.../Interfaces/Keycards/ILabelKeycard.cs | 8 +-
.../Interfaces/Keycards/INameTagKeycard.cs | 4 +-
.../Interfaces/Keycards/IRankKeycard.cs | 4 +-
.../Keycards/ISerialNumberKeycard.cs | 4 +-
.../Interfaces/Keycards/IWearKeycard.cs | 4 +-
.../CustomItemNameDetailData.cs | 34 +++
.../KeycardDetails/CustomLabelDetailData.cs | 8 +-
.../KeycardDetails/CustomPermsDetailData.cs | 2 +-
.../KeycardDetails/CustomRankDetailData.cs | 4 +-
.../CustomSerialNumberDetailData.cs | 4 +-
.../KeycardDetails/CustomTintDetailData.cs | 4 +-
.../KeycardDetails/CustomWearDetailData.cs | 4 +-
.../KeycardDetails/NameTagDetailData.cs | 4 +-
29 files changed, 884 insertions(+), 145 deletions(-)
rename EXILED/Exiled.API/Features/Items/Keycards/{CustomKeycard.cs => CustomKeycardItem.cs} (51%)
create mode 100644 EXILED/Exiled.API/Features/Pickups/Keycards/CustomKeycardPickup.cs
delete mode 100644 EXILED/Exiled.API/Features/Pickups/Keycards/KeycardPickup.cs
create mode 100644 EXILED/Exiled.API/Features/Pickups/Keycards/ManagementKeycardPickup.cs
create mode 100644 EXILED/Exiled.API/Features/Pickups/Keycards/MetalKeycardPickup.cs
create mode 100644 EXILED/Exiled.API/Features/Pickups/Keycards/Site02KeycardPickup.cs
create mode 100644 EXILED/Exiled.API/Features/Pickups/Keycards/TaskForceKeycardPickup.cs
create mode 100644 EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomItemNameDetailData.cs
diff --git a/EXILED/Exiled.API/Extensions/MirrorExtensions.cs b/EXILED/Exiled.API/Extensions/MirrorExtensions.cs
index 83fc70caf4..1cd2eea7e7 100644
--- a/EXILED/Exiled.API/Extensions/MirrorExtensions.cs
+++ b/EXILED/Exiled.API/Extensions/MirrorExtensions.cs
@@ -19,6 +19,8 @@ namespace Exiled.API.Extensions
using CustomPlayerEffects;
using Exiled.API.Enums;
using Exiled.API.Features.Items;
+ using Exiled.API.Features.Items.Keycards;
+ using Exiled.API.Features.Pickups.Keycards;
using Features;
using Features.Pools;
using InventorySystem;
@@ -37,8 +39,6 @@ namespace Exiled.API.Extensions
using Respawning;
using UnityEngine;
- using KeycardPickup = Exiled.API.Features.Pickups.Keycards.KeycardPickup;
-
///
/// A set of extensions for Networking.
///
@@ -407,24 +407,24 @@ public static void SendFakeEffectTo(this Player effectOwner, Player target, Effe
///
/// Makes the server resend a message to all clients updating a keycards details to current values.
///
- /// The keycard to resync.
- public static void ResyncKeycardItem(Features.Items.Keycards.CustomKeycard customKeycard)
+ /// The keycard to resync.
+ public static void ResyncKeycardItem(CustomKeycardItem customKeycardItem)
{
- if (KeycardDetailSynchronizer.Database.Remove(customKeycard.Serial))
+ if (KeycardDetailSynchronizer.Database.Remove(customKeycardItem.Serial))
{
- KeycardDetailSynchronizer.ServerProcessItem(customKeycard.Base);
+ KeycardDetailSynchronizer.ServerProcessItem(customKeycardItem.Base);
}
}
///
/// Makes the server resend a message to all clients updating a keycards details to current values.
///
- /// The keycard to resync.
- public static void ResyncKeycardPickup(KeycardPickup keycard)
+ /// The keycard to resync.
+ public static void ResyncKeycardPickup(CustomKeycardPickup customKeycard)
{
- if (KeycardDetailSynchronizer.Database.Remove(keycard.Serial))
+ if (KeycardDetailSynchronizer.Database.Remove(customKeycard.Serial))
{
- KeycardDetailSynchronizer.ServerProcessPickup((InventorySystem.Items.Keycards.KeycardPickup)keycard.Base);
+ KeycardDetailSynchronizer.ServerProcessPickup(customKeycard.Base);
}
}
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycardItem.cs
similarity index 51%
rename from EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
rename to EXILED/Exiled.API/Features/Items/Keycards/CustomKeycardItem.cs
index 74e6a63329..89907eb59b 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycardItem.cs
@@ -1,5 +1,5 @@
// -----------------------------------------------------------------------
-//
+//
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
//
@@ -7,13 +7,15 @@
namespace Exiled.API.Features.Items.Keycards
{
+ using System;
using System.Collections.Generic;
- using System.Linq;
using Exiled.API.Enums;
using Exiled.API.Extensions;
+ using Exiled.API.Features.Pools;
using Exiled.API.Interfaces.Keycards;
using Interactables.Interobjects.DoorUtils;
+ using InventorySystem;
using InventorySystem.Items;
using InventorySystem.Items.Keycards;
using UnityEngine;
@@ -21,31 +23,26 @@ namespace Exiled.API.Features.Items.Keycards
///
/// A base class for all keycard items.
///
- public abstract class CustomKeycard : Keycard
+ public abstract class CustomKeycardItem : Keycard
{
- private CustomItemNameDetail itemNameDetail;
- private bool itemNameSet;
-
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
/// The to encapsulate.
- internal CustomKeycard(KeycardItem itemBase)
+ internal CustomKeycardItem(KeycardItem itemBase)
: base(itemBase)
{
Base = itemBase;
if (!DataDict.ContainsKey(Serial))
DataDict[Serial] = new KeycardData();
-
- Resync();
}
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
/// The of the item to create.
- internal CustomKeycard(ItemType type)
+ internal CustomKeycardItem(ItemType type)
: this((KeycardItem)Server.Host.Inventory.CreateItemInstance(new(type, 0), false))
{
}
@@ -88,9 +85,9 @@ public KeycardLevels KeycardLevels
///
/// Gets or sets the color of this keycard's permissions.
///
- public Color32? PermissionsColor
+ public Color PermissionsColor
{
- get => DataDict[Serial].PermissionsColor;
+ get => DataDict[Serial].PermissionsColor ?? new Color32(0, 0, 0, 0);
set
{
@@ -105,26 +102,11 @@ public Color32? PermissionsColor
///
public string ItemName
{
- get
- {
- if (!itemNameSet)
- {
- itemNameDetail = GetDetail();
- itemNameSet = true;
- }
-
- return itemNameDetail.Name;
- }
+ get => DataDict[Serial].ItemName;
set
{
- if (!itemNameSet)
- {
- itemNameDetail = GetDetail();
- itemNameSet = true;
- }
-
- itemNameDetail.Name = value;
+ DataDict[Serial].ItemName = value;
Resync();
}
@@ -133,9 +115,9 @@ public string ItemName
///
/// Gets or sets the color of this keycard.
///
- public Color32? Color
+ public Color Color
{
- get => DataDict[Serial].Color;
+ get => DataDict[Serial].Color ?? new Color32(0, 0, 0, 0);
set
{
@@ -150,6 +132,92 @@ public Color32? Color
///
internal static Dictionary DataDict { get; } = new();
+ ///
+ /// Gets an array of ItemTypes of each keycard.
+ ///
+ internal static ItemType[] AllKeycards { get; } =
+ {
+ ItemType.KeycardJanitor, ItemType.KeycardScientist, ItemType.KeycardResearchCoordinator, ItemType.KeycardContainmentEngineer, ItemType.KeycardZoneManager, ItemType.KeycardFacilityManager, ItemType.KeycardGuard, ItemType.KeycardMTFPrivate, ItemType.KeycardMTFOperative, ItemType.KeycardMTFCaptain, ItemType.KeycardChaosInsurgency, ItemType.KeycardO5,
+ };
+
+ ///
+ /// Gets an array of ItemTypes of each Site02 keycard.
+ ///
+ internal static ItemType[] AllSite02 { get; } = { ItemType.KeycardJanitor, ItemType.KeycardScientist, ItemType.KeycardResearchCoordinator, ItemType.KeycardContainmentEngineer };
+
+ ///
+ /// Gets an array of ItemTypes of each Management keycard.
+ ///
+ internal static ItemType[] AllManagement { get; } = { ItemType.KeycardZoneManager, ItemType.KeycardFacilityManager };
+
+ ///
+ /// Gets an array of ItemTypes of each MetalCase keycard.
+ ///
+ internal static ItemType[] AllMetalCase { get; } = { ItemType.KeycardGuard };
+
+ ///
+ /// Gets an array of ItemTypes of each TaskForce keycard.
+ ///
+ internal static ItemType[] AllTaskForce { get; } = { ItemType.KeycardMTFPrivate, ItemType.KeycardMTFOperative, ItemType.KeycardMTFCaptain };
+
+ ///
+ /// Finds a for a keycard by checking if keycard properties match.
+ ///
+ /// /// Whether to use design to check keycards.
+ /// Whether to use permissions to check keycards.
+ /// Whether to use colors to check keycards.
+ /// If 1 match is found, returns the matched value. Otherwise, returns ..
+ /// Unoptimized for now, but shouldn't be too bad.
+ public ItemType FindMatch(bool matchDesign, bool matchPerms, bool matchColors)
+ {
+ List matches = ListPool.Pool.Get();
+
+ ItemType[] toIterate = Type switch
+ {
+ _ when matchDesign => AllKeycards,
+ ItemType.KeycardCustomSite02 => AllSite02,
+ ItemType.KeycardCustomManagement => AllManagement,
+ ItemType.KeycardCustomMetalCase => AllMetalCase,
+ ItemType.KeycardCustomTaskForce => AllTaskForce,
+ _ => throw new ArgumentOutOfRangeException(nameof(Type), Type.ToString()),
+ };
+
+ ILabelKeycard label1 = this as ILabelKeycard;
+ foreach (ItemType type in toIterate)
+ {
+ KeycardItem keycard = type.GetTemplate();
+
+ foreach (DetailBase detail in keycard.Details)
+ {
+ if (detail is PredefinedPermsDetail permsDetail)
+ {
+ if (matchPerms && permsDetail.Levels.Permissions != KeycardLevels.Permissions)
+ goto cont;
+ }
+
+ if (label1 is not null && detail is TranslatedLabelDetail label2)
+ {
+ if (matchColors && label1.LabelColor != label2._textColor)
+ goto cont;
+ }
+ }
+
+ goto add;
+
+ cont:
+ continue;
+
+ add:
+ matches.Add(type);
+ }
+
+ ItemType value = matches.Count is not 1 ? ItemType.None : matches[0];
+
+ ListPool.Pool.Return(matches);
+
+ return value;
+ }
+
///
/// Resyncs all properties of the keycard.
/// Gets called by all setters by default.
@@ -161,12 +229,12 @@ public void Resync()
CustomPermsDetail._customColor = PermissionsColor;
CustomItemNameDetail._customText = ItemName;
- CustomTintDetail._customColor = Color.GetValueOrDefault();
+ CustomTintDetail._customColor = Color;
if (this is ILabelKeycard label)
{
CustomLabelDetail._customText = label.Label;
- CustomLabelDetail._customColor = label.LabelColor.GetValueOrDefault();
+ CustomLabelDetail._customColor = label.LabelColor;
}
if (this is INameTagKeycard holder)
@@ -181,17 +249,6 @@ public void Resync()
MirrorExtensions.ResyncKeycardItem(this);
}
- ///
- /// Gets a specific detail from a .
- ///
- /// The Type of SyncedDetail.
- /// The first detail of the desired type. null if not found.
- public T GetDetail()
- where T : DetailBase
- {
- return (T)Base.Details.First(detail => detail is T);
- }
-
///
/// Returns the Keycard in a human readable format.
///
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/KeycardData.cs b/EXILED/Exiled.API/Features/Items/Keycards/KeycardData.cs
index e9da214c38..ac7ba6aaf2 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/KeycardData.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/KeycardData.cs
@@ -19,6 +19,11 @@ public class KeycardData
///
public Color32? PermissionsColor { get; set; }
+ ///
+ /// Gets or sets the item name of this .
+ ///
+ public string ItemName { get; set; }
+
///
/// Gets or sets the color of this .
///
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs
index 972627b5db..77b339e106 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs
@@ -19,7 +19,7 @@ namespace Exiled.API.Features.Items.Keycards
///
/// Represents the Management Custom Keycard.
///
- public class ManagementKeycard : CustomKeycard, ILabelKeycard
+ public class ManagementKeycard : CustomKeycardItem, ILabelKeycard
{
///
/// Initializes a new instance of the class.
@@ -52,9 +52,9 @@ public string Label
}
///
- public Color32? LabelColor
+ public Color LabelColor
{
- get => DataDict[Serial].LabelColor;
+ get => DataDict[Serial].LabelColor ?? new Color32(0, 0, 0, 0);
set
{
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs
index fa6400579a..712ae6eee7 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs
@@ -19,7 +19,7 @@ namespace Exiled.API.Features.Items.Keycards
///
/// Represents the Metal Custom Keycard.
///
- public class MetalKeycard : CustomKeycard, INameTagKeycard, ILabelKeycard, IWearKeycard, ISerialNumberKeycard
+ public class MetalKeycard : CustomKeycardItem, INameTagKeycard, ILabelKeycard, IWearKeycard, ISerialNumberKeycard
{
///
/// Initializes a new instance of the class.
@@ -64,10 +64,9 @@ public string Label
}
///
- public Color32? LabelColor
+ public Color LabelColor
{
- get => DataDict[Serial].LabelColor;
-
+ get => DataDict[Serial].LabelColor ?? new Color32(0, 0, 0, 0);
set
{
DataDict[Serial].LabelColor = value;
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
index aa63ab4d09..b2f5ae5aeb 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
@@ -19,7 +19,7 @@ namespace Exiled.API.Features.Items.Keycards
///
/// Represents the Site-02 Custom Keycard.
///
- public class Site02Keycard : CustomKeycard, INameTagKeycard, ILabelKeycard, IWearKeycard
+ public class Site02Keycard : CustomKeycardItem, INameTagKeycard, ILabelKeycard, IWearKeycard
{
///
/// Initializes a new instance of the class.
@@ -64,9 +64,9 @@ public string Label
}
///
- public Color32? LabelColor
+ public Color LabelColor
{
- get => DataDict[Serial].LabelColor;
+ get => DataDict[Serial].LabelColor ?? new Color32(0, 0, 0, 0);
set
{
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs
index 00b6f18fcf..86347ad962 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs
@@ -19,7 +19,7 @@ namespace Exiled.API.Features.Items.Keycards
///
/// Represents the Task Force Custom Keycard.
///
- public class TaskForceKeycard : CustomKeycard, INameTagKeycard, ISerialNumberKeycard, IRankKeycard
+ public class TaskForceKeycard : CustomKeycardItem, INameTagKeycard, ISerialNumberKeycard, IRankKeycard
{
///
/// Initializes a new instance of the class.
diff --git a/EXILED/Exiled.API/Features/Map.cs b/EXILED/Exiled.API/Features/Map.cs
index b019c65b7d..fd1110e338 100644
--- a/EXILED/Exiled.API/Features/Map.cs
+++ b/EXILED/Exiled.API/Features/Map.cs
@@ -418,7 +418,7 @@ internal static void ClearCache()
Firearm.BaseCodesValue.Clear();
Firearm.AvailableAttachmentsValue.Clear();
- CustomKeycard.DataDict.Clear();
+ CustomKeycardItem.DataDict.Clear();
#pragma warning disable CS0618
Scp559.CakeToWrapper.Clear();
diff --git a/EXILED/Exiled.API/Features/Pickups/KeycardPickup.cs b/EXILED/Exiled.API/Features/Pickups/KeycardPickup.cs
index e7e29ff13e..87f0a799a2 100644
--- a/EXILED/Exiled.API/Features/Pickups/KeycardPickup.cs
+++ b/EXILED/Exiled.API/Features/Pickups/KeycardPickup.cs
@@ -29,6 +29,10 @@ internal KeycardPickup(BaseKeycard pickupBase)
: base(pickupBase)
{
Base = pickupBase;
+ if (Base is null)
+ {
+ Log.Info(GetType());
+ }
}
///
@@ -42,9 +46,9 @@ internal KeycardPickup(ItemType type)
}
///
- /// Gets the of the keycard.
+ /// Gets or sets the of the keycard.
///
- public KeycardPermissions Permissions { get; private set; }
+ public virtual KeycardPermissions Permissions { get; set; }
///
/// Gets the that this class is encapsulating.
diff --git a/EXILED/Exiled.API/Features/Pickups/Keycards/CustomKeycardPickup.cs b/EXILED/Exiled.API/Features/Pickups/Keycards/CustomKeycardPickup.cs
new file mode 100644
index 0000000000..e3796c15fa
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Pickups/Keycards/CustomKeycardPickup.cs
@@ -0,0 +1,236 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Pickups.Keycards
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+
+ using Exiled.API.Enums;
+ using Exiled.API.Extensions;
+ using Exiled.API.Features.Items.Keycards;
+ using Exiled.API.Features.Pools;
+ using Exiled.API.Interfaces.Keycards;
+ using Interactables.Interobjects.DoorUtils;
+ using InventorySystem;
+ using InventorySystem.Items;
+ using InventorySystem.Items.Keycards;
+ using InventorySystem.Items.Pickups;
+ using UnityEngine;
+
+ ///
+ /// A base class for all keycard pickups.
+ ///
+ public abstract class CustomKeycardPickup : Pickups.KeycardPickup
+ {
+ private static readonly ItemType[] AllKeycards = { ItemType.KeycardJanitor, ItemType.KeycardScientist, ItemType.KeycardResearchCoordinator, ItemType.KeycardZoneManager };
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The to encapsulate.
+ internal CustomKeycardPickup(KeycardPickup pickupBase)
+ : base(pickupBase)
+ {
+ if (!CustomKeycardItem.DataDict.ContainsKey(Serial))
+ CustomKeycardItem.DataDict[Serial] = new KeycardData();
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The of the pickup to create.
+ internal CustomKeycardPickup(ItemType type)
+ : base(type)
+ {
+ }
+
+ ///
+ /// Gets or sets the permissions this keycard has.
+ ///
+ public override KeycardPermissions Permissions
+ {
+ get => CustomPermsDetail.CustomPermissions.TryGetValue(Serial, out DoorPermissionFlags flags) ? (KeycardPermissions)flags : KeycardPermissions.None;
+
+ set
+ {
+ CustomPermsDetail.CustomPermissions[Serial] = (DoorPermissionFlags)value;
+
+ Resync();
+ }
+ }
+
+ ///
+ /// Gets or sets the permissions this keycard has.
+ ///
+ public KeycardLevels KeycardLevels
+ {
+ get => new((DoorPermissionFlags)Permissions);
+
+ set
+ {
+ CustomPermsDetail.CustomPermissions[Serial] = value.Permissions;
+
+ Resync();
+ }
+ }
+
+ ///
+ /// Gets or sets the color of this keycard's permissions.
+ ///
+ public Color PermissionsColor
+ {
+ get => CustomKeycardItem.DataDict[Serial].PermissionsColor ?? new Color32(0, 0, 0, 0);
+
+ set
+ {
+ CustomKeycardItem.DataDict[Serial].PermissionsColor = value;
+
+ Resync();
+ }
+ }
+
+ ///
+ /// Gets or sets the name of this keycard within the inventory.
+ ///
+ public string ItemName
+ {
+ get => CustomKeycardItem.DataDict[Serial].ItemName;
+
+ set
+ {
+ CustomKeycardItem.DataDict[Serial].ItemName = value;
+
+ Resync();
+ }
+ }
+
+ ///
+ /// Gets or sets the color of this keycard.
+ ///
+ public Color Color
+ {
+ get => CustomKeycardItem.DataDict[Serial].Color ?? new Color32(0, 0, 0, 0);
+
+ set
+ {
+ CustomKeycardItem.DataDict[Serial].Color = value;
+
+ Resync();
+ }
+ }
+
+ ///
+ /// Finds a for a keycard by checking if keycard properties match.
+ ///
+ /// /// Whether to use design to check keycards.
+ /// Whether to use permissions to check keycards.
+ /// Whether to use colors to check keycards.
+ /// If 1 match is found, returns the matched value. Otherwise, returns ..
+ /// Unoptimized for now, but shouldn't be too bad.
+ public ItemType FindMatch(bool matchDesign, bool matchPerms, bool matchColors)
+ {
+ List matches = ListPool.Pool.Get();
+
+ ItemType[] toIterate = Type switch
+ {
+ _ when matchDesign => AllKeycards,
+ ItemType.KeycardCustomSite02 => CustomKeycardItem.AllSite02,
+ ItemType.KeycardCustomManagement => CustomKeycardItem.AllManagement,
+ ItemType.KeycardCustomMetalCase => CustomKeycardItem.AllMetalCase,
+ ItemType.KeycardCustomTaskForce => CustomKeycardItem.AllTaskForce,
+ _ => throw new ArgumentOutOfRangeException(nameof(Type), Type.ToString()),
+ };
+
+ ILabelKeycard label1 = this as ILabelKeycard;
+ foreach (ItemType type in toIterate)
+ {
+ KeycardItem keycard = type.GetTemplate();
+
+ foreach (DetailBase detail in keycard.Details)
+ {
+ if (detail is PredefinedPermsDetail permsDetail)
+ {
+ if (matchPerms && permsDetail.Levels.Permissions != KeycardLevels.Permissions)
+ goto cont;
+ }
+
+ if (label1 is not null && detail is TranslatedLabelDetail label2)
+ {
+ if (matchColors && label1.LabelColor != label2._textColor)
+ goto cont;
+ }
+ }
+
+ goto add;
+
+ cont:
+ continue;
+
+ add:
+ matches.Add(type);
+ }
+
+ ItemType value = matches.Count is not 1 ? ItemType.None : matches[0];
+
+ ListPool.Pool.Return(matches);
+
+ return value;
+ }
+
+ ///
+ /// Resyncs all properties of the keycard.
+ /// Gets called by all setters by default.
+ ///
+ public void Resync()
+ {
+ // we loveeeeeeeeeeeee NW static fields trusttttttttttttttt I'm not mad at allllllllllll
+ CustomPermsDetail._customLevels = KeycardLevels;
+ CustomPermsDetail._customColor = PermissionsColor;
+
+ CustomItemNameDetail._customText = ItemName;
+ CustomTintDetail._customColor = Color;
+
+ if (this is ILabelKeycard label)
+ {
+ CustomLabelDetail._customText = label.Label;
+ CustomLabelDetail._customColor = label.LabelColor;
+ }
+
+ if (this is INameTagKeycard holder)
+ NametagDetail._customNametag = holder.NameTag;
+
+ if (this is IWearKeycard wear)
+ CustomWearDetail._customWearLevel = wear.Wear;
+
+ if (this is ISerialNumberKeycard serial)
+ CustomSerialNumberDetail._customVal = serial.SerialNumber;
+
+ // can happen if a dev does the big dumb
+ if (Base is null)
+ {
+ Log.Error("Base of CustomKeycardPickup was null! See StackTrace to fix problem.");
+ Log.Info(GetType());
+ Log.Info(new StackTrace());
+ }
+
+ MirrorExtensions.ResyncKeycardPickup(this);
+ }
+
+ ///
+ /// Returns the Keycard in a human readable format.
+ ///
+ /// A string containing Keycard-related data.
+ public override string ToString() => $"{Type} ={ItemName}= ({Serial}) [{Weight}] *{Scale}* |{Permissions}|";
+
+ ///
+ protected override void InitializeProperties(ItemBase itemBase)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Pickups/Keycards/KeycardPickup.cs b/EXILED/Exiled.API/Features/Pickups/Keycards/KeycardPickup.cs
deleted file mode 100644
index ac968a4346..0000000000
--- a/EXILED/Exiled.API/Features/Pickups/Keycards/KeycardPickup.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-// -----------------------------------------------------------------------
-//
-// Copyright (c) ExMod Team. All rights reserved.
-// Licensed under the CC BY-SA 3.0 license.
-//
-// -----------------------------------------------------------------------
-
-namespace Exiled.API.Features.Pickups.Keycards
-{
- using Exiled.API.Extensions;
-
- using InventorySystem.Items.Pickups;
-
- ///
- /// A base class for all keycard pickups.
- ///
- public class KeycardPickup : Pickup
- {
- ///
- /// Initializes a new instance of the class.
- ///
- /// The base class.
- public KeycardPickup(ItemPickupBase pickupBase)
- : base(pickupBase)
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The of the pickup.
- internal KeycardPickup(ItemType type)
- : base(type)
- {
- }
-
- ///
- /// Resyncs all properties of the keycard.
- /// Gets called by all setters by default.
- ///
- public void Resync()
- {
- MirrorExtensions.ResyncKeycardPickup(this);
- }
- }
-}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Pickups/Keycards/ManagementKeycardPickup.cs b/EXILED/Exiled.API/Features/Pickups/Keycards/ManagementKeycardPickup.cs
new file mode 100644
index 0000000000..382f759604
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Pickups/Keycards/ManagementKeycardPickup.cs
@@ -0,0 +1,86 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Pickups.Keycards
+{
+ using Exiled.API.Features.Items.Keycards;
+ using Exiled.API.Interfaces.Keycards;
+ using Interactables.Interobjects.DoorUtils;
+ using InventorySystem.Items.Keycards;
+ using InventorySystem.Items.Pickups;
+ using UnityEngine;
+
+ ///
+ /// Represents the Management Custom Keycard.
+ ///
+ public class ManagementKeycardPickup : CustomKeycardPickup, ILabelKeycard
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The to encapsulate.
+ internal ManagementKeycardPickup(KeycardPickup pickupBase)
+ : base(pickupBase)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The of the pickup to create.
+ internal ManagementKeycardPickup(ItemType type)
+ : base(type)
+ {
+ }
+
+ ///
+ public string Label
+ {
+ get => CustomKeycardItem.DataDict[Serial].Label;
+
+ set
+ {
+ CustomKeycardItem.DataDict[Serial].Label = value;
+ Resync();
+ }
+ }
+
+ ///
+ public Color LabelColor
+ {
+ get => CustomKeycardItem.DataDict[Serial].LabelColor ?? new Color32(0, 0, 0, 0);
+
+ set
+ {
+ CustomKeycardItem.DataDict[Serial].LabelColor = value;
+ Resync();
+ }
+ }
+
+ ///
+ /// Creates a .
+ ///
+ /// The permissions of the keycard.
+ /// The color of the permissions of the keycard.
+ /// The inventory name of the keycard.
+ /// The color of the keycard.
+ /// The label on the keycard.
+ /// The color of the label on the keycard.
+ /// The new .
+ public static ManagementKeycardPickup Create(KeycardLevels keycardLevels, Color permissionsColor, string itemName, Color color, string label, Color labelColor)
+ {
+ ManagementKeycardPickup keycardPickup = Create(ItemType.KeycardCustomManagement);
+ keycardPickup.KeycardLevels = keycardLevels;
+ keycardPickup.PermissionsColor = permissionsColor;
+ keycardPickup.ItemName = itemName;
+ keycardPickup.Color = color;
+ keycardPickup.Label = label;
+ keycardPickup.LabelColor = labelColor;
+ return keycardPickup;
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Pickups/Keycards/MetalKeycardPickup.cs b/EXILED/Exiled.API/Features/Pickups/Keycards/MetalKeycardPickup.cs
new file mode 100644
index 0000000000..131c95cb43
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Pickups/Keycards/MetalKeycardPickup.cs
@@ -0,0 +1,131 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Pickups.Keycards
+{
+ using Exiled.API.Features.Items.Keycards;
+ using Exiled.API.Interfaces.Keycards;
+ using Interactables.Interobjects.DoorUtils;
+ using InventorySystem.Items.Keycards;
+ using InventorySystem.Items.Pickups;
+ using UnityEngine;
+
+ ///
+ /// Represents the Metal Custom Keycard.
+ ///
+ public class MetalKeycardPickup : CustomKeycardPickup, INameTagKeycard, ILabelKeycard, IWearKeycard, ISerialNumberKeycard
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The to encapsulate.
+ internal MetalKeycardPickup(KeycardPickup pickupBase)
+ : base(pickupBase)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The of the pickup to create.
+ internal MetalKeycardPickup(ItemType type)
+ : base(type)
+ {
+ }
+
+ ///
+ public string NameTag
+ {
+ get => CustomKeycardItem.DataDict[Serial].NameTag;
+
+ set
+ {
+ CustomKeycardItem.DataDict[Serial].NameTag = value;
+ Resync();
+ }
+ }
+
+ ///
+ public string Label
+ {
+ get => CustomKeycardItem.DataDict[Serial].Label;
+
+ set
+ {
+ CustomKeycardItem.DataDict[Serial].Label = value;
+ Resync();
+ }
+ }
+
+ ///
+ public Color LabelColor
+ {
+ get => CustomKeycardItem.DataDict[Serial].LabelColor ?? new Color32(0, 0, 0, 0);
+
+ set
+ {
+ CustomKeycardItem.DataDict[Serial].LabelColor = value;
+ Resync();
+ }
+ }
+
+ ///
+ /// Capped from 0-5 for Site-02 keycards, returns 255 if no wear level is found.
+ public byte Wear
+ {
+ get => CustomKeycardItem.DataDict[Serial].Wear;
+
+ set
+ {
+ CustomKeycardItem.DataDict[Serial].Wear = value;
+
+ Resync();
+ }
+ }
+
+ ///
+ public string SerialNumber
+ {
+ get => CustomKeycardItem.DataDict[Serial].SerialNumber;
+
+ set
+ {
+ CustomKeycardItem.DataDict[Serial].SerialNumber = value;
+
+ Resync();
+ }
+ }
+
+ ///
+ /// Creates a .
+ ///
+ /// The permissions of the keycard.
+ /// The color of the permissions of the keycard.
+ /// The inventory name of the keycard.
+ /// The color of the keycard.
+ /// The name of the owner of the keycard.
+ /// The label on the keycard.
+ /// The color of the label on the keycard.
+ /// How worn the keycard looks (capped from 0-5).
+ /// The serial number of the keycard (numbers only, 12 max).
+ /// The new .
+ public static MetalKeycardPickup Create(KeycardLevels keycardLevels, Color permissionsColor, string itemName, Color color, string nameTag, string label, Color labelColor, byte wear, string serialNumber)
+ {
+ MetalKeycardPickup keycardPickup = Create(ItemType.KeycardCustomManagement);
+ keycardPickup.KeycardLevels = keycardLevels;
+ keycardPickup.PermissionsColor = permissionsColor;
+ keycardPickup.ItemName = itemName;
+ keycardPickup.Color = color;
+ keycardPickup.NameTag = nameTag;
+ keycardPickup.Label = label;
+ keycardPickup.LabelColor = labelColor;
+ keycardPickup.Wear = wear;
+ keycardPickup.SerialNumber = serialNumber;
+ return keycardPickup;
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Pickups/Keycards/Site02KeycardPickup.cs b/EXILED/Exiled.API/Features/Pickups/Keycards/Site02KeycardPickup.cs
new file mode 100644
index 0000000000..29e7254819
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Pickups/Keycards/Site02KeycardPickup.cs
@@ -0,0 +1,116 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Pickups.Keycards
+{
+ using Exiled.API.Features.Items.Keycards;
+ using Exiled.API.Interfaces.Keycards;
+ using Interactables.Interobjects.DoorUtils;
+ using InventorySystem.Items.Keycards;
+ using InventorySystem.Items.Pickups;
+ using UnityEngine;
+
+ ///
+ /// Represents the Site-02 Custom Keycard.
+ ///
+ public class Site02KeycardPickup : CustomKeycardPickup, INameTagKeycard, ILabelKeycard, IWearKeycard
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The to encapsulate.
+ internal Site02KeycardPickup(KeycardPickup pickupBase)
+ : base(pickupBase)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The of the pickup to create.
+ internal Site02KeycardPickup(ItemType type)
+ : base(type)
+ {
+ }
+
+ ///
+ public string NameTag
+ {
+ get => CustomKeycardItem.DataDict[Serial].NameTag;
+
+ set
+ {
+ CustomKeycardItem.DataDict[Serial].NameTag = value;
+ Resync();
+ }
+ }
+
+ ///
+ public string Label
+ {
+ get => CustomKeycardItem.DataDict[Serial].Label;
+
+ set
+ {
+ CustomKeycardItem.DataDict[Serial].Label = value;
+ Resync();
+ }
+ }
+
+ ///
+ public Color LabelColor
+ {
+ get => CustomKeycardItem.DataDict[Serial].LabelColor ?? new Color32(0, 0, 0, 0);
+
+ set
+ {
+ CustomKeycardItem.DataDict[Serial].LabelColor = value;
+ Resync();
+ }
+ }
+
+ ///
+ /// Capped from 0-4 for Site-02 keycards, returns 255 if no wear level is found.
+ public byte Wear
+ {
+ get => CustomKeycardItem.DataDict[Serial].Wear;
+
+ set
+ {
+ CustomKeycardItem.DataDict[Serial].Wear = value;
+
+ Resync();
+ }
+ }
+
+ ///
+ /// Creates a .
+ ///
+ /// The permissions of the keycard.
+ /// The color of the permissions of the keycard.
+ /// The inventory name of the keycard.
+ /// The color of the keycard.
+ /// The name of the owner of the keycard.
+ /// The label on the keycard.
+ /// The color of the label on the keycard.
+ /// How worn the keycard looks (capped from 0-5).
+ /// The new .
+ public static Site02KeycardPickup Create(KeycardLevels keycardLevels, Color permissionsColor, string itemName, Color color, string nameTag, string label, Color labelColor, byte wear)
+ {
+ Site02KeycardPickup keycardPickup = Create(ItemType.KeycardCustomManagement);
+ keycardPickup.KeycardLevels = keycardLevels;
+ keycardPickup.PermissionsColor = permissionsColor;
+ keycardPickup.ItemName = itemName;
+ keycardPickup.Color = color;
+ keycardPickup.NameTag = nameTag;
+ keycardPickup.Label = label;
+ keycardPickup.LabelColor = labelColor;
+ keycardPickup.Wear = wear;
+ return keycardPickup;
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Pickups/Keycards/TaskForceKeycardPickup.cs b/EXILED/Exiled.API/Features/Pickups/Keycards/TaskForceKeycardPickup.cs
new file mode 100644
index 0000000000..194ecc4d57
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Pickups/Keycards/TaskForceKeycardPickup.cs
@@ -0,0 +1,102 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Pickups.Keycards
+{
+ using Exiled.API.Features.Items.Keycards;
+ using Exiled.API.Interfaces.Keycards;
+ using Interactables.Interobjects.DoorUtils;
+ using InventorySystem.Items.Keycards;
+ using InventorySystem.Items.Pickups;
+ using UnityEngine;
+
+ ///
+ /// Represents the Task Force Custom Keycard.
+ ///
+ public class TaskForceKeycardPickup : CustomKeycardPickup, INameTagKeycard, ISerialNumberKeycard, IRankKeycard
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The to encapsulate.
+ internal TaskForceKeycardPickup(KeycardPickup pickupBase)
+ : base(pickupBase)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The of the pickup to create.
+ internal TaskForceKeycardPickup(ItemType type)
+ : base(type)
+ {
+ }
+
+ ///
+ public string NameTag
+ {
+ get => CustomKeycardItem.DataDict[Serial].NameTag;
+
+ set
+ {
+ CustomKeycardItem.DataDict[Serial].NameTag = value;
+ Resync();
+ }
+ }
+
+ ///
+ public string SerialNumber
+ {
+ get => CustomKeycardItem.DataDict[Serial].SerialNumber;
+
+ set
+ {
+ CustomKeycardItem.DataDict[Serial].SerialNumber = value;
+
+ Resync();
+ }
+ }
+
+ ///
+ public byte Rank
+ {
+ get => CustomKeycardItem.DataDict[Serial].Rank;
+
+ set
+ {
+ CustomKeycardItem.DataDict[Serial].Rank = value;
+
+ Resync();
+ }
+ }
+
+ ///
+ /// Creates a .
+ ///
+ /// The permissions of the keycard.
+ /// The color of the permissions of the keycard.
+ /// The inventory name of the keycard.
+ /// The color of the keycard.
+ /// The name of the owner of the keycard.
+ /// The serial number of the keycard (numbers only, 12 max).
+ /// The rank of the keycard (capped from 0-3).
+ /// The new .
+ public static TaskForceKeycardPickup Create(KeycardLevels keycardLevels, Color permissionsColor, string itemName, Color color, string nameTag, string serialNumber, byte rank)
+ {
+ TaskForceKeycardPickup keycardPickup = Create(ItemType.KeycardCustomManagement);
+ keycardPickup.KeycardLevels = keycardLevels;
+ keycardPickup.PermissionsColor = permissionsColor;
+ keycardPickup.ItemName = itemName;
+ keycardPickup.Color = color;
+ keycardPickup.NameTag = nameTag;
+ keycardPickup.SerialNumber = serialNumber;
+ keycardPickup.Rank = rank;
+ return keycardPickup;
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Pickups/Pickup.cs b/EXILED/Exiled.API/Features/Pickups/Pickup.cs
index a610217fb3..0d81c9f8e9 100644
--- a/EXILED/Exiled.API/Features/Pickups/Pickup.cs
+++ b/EXILED/Exiled.API/Features/Pickups/Pickup.cs
@@ -13,6 +13,7 @@ namespace Exiled.API.Features.Pickups
using Exiled.API.Extensions;
using Exiled.API.Features.Core;
+ using Exiled.API.Features.Pickups.Keycards;
using Exiled.API.Features.Pickups.Projectiles;
using Exiled.API.Interfaces;
@@ -317,7 +318,14 @@ public static Pickup Get(ItemPickupBase pickupBase)
_ => new GrenadePickup(timeGrenade),
},
BaseFirearmPickup firearmPickup => new FirearmPickup(firearmPickup),
- BaseKeycardPickup keycardPickup => new KeycardPickup(keycardPickup),
+ BaseKeycardPickup keycardPickup => keycardPickup.ItemId.TypeId switch
+ {
+ ItemType.KeycardCustomTaskForce => new TaskForceKeycardPickup(keycardPickup),
+ ItemType.KeycardCustomSite02 => new Site02KeycardPickup(keycardPickup),
+ ItemType.KeycardCustomManagement => new ManagementKeycardPickup(keycardPickup),
+ ItemType.KeycardCustomMetalCase => new MetalKeycardPickup(keycardPickup),
+ _ => new KeycardPickup(keycardPickup),
+ },
BaseBodyArmorPickup bodyArmorPickup => new BodyArmorPickup(bodyArmorPickup),
BaseScp330Pickup scp330Pickup => new Scp330Pickup(scp330Pickup),
BaseScp1576Pickup scp1576Pickup => new Scp1576Pickup(scp1576Pickup),
@@ -487,7 +495,14 @@ public static IEnumerable Get(IEnumerable gameObjects)
_ => new GrenadePickup(type),
},
BaseFirearmPickup => new FirearmPickup(type),
- BaseKeycardPickup => new KeycardPickup(type),
+ BaseKeycardPickup keycardPickup => type switch
+ {
+ ItemType.KeycardCustomTaskForce => new TaskForceKeycardPickup(type),
+ ItemType.KeycardCustomSite02 => new Site02KeycardPickup(type),
+ ItemType.KeycardCustomManagement => new ManagementKeycardPickup(type),
+ ItemType.KeycardCustomMetalCase => new MetalKeycardPickup(type),
+ _ => new KeycardPickup(keycardPickup),
+ },
BaseBodyArmorPickup => new BodyArmorPickup(type),
BaseScp330Pickup => new Scp330Pickup(),
BaseScp1576Pickup => new Scp1576Pickup(),
diff --git a/EXILED/Exiled.API/Interfaces/Keycards/ILabelKeycard.cs b/EXILED/Exiled.API/Interfaces/Keycards/ILabelKeycard.cs
index f2a78f6d6a..d724f997ea 100644
--- a/EXILED/Exiled.API/Interfaces/Keycards/ILabelKeycard.cs
+++ b/EXILED/Exiled.API/Interfaces/Keycards/ILabelKeycard.cs
@@ -11,18 +11,18 @@ namespace Exiled.API.Interfaces.Keycards
using UnityEngine;
///
- /// An interface for 's with the property.
+ /// An interface for 's with the property.
///
public interface ILabelKeycard
{
///
- /// Gets or sets the label of this .
+ /// Gets or sets the label of this .
///
public string Label { get; set; }
///
- /// Gets or sets the of this .
+ /// Gets or sets the of this .
///
- public Color32? LabelColor { get; set; }
+ public Color LabelColor { get; set; }
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Interfaces/Keycards/INameTagKeycard.cs b/EXILED/Exiled.API/Interfaces/Keycards/INameTagKeycard.cs
index 4b035fdb28..02d85ddd53 100644
--- a/EXILED/Exiled.API/Interfaces/Keycards/INameTagKeycard.cs
+++ b/EXILED/Exiled.API/Interfaces/Keycards/INameTagKeycard.cs
@@ -10,12 +10,12 @@ namespace Exiled.API.Interfaces.Keycards
using Exiled.API.Features.Items.Keycards;
///
- /// An interface for 's with the property.
+ /// An interface for 's with the property.
///
public interface INameTagKeycard
{
///
- /// Gets or sets the name of the owner of this .
+ /// Gets or sets the name of the owner of this .
///
public string NameTag { get; set; }
}
diff --git a/EXILED/Exiled.API/Interfaces/Keycards/IRankKeycard.cs b/EXILED/Exiled.API/Interfaces/Keycards/IRankKeycard.cs
index 0f8e7e74e1..f0bb1d389a 100644
--- a/EXILED/Exiled.API/Interfaces/Keycards/IRankKeycard.cs
+++ b/EXILED/Exiled.API/Interfaces/Keycards/IRankKeycard.cs
@@ -10,12 +10,12 @@ namespace Exiled.API.Interfaces.Keycards
using Exiled.API.Features.Items.Keycards;
///
- /// An interface for 's with the property.
+ /// An interface for 's with the property.
///
public interface IRankKeycard
{
///
- /// Gets or sets the rank of this .
+ /// Gets or sets the rank of this .
///
/// Capped from 0-3, returns 255 if no value was found.
public byte Rank { get; set; }
diff --git a/EXILED/Exiled.API/Interfaces/Keycards/ISerialNumberKeycard.cs b/EXILED/Exiled.API/Interfaces/Keycards/ISerialNumberKeycard.cs
index 1bf0a1ba90..c3e4c799b2 100644
--- a/EXILED/Exiled.API/Interfaces/Keycards/ISerialNumberKeycard.cs
+++ b/EXILED/Exiled.API/Interfaces/Keycards/ISerialNumberKeycard.cs
@@ -10,12 +10,12 @@ namespace Exiled.API.Interfaces.Keycards
using Exiled.API.Features.Items.Keycards;
///
- /// An interface for 's with the property.
+ /// An interface for 's with the property.
///
public interface ISerialNumberKeycard
{
///
- /// Gets or sets the serial number of this .
+ /// Gets or sets the serial number of this .
///
/// Can only hold 12 numbers. Non-numerical chars will be replaced with "-".
public string SerialNumber { get; set; }
diff --git a/EXILED/Exiled.API/Interfaces/Keycards/IWearKeycard.cs b/EXILED/Exiled.API/Interfaces/Keycards/IWearKeycard.cs
index 8a29572a5a..02f4584b38 100644
--- a/EXILED/Exiled.API/Interfaces/Keycards/IWearKeycard.cs
+++ b/EXILED/Exiled.API/Interfaces/Keycards/IWearKeycard.cs
@@ -10,12 +10,12 @@ namespace Exiled.API.Interfaces.Keycards
using Exiled.API.Features.Items.Keycards;
///
- /// An interface for 's with the property.
+ /// An interface for 's with the property.
///
public interface IWearKeycard
{
///
- /// Gets or sets the wear on this .
+ /// Gets or sets the wear on this .
///
public byte Wear { get; set; }
}
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomItemNameDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomItemNameDetailData.cs
new file mode 100644
index 0000000000..f423c93c4c
--- /dev/null
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomItemNameDetailData.cs
@@ -0,0 +1,34 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.Patches.Generic.KeycardDetails
+{
+ using Exiled.API.Features.Items.Keycards;
+ using HarmonyLib;
+ using InventorySystem.Items.Keycards;
+
+ ///
+ /// Patch for storing item name from custom keycards.
+ ///
+ [HarmonyPatch(typeof(CustomItemNameDetail))]
+ public class CustomItemNameDetailData
+ {
+ [HarmonyPatch(nameof(CustomItemNameDetail.WriteNewItem))]
+ [HarmonyPrefix]
+ private static void PrefixItem(KeycardItem item)
+ {
+ CustomKeycardItem.DataDict[item.ItemSerial].ItemName = CustomItemNameDetail._customText;
+ }
+
+ [HarmonyPatch(nameof(CustomItemNameDetail.WriteNewPickup))]
+ [HarmonyPrefix]
+ private static void PrefixPickup(KeycardPickup pickup)
+ {
+ CustomKeycardItem.DataDict[pickup.ItemId.SerialNumber].ItemName = CustomItemNameDetail._customText;
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomLabelDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomLabelDetailData.cs
index 92aef090a1..adb01c9222 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomLabelDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomLabelDetailData.cs
@@ -21,16 +21,16 @@ public class CustomLabelDetailData
[HarmonyPrefix]
private static void Prefix(KeycardItem item)
{
- CustomKeycard.DataDict[item.ItemSerial].Label = CustomLabelDetail._customText;
- CustomKeycard.DataDict[item.ItemSerial].LabelColor = CustomLabelDetail._customColor;
+ CustomKeycardItem.DataDict[item.ItemSerial].Label = CustomLabelDetail._customText;
+ CustomKeycardItem.DataDict[item.ItemSerial].LabelColor = CustomLabelDetail._customColor;
}
[HarmonyPatch(nameof(CustomLabelDetail.WriteNewPickup))]
[HarmonyPrefix]
private static void Prefix(KeycardPickup pickup)
{
- CustomKeycard.DataDict[pickup.ItemId.SerialNumber].Label = CustomLabelDetail._customText;
- CustomKeycard.DataDict[pickup.ItemId.SerialNumber].LabelColor = CustomLabelDetail._customColor;
+ CustomKeycardItem.DataDict[pickup.ItemId.SerialNumber].Label = CustomLabelDetail._customText;
+ CustomKeycardItem.DataDict[pickup.ItemId.SerialNumber].LabelColor = CustomLabelDetail._customColor;
}
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomPermsDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomPermsDetailData.cs
index 4237bc1933..f3ff48e595 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomPermsDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomPermsDetailData.cs
@@ -20,7 +20,7 @@ public class CustomPermsDetailData
{
private static void Prefix(IIdentifierProvider target)
{
- CustomKeycard.DataDict[target.ItemId.SerialNumber].PermissionsColor = CustomPermsDetail._customColor;
+ CustomKeycardItem.DataDict[target.ItemId.SerialNumber].PermissionsColor = CustomPermsDetail._customColor;
}
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomRankDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomRankDetailData.cs
index 9808e33216..96b8e803fa 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomRankDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomRankDetailData.cs
@@ -24,14 +24,14 @@ public class CustomRankDetailData
[HarmonyPrefix]
private static void PrefixItem(CustomRankDetail __instance, KeycardItem item)
{
- CustomKeycard.DataDict[item.ItemSerial].Rank = (byte)(Mathf.Abs(CustomRankDetail._index) % __instance._options.Length);
+ CustomKeycardItem.DataDict[item.ItemSerial].Rank = (byte)(Mathf.Abs(CustomRankDetail._index) % __instance._options.Length);
}
[HarmonyPatch(nameof(CustomRankDetail.WriteNewPickup))]
[HarmonyPrefix]
private static void PrefixPickup(CustomRankDetail __instance, KeycardPickup pickup)
{
- CustomKeycard.DataDict[pickup.ItemId.SerialNumber].Rank = (byte)(Mathf.Abs(CustomRankDetail._index) % __instance._options.Length);
+ CustomKeycardItem.DataDict[pickup.ItemId.SerialNumber].Rank = (byte)(Mathf.Abs(CustomRankDetail._index) % __instance._options.Length);
}
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomSerialNumberDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomSerialNumberDetailData.cs
index c48d55ab38..cd47216897 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomSerialNumberDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomSerialNumberDetailData.cs
@@ -21,14 +21,14 @@ public class CustomSerialNumberDetailData
[HarmonyPrefix]
private static void PrefixItem(KeycardItem item)
{
- CustomKeycard.DataDict[item.ItemSerial].SerialNumber = CustomSerialNumberDetail._customVal;
+ CustomKeycardItem.DataDict[item.ItemSerial].SerialNumber = CustomSerialNumberDetail._customVal;
}
[HarmonyPatch(nameof(CustomSerialNumberDetail.WriteNewPickup))]
[HarmonyPrefix]
private static void PrefixPickup(KeycardPickup pickup)
{
- CustomKeycard.DataDict[pickup.ItemId.SerialNumber].SerialNumber = CustomSerialNumberDetail._customVal;
+ CustomKeycardItem.DataDict[pickup.ItemId.SerialNumber].SerialNumber = CustomSerialNumberDetail._customVal;
}
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomTintDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomTintDetailData.cs
index f26bb73e4a..81c779ff0f 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomTintDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomTintDetailData.cs
@@ -21,14 +21,14 @@ public class CustomTintDetailData
[HarmonyPrefix]
private static void PrefixItem(KeycardItem item)
{
- CustomKeycard.DataDict[item.ItemSerial].Color = CustomTintDetail._customColor;
+ CustomKeycardItem.DataDict[item.ItemSerial].Color = CustomTintDetail._customColor;
}
[HarmonyPatch(nameof(CustomTintDetail.WriteNewPickup))]
[HarmonyPrefix]
private static void PrefixPickup(KeycardPickup pickup)
{
- CustomKeycard.DataDict[pickup.ItemId.SerialNumber].Color = CustomTintDetail._customColor;
+ CustomKeycardItem.DataDict[pickup.ItemId.SerialNumber].Color = CustomTintDetail._customColor;
}
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomWearDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomWearDetailData.cs
index 3ed41c9900..ae8025047a 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomWearDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomWearDetailData.cs
@@ -21,14 +21,14 @@ public class CustomWearDetailData
[HarmonyPrefix]
private static void PrefixItem(KeycardItem item)
{
- CustomKeycard.DataDict[item.ItemSerial].Wear = CustomWearDetail._customWearLevel;
+ CustomKeycardItem.DataDict[item.ItemSerial].Wear = CustomWearDetail._customWearLevel;
}
[HarmonyPatch(nameof(CustomWearDetail.WriteNewPickup))]
[HarmonyPrefix]
private static void PrefixPickup(KeycardPickup pickup)
{
- CustomKeycard.DataDict[pickup.ItemId.SerialNumber].Wear = CustomWearDetail._customWearLevel;
+ CustomKeycardItem.DataDict[pickup.ItemId.SerialNumber].Wear = CustomWearDetail._customWearLevel;
}
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/NameTagDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/NameTagDetailData.cs
index 5d2f33a956..482c996c3c 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/NameTagDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/NameTagDetailData.cs
@@ -22,7 +22,7 @@ public class NameTagDetailData
[HarmonyPrefix]
private static void PrefixItem(KeycardItem item)
{
- if (CustomKeycard.DataDict.TryGetValue(item.ItemSerial, out KeycardData data))
+ if (CustomKeycardItem.DataDict.TryGetValue(item.ItemSerial, out KeycardData data))
data.NameTag = NametagDetail._customNametag;
}
@@ -30,7 +30,7 @@ private static void PrefixItem(KeycardItem item)
[HarmonyPrefix]
private static void PrefixPickup(KeycardPickup pickup)
{
- if (CustomKeycard.DataDict.TryGetValue(pickup.ItemId.SerialNumber, out KeycardData data))
+ if (CustomKeycardItem.DataDict.TryGetValue(pickup.ItemId.SerialNumber, out KeycardData data))
data.NameTag = NametagDetail._customNametag;
}
}
From bf152055ddd627ef0dcfaf31dd8adcf674818f7e Mon Sep 17 00:00:00 2001
From: "@Someone" <45270312+Someone-193@users.noreply.github.com>
Date: Wed, 27 Aug 2025 20:28:50 -0400
Subject: [PATCH 22/38] Add stability
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
basically all done I think 😭
cant wait for NW to change custom keycards to sync vars next update and make all my work obsolete
---
.../KeycardDetails/CustomItemNameDetailData.cs | 8 ++++++--
.../Generic/KeycardDetails/CustomLabelDetailData.cs | 12 ++++++++----
.../Generic/KeycardDetails/CustomPermsDetailData.cs | 4 +++-
.../Generic/KeycardDetails/CustomRankDetailData.cs | 8 ++++++--
.../KeycardDetails/CustomSerialNumberDetailData.cs | 8 ++++++--
.../Generic/KeycardDetails/CustomTintDetailData.cs | 8 ++++++--
.../Generic/KeycardDetails/CustomWearDetailData.cs | 8 ++++++--
7 files changed, 41 insertions(+), 15 deletions(-)
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomItemNameDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomItemNameDetailData.cs
index f423c93c4c..896084a08a 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomItemNameDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomItemNameDetailData.cs
@@ -21,14 +21,18 @@ public class CustomItemNameDetailData
[HarmonyPrefix]
private static void PrefixItem(KeycardItem item)
{
- CustomKeycardItem.DataDict[item.ItemSerial].ItemName = CustomItemNameDetail._customText;
+ if (!CustomKeycardItem.DataDict.TryGetValue(item.ItemSerial, out KeycardData data))
+ CustomKeycardItem.DataDict[item.ItemSerial] = data = new KeycardData();
+ data.ItemName = CustomItemNameDetail._customText;
}
[HarmonyPatch(nameof(CustomItemNameDetail.WriteNewPickup))]
[HarmonyPrefix]
private static void PrefixPickup(KeycardPickup pickup)
{
- CustomKeycardItem.DataDict[pickup.ItemId.SerialNumber].ItemName = CustomItemNameDetail._customText;
+ if (!CustomKeycardItem.DataDict.TryGetValue(pickup.ItemId.SerialNumber, out KeycardData data))
+ CustomKeycardItem.DataDict[pickup.ItemId.SerialNumber] = data = new KeycardData();
+ data.ItemName = CustomItemNameDetail._customText;
}
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomLabelDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomLabelDetailData.cs
index adb01c9222..574ce2b78d 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomLabelDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomLabelDetailData.cs
@@ -21,16 +21,20 @@ public class CustomLabelDetailData
[HarmonyPrefix]
private static void Prefix(KeycardItem item)
{
- CustomKeycardItem.DataDict[item.ItemSerial].Label = CustomLabelDetail._customText;
- CustomKeycardItem.DataDict[item.ItemSerial].LabelColor = CustomLabelDetail._customColor;
+ if (!CustomKeycardItem.DataDict.TryGetValue(item.ItemSerial, out KeycardData data))
+ CustomKeycardItem.DataDict[item.ItemSerial] = data = new KeycardData();
+ data.Label = CustomLabelDetail._customText;
+ data.LabelColor = CustomLabelDetail._customColor;
}
[HarmonyPatch(nameof(CustomLabelDetail.WriteNewPickup))]
[HarmonyPrefix]
private static void Prefix(KeycardPickup pickup)
{
- CustomKeycardItem.DataDict[pickup.ItemId.SerialNumber].Label = CustomLabelDetail._customText;
- CustomKeycardItem.DataDict[pickup.ItemId.SerialNumber].LabelColor = CustomLabelDetail._customColor;
+ if (!CustomKeycardItem.DataDict.TryGetValue(pickup.ItemId.SerialNumber, out KeycardData data))
+ CustomKeycardItem.DataDict[pickup.ItemId.SerialNumber] = data = new KeycardData();
+ data.Label = CustomLabelDetail._customText;
+ data.LabelColor = CustomLabelDetail._customColor;
}
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomPermsDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomPermsDetailData.cs
index f3ff48e595..d3a1c7cc84 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomPermsDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomPermsDetailData.cs
@@ -20,7 +20,9 @@ public class CustomPermsDetailData
{
private static void Prefix(IIdentifierProvider target)
{
- CustomKeycardItem.DataDict[target.ItemId.SerialNumber].PermissionsColor = CustomPermsDetail._customColor;
+ if (!CustomKeycardItem.DataDict.TryGetValue(target.ItemId.SerialNumber, out KeycardData data))
+ CustomKeycardItem.DataDict[target.ItemId.SerialNumber] = data = new KeycardData();
+ data.PermissionsColor = CustomPermsDetail._customColor;
}
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomRankDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomRankDetailData.cs
index 96b8e803fa..6b5889f193 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomRankDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomRankDetailData.cs
@@ -24,14 +24,18 @@ public class CustomRankDetailData
[HarmonyPrefix]
private static void PrefixItem(CustomRankDetail __instance, KeycardItem item)
{
- CustomKeycardItem.DataDict[item.ItemSerial].Rank = (byte)(Mathf.Abs(CustomRankDetail._index) % __instance._options.Length);
+ if (!CustomKeycardItem.DataDict.TryGetValue(item.ItemSerial, out KeycardData data))
+ CustomKeycardItem.DataDict[item.ItemSerial] = data = new KeycardData();
+ data.Rank = (byte)(Mathf.Abs(CustomRankDetail._index) % __instance._options.Length);
}
[HarmonyPatch(nameof(CustomRankDetail.WriteNewPickup))]
[HarmonyPrefix]
private static void PrefixPickup(CustomRankDetail __instance, KeycardPickup pickup)
{
- CustomKeycardItem.DataDict[pickup.ItemId.SerialNumber].Rank = (byte)(Mathf.Abs(CustomRankDetail._index) % __instance._options.Length);
+ if (!CustomKeycardItem.DataDict.TryGetValue(pickup.ItemId.SerialNumber, out KeycardData data))
+ CustomKeycardItem.DataDict[pickup.ItemId.SerialNumber] = data = new KeycardData();
+ data.Rank = (byte)(Mathf.Abs(CustomRankDetail._index) % __instance._options.Length);
}
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomSerialNumberDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomSerialNumberDetailData.cs
index cd47216897..b846455d9c 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomSerialNumberDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomSerialNumberDetailData.cs
@@ -21,14 +21,18 @@ public class CustomSerialNumberDetailData
[HarmonyPrefix]
private static void PrefixItem(KeycardItem item)
{
- CustomKeycardItem.DataDict[item.ItemSerial].SerialNumber = CustomSerialNumberDetail._customVal;
+ if (!CustomKeycardItem.DataDict.TryGetValue(item.ItemSerial, out KeycardData data))
+ CustomKeycardItem.DataDict[item.ItemSerial] = data = new KeycardData();
+ data.SerialNumber = CustomSerialNumberDetail._customVal;
}
[HarmonyPatch(nameof(CustomSerialNumberDetail.WriteNewPickup))]
[HarmonyPrefix]
private static void PrefixPickup(KeycardPickup pickup)
{
- CustomKeycardItem.DataDict[pickup.ItemId.SerialNumber].SerialNumber = CustomSerialNumberDetail._customVal;
+ if (!CustomKeycardItem.DataDict.TryGetValue(pickup.ItemId.SerialNumber, out KeycardData data))
+ CustomKeycardItem.DataDict[pickup.ItemId.SerialNumber] = data = new KeycardData();
+ data.SerialNumber = CustomSerialNumberDetail._customVal;
}
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomTintDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomTintDetailData.cs
index 81c779ff0f..fb2bf92181 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomTintDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomTintDetailData.cs
@@ -21,14 +21,18 @@ public class CustomTintDetailData
[HarmonyPrefix]
private static void PrefixItem(KeycardItem item)
{
- CustomKeycardItem.DataDict[item.ItemSerial].Color = CustomTintDetail._customColor;
+ if (!CustomKeycardItem.DataDict.TryGetValue(item.ItemSerial, out KeycardData data))
+ CustomKeycardItem.DataDict[item.ItemSerial] = data = new KeycardData();
+ data.Color = CustomTintDetail._customColor;
}
[HarmonyPatch(nameof(CustomTintDetail.WriteNewPickup))]
[HarmonyPrefix]
private static void PrefixPickup(KeycardPickup pickup)
{
- CustomKeycardItem.DataDict[pickup.ItemId.SerialNumber].Color = CustomTintDetail._customColor;
+ if (!CustomKeycardItem.DataDict.TryGetValue(pickup.ItemId.SerialNumber, out KeycardData data))
+ CustomKeycardItem.DataDict[pickup.ItemId.SerialNumber] = data = new KeycardData();
+ data.Color = CustomTintDetail._customColor;
}
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomWearDetailData.cs b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomWearDetailData.cs
index ae8025047a..af25a81e9e 100644
--- a/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomWearDetailData.cs
+++ b/EXILED/Exiled.Events/Patches/Generic/KeycardDetails/CustomWearDetailData.cs
@@ -21,14 +21,18 @@ public class CustomWearDetailData
[HarmonyPrefix]
private static void PrefixItem(KeycardItem item)
{
- CustomKeycardItem.DataDict[item.ItemSerial].Wear = CustomWearDetail._customWearLevel;
+ if (!CustomKeycardItem.DataDict.TryGetValue(item.ItemSerial, out KeycardData data))
+ CustomKeycardItem.DataDict[item.ItemSerial] = data = new KeycardData();
+ data.Wear = CustomWearDetail._customWearLevel;
}
[HarmonyPatch(nameof(CustomWearDetail.WriteNewPickup))]
[HarmonyPrefix]
private static void PrefixPickup(KeycardPickup pickup)
{
- CustomKeycardItem.DataDict[pickup.ItemId.SerialNumber].Wear = CustomWearDetail._customWearLevel;
+ if (!CustomKeycardItem.DataDict.TryGetValue(pickup.ItemId.SerialNumber, out KeycardData data))
+ CustomKeycardItem.DataDict[pickup.ItemId.SerialNumber] = data = new KeycardData();
+ data.Wear = CustomWearDetail._customWearLevel;
}
}
}
\ No newline at end of file
From b1c6c9f40f4ab7e8c45c729643f531ee889b5c23 Mon Sep 17 00:00:00 2001
From: Yamato
Date: Thu, 28 Aug 2025 10:11:31 +0200
Subject: [PATCH 23/38] Use Color.clear instead of new Color32
---
.../Exiled.API/Features/Items/Keycards/CustomKeycardItem.cs | 4 ++--
.../Exiled.API/Features/Items/Keycards/ManagementKeycard.cs | 2 +-
EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs | 2 +-
EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs | 2 +-
.../Features/Pickups/Keycards/CustomKeycardPickup.cs | 6 +++---
.../Features/Pickups/Keycards/ManagementKeycardPickup.cs | 4 ++--
.../Features/Pickups/Keycards/MetalKeycardPickup.cs | 4 ++--
.../Features/Pickups/Keycards/Site02KeycardPickup.cs | 4 ++--
8 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycardItem.cs b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycardItem.cs
index 89907eb59b..addf51f57c 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycardItem.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycardItem.cs
@@ -87,7 +87,7 @@ public KeycardLevels KeycardLevels
///
public Color PermissionsColor
{
- get => DataDict[Serial].PermissionsColor ?? new Color32(0, 0, 0, 0);
+ get => DataDict[Serial].PermissionsColor ?? Color.clear;
set
{
@@ -117,7 +117,7 @@ public string ItemName
///
public Color Color
{
- get => DataDict[Serial].Color ?? new Color32(0, 0, 0, 0);
+ get => DataDict[Serial].Color ?? Color.clear;
set
{
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs
index 77b339e106..9b03fd5eca 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/ManagementKeycard.cs
@@ -54,7 +54,7 @@ public string Label
///
public Color LabelColor
{
- get => DataDict[Serial].LabelColor ?? new Color32(0, 0, 0, 0);
+ get => DataDict[Serial].LabelColor ?? Color.clear;
set
{
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs
index 712ae6eee7..291eb6d558 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs
@@ -66,7 +66,7 @@ public string Label
///
public Color LabelColor
{
- get => DataDict[Serial].LabelColor ?? new Color32(0, 0, 0, 0);
+ get => DataDict[Serial].LabelColor ?? Color.clear;
set
{
DataDict[Serial].LabelColor = value;
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
index b2f5ae5aeb..7b73985bae 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
@@ -66,7 +66,7 @@ public string Label
///
public Color LabelColor
{
- get => DataDict[Serial].LabelColor ?? new Color32(0, 0, 0, 0);
+ get => DataDict[Serial].LabelColor ?? Color.clear;
set
{
diff --git a/EXILED/Exiled.API/Features/Pickups/Keycards/CustomKeycardPickup.cs b/EXILED/Exiled.API/Features/Pickups/Keycards/CustomKeycardPickup.cs
index e3796c15fa..82fa98024c 100644
--- a/EXILED/Exiled.API/Features/Pickups/Keycards/CustomKeycardPickup.cs
+++ b/EXILED/Exiled.API/Features/Pickups/Keycards/CustomKeycardPickup.cs
@@ -1,4 +1,4 @@
-// -----------------------------------------------------------------------
+// -----------------------------------------------------------------------
//
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
@@ -85,7 +85,7 @@ public KeycardLevels KeycardLevels
///
public Color PermissionsColor
{
- get => CustomKeycardItem.DataDict[Serial].PermissionsColor ?? new Color32(0, 0, 0, 0);
+ get => CustomKeycardItem.DataDict[Serial].PermissionsColor ?? Color.clear;
set
{
@@ -115,7 +115,7 @@ public string ItemName
///
public Color Color
{
- get => CustomKeycardItem.DataDict[Serial].Color ?? new Color32(0, 0, 0, 0);
+ get => CustomKeycardItem.DataDict[Serial].Color ?? Color.clear;
set
{
diff --git a/EXILED/Exiled.API/Features/Pickups/Keycards/ManagementKeycardPickup.cs b/EXILED/Exiled.API/Features/Pickups/Keycards/ManagementKeycardPickup.cs
index 382f759604..9e745a6776 100644
--- a/EXILED/Exiled.API/Features/Pickups/Keycards/ManagementKeycardPickup.cs
+++ b/EXILED/Exiled.API/Features/Pickups/Keycards/ManagementKeycardPickup.cs
@@ -1,4 +1,4 @@
-// -----------------------------------------------------------------------
+// -----------------------------------------------------------------------
//
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
@@ -52,7 +52,7 @@ public string Label
///
public Color LabelColor
{
- get => CustomKeycardItem.DataDict[Serial].LabelColor ?? new Color32(0, 0, 0, 0);
+ get => CustomKeycardItem.DataDict[Serial].LabelColor ?? Color.clear;
set
{
diff --git a/EXILED/Exiled.API/Features/Pickups/Keycards/MetalKeycardPickup.cs b/EXILED/Exiled.API/Features/Pickups/Keycards/MetalKeycardPickup.cs
index 131c95cb43..9367e933d5 100644
--- a/EXILED/Exiled.API/Features/Pickups/Keycards/MetalKeycardPickup.cs
+++ b/EXILED/Exiled.API/Features/Pickups/Keycards/MetalKeycardPickup.cs
@@ -1,4 +1,4 @@
-// -----------------------------------------------------------------------
+// -----------------------------------------------------------------------
//
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
@@ -64,7 +64,7 @@ public string Label
///
public Color LabelColor
{
- get => CustomKeycardItem.DataDict[Serial].LabelColor ?? new Color32(0, 0, 0, 0);
+ get => CustomKeycardItem.DataDict[Serial].LabelColor ?? Color.clear;
set
{
diff --git a/EXILED/Exiled.API/Features/Pickups/Keycards/Site02KeycardPickup.cs b/EXILED/Exiled.API/Features/Pickups/Keycards/Site02KeycardPickup.cs
index 29e7254819..06cfac4bac 100644
--- a/EXILED/Exiled.API/Features/Pickups/Keycards/Site02KeycardPickup.cs
+++ b/EXILED/Exiled.API/Features/Pickups/Keycards/Site02KeycardPickup.cs
@@ -1,4 +1,4 @@
-// -----------------------------------------------------------------------
+// -----------------------------------------------------------------------
//
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
@@ -64,7 +64,7 @@ public string Label
///
public Color LabelColor
{
- get => CustomKeycardItem.DataDict[Serial].LabelColor ?? new Color32(0, 0, 0, 0);
+ get => CustomKeycardItem.DataDict[Serial].LabelColor ?? Color.clear;
set
{
From e837150c0f16ce4cb6e3271a4d37bf752bd72eea Mon Sep 17 00:00:00 2001
From: Yamato
Date: Thu, 28 Aug 2025 14:14:04 +0200
Subject: [PATCH 24/38] just improving code readability and fix matchDesign
---
.../Features/Items/Keycards/CustomKeycardItem.cs | 12 +++---------
.../Features/Items/Keycards/KeycardData.cs | 6 +++---
2 files changed, 6 insertions(+), 12 deletions(-)
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycardItem.cs b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycardItem.cs
index addf51f57c..ff15c5f740 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycardItem.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycardItem.cs
@@ -174,7 +174,7 @@ public ItemType FindMatch(bool matchDesign, bool matchPerms, bool matchColors)
ItemType[] toIterate = Type switch
{
- _ when matchDesign => AllKeycards,
+ _ when !matchDesign => AllKeycards,
ItemType.KeycardCustomSite02 => AllSite02,
ItemType.KeycardCustomManagement => AllManagement,
ItemType.KeycardCustomMetalCase => AllMetalCase,
@@ -192,22 +192,16 @@ public ItemType FindMatch(bool matchDesign, bool matchPerms, bool matchColors)
if (detail is PredefinedPermsDetail permsDetail)
{
if (matchPerms && permsDetail.Levels.Permissions != KeycardLevels.Permissions)
- goto cont;
+ continue;
}
if (label1 is not null && detail is TranslatedLabelDetail label2)
{
if (matchColors && label1.LabelColor != label2._textColor)
- goto cont;
+ continue;
}
}
- goto add;
-
- cont:
- continue;
-
- add:
matches.Add(type);
}
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/KeycardData.cs b/EXILED/Exiled.API/Features/Items/Keycards/KeycardData.cs
index ac7ba6aaf2..c8d60cbd2e 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/KeycardData.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/KeycardData.cs
@@ -1,4 +1,4 @@
-// -----------------------------------------------------------------------
+// -----------------------------------------------------------------------
//
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
@@ -47,7 +47,7 @@ public class KeycardData
///
/// Gets or sets the wear of this .
///
- public byte Wear { get; set; } = 255;
+ public byte Wear { get; set; } = byte.MaxValue;
///
/// Gets or sets the serial number of this .
@@ -57,6 +57,6 @@ public class KeycardData
///
/// Gets or sets the rank of this .
///
- public byte Rank { get; set; } = 255;
+ public byte Rank { get; set; } = byte.MaxValue;
}
}
\ No newline at end of file
From 13a2956f0028412c90b55caf1dc2c29eeeb75b99 Mon Sep 17 00:00:00 2001
From: Yamato
Date: Fri, 29 Aug 2025 13:39:32 +0200
Subject: [PATCH 25/38] Add ChaosKeycard and SingleUseKeycard
Introduced new ChaosKeycard and SingleUseKeycard types for keycard items, updating Item.cs logic to instantiate these specific classes. Updated Keycard.cs to support owner parameter and improved type handling. Added reference to Snake.dll for ChaosKeycard functionality. Clarified documentation in CustomKeycardItem.cs.
---
EXILED/Exiled.API/Exiled.API.csproj | 1 +
EXILED/Exiled.API/Features/Items/Item.cs | 10 +--
EXILED/Exiled.API/Features/Items/Keycard.cs | 5 +-
.../Features/Items/Keycards/ChaosKeycard.cs | 54 ++++++++++++
.../Items/Keycards/CustomKeycardItem.cs | 2 +-
.../Items/Keycards/SingleUseKeycard.cs | 85 +++++++++++++++++++
6 files changed, 149 insertions(+), 8 deletions(-)
create mode 100644 EXILED/Exiled.API/Features/Items/Keycards/ChaosKeycard.cs
create mode 100644 EXILED/Exiled.API/Features/Items/Keycards/SingleUseKeycard.cs
diff --git a/EXILED/Exiled.API/Exiled.API.csproj b/EXILED/Exiled.API/Exiled.API.csproj
index 3b2040da91..84dd05ff53 100644
--- a/EXILED/Exiled.API/Exiled.API.csproj
+++ b/EXILED/Exiled.API/Exiled.API.csproj
@@ -31,6 +31,7 @@
+
diff --git a/EXILED/Exiled.API/Features/Items/Item.cs b/EXILED/Exiled.API/Features/Items/Item.cs
index f910af56c5..3082a75709 100644
--- a/EXILED/Exiled.API/Features/Items/Item.cs
+++ b/EXILED/Exiled.API/Features/Items/Item.cs
@@ -220,8 +220,8 @@ public static Item Get(ItemBase itemBase)
InventorySystem.Items.Firearms.Firearm firearm => new Firearm(firearm),
KeycardItem keycard => keycard switch
{
- ChaosKeycardItem chaosKeycardItem => new Keycard(chaosKeycardItem),
- SingleUseKeycardItem singleUseKeycardItem => new Keycard(singleUseKeycardItem),
+ ChaosKeycardItem chaosKeycardItem => new ChaosKeycard(chaosKeycardItem),
+ SingleUseKeycardItem singleUseKeycardItem => new SingleUseKeycard(singleUseKeycardItem),
_ => keycard.ItemTypeId switch
{
ItemType.KeycardCustomTaskForce => new TaskForceKeycard(keycard),
@@ -319,15 +319,15 @@ public static T Get(ushort serial)
InventorySystem.Items.Firearms.Firearm => new Firearm(type),
KeycardItem keycard => keycard switch
{
- ChaosKeycardItem => new Keycard(type),
- SingleUseKeycardItem => new Keycard(type),
+ ChaosKeycardItem => new ChaosKeycard(type),
+ SingleUseKeycardItem => new SingleUseKeycard(type),
_ => keycard.ItemTypeId switch
{
ItemType.KeycardCustomTaskForce => new TaskForceKeycard(type),
ItemType.KeycardCustomSite02 => new Site02Keycard(type),
ItemType.KeycardCustomManagement => new ManagementKeycard(type),
ItemType.KeycardCustomMetalCase => new MetalKeycard(type),
- _ => new Keycard(type),
+ _ => new Keycard(type, owner),
}
},
UsableItem usable => usable switch
diff --git a/EXILED/Exiled.API/Features/Items/Keycard.cs b/EXILED/Exiled.API/Features/Items/Keycard.cs
index 2cff5d2e4d..6e3cf91dea 100644
--- a/EXILED/Exiled.API/Features/Items/Keycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycard.cs
@@ -32,8 +32,9 @@ public Keycard(KeycardItem itemBase)
/// Initializes a new instance of the class.
///
/// The of the keycard.
- internal Keycard(ItemType type)
- : this((KeycardItem)Server.Host.Inventory.CreateItemInstance(new(type, 0), false))
+ /// The owner of the grenade. Leave for no owner.
+ internal Keycard(ItemType type, Player owner = null)
+ : this((KeycardItem)(owner ?? Server.Host).Inventory.CreateItemInstance(new(type, 0), false))
{
}
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/ChaosKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/ChaosKeycard.cs
new file mode 100644
index 0000000000..5a8329363a
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Items/Keycards/ChaosKeycard.cs
@@ -0,0 +1,54 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Items.Keycards
+{
+ using InventorySystem.Items;
+ using InventorySystem.Items.Keycards;
+ using InventorySystem.Items.Keycards.Snake;
+
+ ///
+ /// A base class for SingleUse keycard items.
+ ///
+ public class ChaosKeycard : Keycard
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The to encapsulate.
+ internal ChaosKeycard(ChaosKeycardItem itemBase)
+ : base(itemBase)
+ {
+ Base = itemBase;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The of the item to create.
+ internal ChaosKeycard(ItemType type)
+ : this((ChaosKeycardItem)Server.Host.Inventory.CreateItemInstance(new(type, 0), false))
+ {
+ }
+
+ ///
+ /// Gets the this encapsulates.
+ ///
+ public new ChaosKeycardItem Base { get; }
+
+ ///
+ /// Gets the this encapsulates.
+ ///
+ public SnakeEngine SnakeEngine => Base._localEngine;
+
+ ///
+ /// Returns the Keycard in a human readable format.
+ ///
+ /// A string containing Keycard-related data.
+ public override string ToString() => $"{Type} == ({Serial}) [{Weight}] *{Scale}* |{Permissions}|";
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycardItem.cs b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycardItem.cs
index ff15c5f740..4e6b848c81 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycardItem.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycardItem.cs
@@ -21,7 +21,7 @@ namespace Exiled.API.Features.Items.Keycards
using UnityEngine;
///
- /// A base class for all keycard items.
+ /// A base class for all custom keycard items.
///
public abstract class CustomKeycardItem : Keycard
{
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/SingleUseKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/SingleUseKeycard.cs
new file mode 100644
index 0000000000..8a7284de53
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Items/Keycards/SingleUseKeycard.cs
@@ -0,0 +1,85 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Items.Keycards
+{
+ using Exiled.API.Enums;
+ using Interactables.Interobjects.DoorUtils;
+ using InventorySystem.Items;
+ using InventorySystem.Items.Keycards;
+ using UnityEngine;
+
+ ///
+ /// A base class for SingleUse keycard items.
+ ///
+ public class SingleUseKeycard : Keycard
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The to encapsulate.
+ internal SingleUseKeycard(SingleUseKeycardItem itemBase)
+ : base(itemBase)
+ {
+ Base = itemBase;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The of the item to create.
+ internal SingleUseKeycard(ItemType type)
+ : this((SingleUseKeycardItem)Server.Host.Inventory.CreateItemInstance(new(type, 0), false))
+ {
+ }
+
+ ///
+ /// Gets the this encapsulates.
+ ///
+ public new SingleUseKeycardItem Base { get; }
+
+ ///
+ /// Gets or sets the time delay to destroy the Keycard after being used.
+ ///
+ public float TimeToDestroy
+ {
+ get => Base._timeToDestroy;
+ set => Base._timeToDestroy = value;
+ }
+
+ ///
+ public override KeycardPermissions Permissions
+ {
+ get => (KeycardPermissions)Base._singleUsePermissions;
+ set => Base._singleUsePermissions = (DoorPermissionFlags)value;
+ }
+
+ ///
+ /// Gets or sets a value indicating whether the Keycard allow the closing of Doors.
+ ///
+ public bool AllowClosingDoors
+ {
+ get => Base._allowClosingDoors;
+ set => Base._allowClosingDoors = value;
+ }
+
+ ///
+ /// Gets or sets a value indicating whether the Keycard allow the closing of Doors.
+ ///
+ public bool IsDestroyed
+ {
+ get => Base._destroyed;
+ set => Base._destroyed = value;
+ }
+
+ ///
+ /// Returns the Keycard in a human readable format.
+ ///
+ /// A string containing Keycard-related data.
+ public override string ToString() => $"{Type} ={AllowClosingDoors}= ({Serial}) [{Weight}] *{Scale}* |{Permissions}|";
+ }
+}
\ No newline at end of file
From f0c30c9c1c7d517853f2d3fa9164977b256d9b20 Mon Sep 17 00:00:00 2001
From: Yamato
Date: Fri, 29 Aug 2025 13:55:07 +0200
Subject: [PATCH 26/38] PartiallyRevert previous commit
---
.../Features/Items/Keycards/CustomKeycardItem.cs | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycardItem.cs b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycardItem.cs
index 4e6b848c81..004085b922 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycardItem.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycardItem.cs
@@ -192,16 +192,22 @@ public ItemType FindMatch(bool matchDesign, bool matchPerms, bool matchColors)
if (detail is PredefinedPermsDetail permsDetail)
{
if (matchPerms && permsDetail.Levels.Permissions != KeycardLevels.Permissions)
- continue;
+ goto cont;
}
if (label1 is not null && detail is TranslatedLabelDetail label2)
{
if (matchColors && label1.LabelColor != label2._textColor)
- continue;
+ goto cont;
}
}
+ goto add;
+
+ cont:
+ continue;
+
+ add:
matches.Add(type);
}
From 79581735c0ae53e0e7e50eb4e7d52511ae15568b Mon Sep 17 00:00:00 2001
From: Yamato
Date: Fri, 29 Aug 2025 14:35:47 +0200
Subject: [PATCH 27/38] Add the Pickup Class for SingleUse And Chaos Keycard
---
.../Pickups/Keycards/ChaosKeycardPickup.cs | 55 ++++++++++++
.../Keycards/SingleUseKeycardPickup.cs | 83 +++++++++++++++++++
2 files changed, 138 insertions(+)
create mode 100644 EXILED/Exiled.API/Features/Pickups/Keycards/ChaosKeycardPickup.cs
create mode 100644 EXILED/Exiled.API/Features/Pickups/Keycards/SingleUseKeycardPickup.cs
diff --git a/EXILED/Exiled.API/Features/Pickups/Keycards/ChaosKeycardPickup.cs b/EXILED/Exiled.API/Features/Pickups/Keycards/ChaosKeycardPickup.cs
new file mode 100644
index 0000000000..a671f11243
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Pickups/Keycards/ChaosKeycardPickup.cs
@@ -0,0 +1,55 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Pickups.Keycards
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+
+ using Exiled.API.Enums;
+ using Exiled.API.Extensions;
+ using Exiled.API.Features.Items.Keycards;
+ using Exiled.API.Features.Pools;
+ using Exiled.API.Interfaces.Keycards;
+ using Interactables.Interobjects.DoorUtils;
+ using InventorySystem;
+ using InventorySystem.Items;
+ using InventorySystem.Items.Keycards;
+ using InventorySystem.Items.Pickups;
+ using UnityEngine;
+
+ ///
+ /// A base class for all keycard pickups.
+ ///
+ public abstract class ChaosKeycardPickup : Pickups.KeycardPickup
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The to encapsulate.
+ internal ChaosKeycardPickup(KeycardPickup pickupBase)
+ : base(pickupBase)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The of the pickup to create.
+ internal ChaosKeycardPickup(ItemType type)
+ : base(type)
+ {
+ }
+
+ ///
+ /// Returns the Keycard in a human readable format.
+ ///
+ /// A string containing Keycard-related data.
+ public override string ToString() => $"{Type} == ({Serial}) [{Weight}] *{Scale}* |{Permissions}|";
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Pickups/Keycards/SingleUseKeycardPickup.cs b/EXILED/Exiled.API/Features/Pickups/Keycards/SingleUseKeycardPickup.cs
new file mode 100644
index 0000000000..5b0cfc21b3
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Pickups/Keycards/SingleUseKeycardPickup.cs
@@ -0,0 +1,83 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Pickups.Keycards
+{
+ using Exiled.API.Enums;
+ using Exiled.API.Features.Items;
+ using Exiled.API.Features.Items.Keycards;
+ using InventorySystem.Items;
+ using InventorySystem.Items.Keycards;
+ using InventorySystem.Items.Pickups;
+
+ ///
+ /// A base class for all keycard pickups.
+ ///
+ public abstract class SingleUseKeycardPickup : Pickups.KeycardPickup
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The to encapsulate.
+ internal SingleUseKeycardPickup(KeycardPickup pickupBase)
+ : base(pickupBase)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The of the pickup to create.
+ internal SingleUseKeycardPickup(ItemType type)
+ : base(type)
+ {
+ }
+
+ ///
+ /// Gets or sets the time delay to destroy the Keycard after being used.
+ ///
+ public float TimeToDestroy { get; set; }
+
+ ///
+ public override KeycardPermissions Permissions { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the Keycard allow the closing of Doors.
+ ///
+ public bool AllowClosingDoors { get; set; }
+
+ ///
+ /// Returns the Keycard in a human readable format.
+ ///
+ /// A string containing Keycard-related data.
+ public override string ToString() => $"{Type} ={AllowClosingDoors}= ({Serial}) [{Weight}] *{Scale}* |{Permissions}|";
+
+ ///
+ internal override void ReadItemInfo(Item item)
+ {
+ base.ReadItemInfo(item);
+ if (item is SingleUseKeycard singleUseKeycardItem)
+ {
+ TimeToDestroy = singleUseKeycardItem.TimeToDestroy;
+ Permissions = singleUseKeycardItem.Permissions;
+ AllowClosingDoors = singleUseKeycardItem.AllowClosingDoors;
+ }
+ }
+
+ ///
+ protected override void InitializeProperties(ItemBase itemBase)
+ {
+ base.InitializeProperties(itemBase);
+ if (itemBase is SingleUseKeycardItem singleUseKeycardItem)
+ {
+ TimeToDestroy = singleUseKeycardItem._timeToDestroy;
+ Permissions = (KeycardPermissions)singleUseKeycardItem._singleUsePermissions;
+ AllowClosingDoors = singleUseKeycardItem._allowClosingDoors;
+ }
+ }
+ }
+}
\ No newline at end of file
From 2ffc80fe2300e94e2c86162858a7a2dcc27cea04 Mon Sep 17 00:00:00 2001
From: "@Someone" <45270312+Someone-193@users.noreply.github.com>
Date: Sat, 30 Aug 2025 00:07:53 -0400
Subject: [PATCH 28/38] minor docs change
---
EXILED/Exiled.API/Features/Items/Keycards/ChaosKeycard.cs | 2 +-
EXILED/Exiled.API/Features/Items/Keycards/SingleUseKeycard.cs | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/ChaosKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/ChaosKeycard.cs
index 5a8329363a..8d8bdad39d 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/ChaosKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/ChaosKeycard.cs
@@ -12,7 +12,7 @@ namespace Exiled.API.Features.Items.Keycards
using InventorySystem.Items.Keycards.Snake;
///
- /// A base class for SingleUse keycard items.
+ /// A base class for chaos keycard items.
///
public class ChaosKeycard : Keycard
{
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/SingleUseKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/SingleUseKeycard.cs
index 8a7284de53..3e7637e667 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/SingleUseKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/SingleUseKeycard.cs
@@ -68,7 +68,7 @@ public bool AllowClosingDoors
}
///
- /// Gets or sets a value indicating whether the Keycard allow the closing of Doors.
+ /// Gets or sets a value indicating whether the Keycard is destroyed.
///
public bool IsDestroyed
{
From 091dd44c0f6ae86a576c981a879b24338e992aef Mon Sep 17 00:00:00 2001
From: Yamato
Date: Sat, 30 Aug 2025 13:02:04 +0200
Subject: [PATCH 29/38] Add SingleUseKeycard pickup info reading and
ChaosKeycard SnakeEngine property
Implemented ReadPickupInfoBefore in SingleUseKeycard to populate properties from its pickup. Added a SnakeEngine property to ChaosKeycardPickup for accessing the underlying engine instance.
---
.../Items/Keycards/SingleUseKeycard.cs | 14 +++++++++++++-
.../Pickups/Keycards/ChaosKeycardPickup.cs | 19 ++++++-------------
2 files changed, 19 insertions(+), 14 deletions(-)
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/SingleUseKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/SingleUseKeycard.cs
index 8a7284de53..9584b1729c 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/SingleUseKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/SingleUseKeycard.cs
@@ -8,10 +8,11 @@
namespace Exiled.API.Features.Items.Keycards
{
using Exiled.API.Enums;
+ using Exiled.API.Features.Pickups;
+ using Exiled.API.Features.Pickups.Keycards;
using Interactables.Interobjects.DoorUtils;
using InventorySystem.Items;
using InventorySystem.Items.Keycards;
- using UnityEngine;
///
/// A base class for SingleUse keycard items.
@@ -81,5 +82,16 @@ public bool IsDestroyed
///
/// A string containing Keycard-related data.
public override string ToString() => $"{Type} ={AllowClosingDoors}= ({Serial}) [{Weight}] *{Scale}* |{Permissions}|";
+
+ ///
+ internal override void ReadPickupInfoBefore(Pickup pickup)
+ {
+ if (pickup is SingleUseKeycardPickup singleUseKeycard)
+ {
+ TimeToDestroy = singleUseKeycard.TimeToDestroy;
+ Permissions = singleUseKeycard.Permissions;
+ AllowClosingDoors = singleUseKeycard.AllowClosingDoors;
+ }
+ }
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Pickups/Keycards/ChaosKeycardPickup.cs b/EXILED/Exiled.API/Features/Pickups/Keycards/ChaosKeycardPickup.cs
index a671f11243..4a8e3bc14b 100644
--- a/EXILED/Exiled.API/Features/Pickups/Keycards/ChaosKeycardPickup.cs
+++ b/EXILED/Exiled.API/Features/Pickups/Keycards/ChaosKeycardPickup.cs
@@ -7,21 +7,9 @@
namespace Exiled.API.Features.Pickups.Keycards
{
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
-
- using Exiled.API.Enums;
- using Exiled.API.Extensions;
- using Exiled.API.Features.Items.Keycards;
- using Exiled.API.Features.Pools;
- using Exiled.API.Interfaces.Keycards;
- using Interactables.Interobjects.DoorUtils;
- using InventorySystem;
- using InventorySystem.Items;
using InventorySystem.Items.Keycards;
+ using InventorySystem.Items.Keycards.Snake;
using InventorySystem.Items.Pickups;
- using UnityEngine;
///
/// A base class for all keycard pickups.
@@ -46,6 +34,11 @@ internal ChaosKeycardPickup(ItemType type)
{
}
+ ///
+ /// Gets the this encapsulates.
+ ///
+ public SnakeEngine SnakeEngine => ChaosKeycardItem.GetEngineForSerial(Serial);
+
///
/// Returns the Keycard in a human readable format.
///
From 4b09399b5e37be5ea767809eb077c0ec02b64b5e Mon Sep 17 00:00:00 2001
From: Yamato
Date: Mon, 1 Sep 2025 21:14:06 +0200
Subject: [PATCH 30/38] Fix Keycard::Create using wrong ItemType
---
.../Features/Pickups/Keycards/MetalKeycardPickup.cs | 2 +-
.../Features/Pickups/Keycards/Site02KeycardPickup.cs | 2 +-
.../Features/Pickups/Keycards/TaskForceKeycardPickup.cs | 4 ++--
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/EXILED/Exiled.API/Features/Pickups/Keycards/MetalKeycardPickup.cs b/EXILED/Exiled.API/Features/Pickups/Keycards/MetalKeycardPickup.cs
index 9367e933d5..0e2f02b8aa 100644
--- a/EXILED/Exiled.API/Features/Pickups/Keycards/MetalKeycardPickup.cs
+++ b/EXILED/Exiled.API/Features/Pickups/Keycards/MetalKeycardPickup.cs
@@ -115,7 +115,7 @@ public string SerialNumber
/// The new .
public static MetalKeycardPickup Create(KeycardLevels keycardLevels, Color permissionsColor, string itemName, Color color, string nameTag, string label, Color labelColor, byte wear, string serialNumber)
{
- MetalKeycardPickup keycardPickup = Create(ItemType.KeycardCustomManagement);
+ MetalKeycardPickup keycardPickup = Create(ItemType.KeycardCustomMetalCase);
keycardPickup.KeycardLevels = keycardLevels;
keycardPickup.PermissionsColor = permissionsColor;
keycardPickup.ItemName = itemName;
diff --git a/EXILED/Exiled.API/Features/Pickups/Keycards/Site02KeycardPickup.cs b/EXILED/Exiled.API/Features/Pickups/Keycards/Site02KeycardPickup.cs
index 06cfac4bac..f21aa8cf40 100644
--- a/EXILED/Exiled.API/Features/Pickups/Keycards/Site02KeycardPickup.cs
+++ b/EXILED/Exiled.API/Features/Pickups/Keycards/Site02KeycardPickup.cs
@@ -101,7 +101,7 @@ public byte Wear
/// The new .
public static Site02KeycardPickup Create(KeycardLevels keycardLevels, Color permissionsColor, string itemName, Color color, string nameTag, string label, Color labelColor, byte wear)
{
- Site02KeycardPickup keycardPickup = Create(ItemType.KeycardCustomManagement);
+ Site02KeycardPickup keycardPickup = Create(ItemType.KeycardCustomSite02);
keycardPickup.KeycardLevels = keycardLevels;
keycardPickup.PermissionsColor = permissionsColor;
keycardPickup.ItemName = itemName;
diff --git a/EXILED/Exiled.API/Features/Pickups/Keycards/TaskForceKeycardPickup.cs b/EXILED/Exiled.API/Features/Pickups/Keycards/TaskForceKeycardPickup.cs
index 194ecc4d57..5cbfca9970 100644
--- a/EXILED/Exiled.API/Features/Pickups/Keycards/TaskForceKeycardPickup.cs
+++ b/EXILED/Exiled.API/Features/Pickups/Keycards/TaskForceKeycardPickup.cs
@@ -1,4 +1,4 @@
-// -----------------------------------------------------------------------
+// -----------------------------------------------------------------------
//
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
@@ -88,7 +88,7 @@ public byte Rank
/// The new .
public static TaskForceKeycardPickup Create(KeycardLevels keycardLevels, Color permissionsColor, string itemName, Color color, string nameTag, string serialNumber, byte rank)
{
- TaskForceKeycardPickup keycardPickup = Create(ItemType.KeycardCustomManagement);
+ TaskForceKeycardPickup keycardPickup = Create(ItemType.KeycardCustomTaskForce);
keycardPickup.KeycardLevels = keycardLevels;
keycardPickup.PermissionsColor = permissionsColor;
keycardPickup.ItemName = itemName;
From 6ca8399ab3aeda764115c594bdb5e4fbcdd3f4e3 Mon Sep 17 00:00:00 2001
From: "@Someone" <45270312+Someone-193@users.noreply.github.com>
Date: Mon, 1 Sep 2025 17:41:24 -0400
Subject: [PATCH 31/38] tinybrain moment :trollface:
---
.../Features/Pickups/Keycards/ChaosKeycardPickup.cs | 2 +-
.../Features/Pickups/Keycards/SingleUseKeycardPickup.cs | 2 +-
EXILED/Exiled.API/Features/Pickups/Pickup.cs | 4 ++++
3 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/EXILED/Exiled.API/Features/Pickups/Keycards/ChaosKeycardPickup.cs b/EXILED/Exiled.API/Features/Pickups/Keycards/ChaosKeycardPickup.cs
index 4a8e3bc14b..09374e3bc5 100644
--- a/EXILED/Exiled.API/Features/Pickups/Keycards/ChaosKeycardPickup.cs
+++ b/EXILED/Exiled.API/Features/Pickups/Keycards/ChaosKeycardPickup.cs
@@ -14,7 +14,7 @@ namespace Exiled.API.Features.Pickups.Keycards
///
/// A base class for all keycard pickups.
///
- public abstract class ChaosKeycardPickup : Pickups.KeycardPickup
+ public class ChaosKeycardPickup : Pickups.KeycardPickup
{
///
/// Initializes a new instance of the class.
diff --git a/EXILED/Exiled.API/Features/Pickups/Keycards/SingleUseKeycardPickup.cs b/EXILED/Exiled.API/Features/Pickups/Keycards/SingleUseKeycardPickup.cs
index 5b0cfc21b3..63f5bf322a 100644
--- a/EXILED/Exiled.API/Features/Pickups/Keycards/SingleUseKeycardPickup.cs
+++ b/EXILED/Exiled.API/Features/Pickups/Keycards/SingleUseKeycardPickup.cs
@@ -17,7 +17,7 @@ namespace Exiled.API.Features.Pickups.Keycards
///
/// A base class for all keycard pickups.
///
- public abstract class SingleUseKeycardPickup : Pickups.KeycardPickup
+ public class SingleUseKeycardPickup : Pickups.KeycardPickup
{
///
/// Initializes a new instance of the class.
diff --git a/EXILED/Exiled.API/Features/Pickups/Pickup.cs b/EXILED/Exiled.API/Features/Pickups/Pickup.cs
index 0d81c9f8e9..24368655f0 100644
--- a/EXILED/Exiled.API/Features/Pickups/Pickup.cs
+++ b/EXILED/Exiled.API/Features/Pickups/Pickup.cs
@@ -324,6 +324,8 @@ public static Pickup Get(ItemPickupBase pickupBase)
ItemType.KeycardCustomSite02 => new Site02KeycardPickup(keycardPickup),
ItemType.KeycardCustomManagement => new ManagementKeycardPickup(keycardPickup),
ItemType.KeycardCustomMetalCase => new MetalKeycardPickup(keycardPickup),
+ ItemType.SurfaceAccessPass => new SingleUseKeycardPickup(keycardPickup),
+ ItemType.KeycardChaosInsurgency => new ChaosKeycardPickup(keycardPickup),
_ => new KeycardPickup(keycardPickup),
},
BaseBodyArmorPickup bodyArmorPickup => new BodyArmorPickup(bodyArmorPickup),
@@ -501,6 +503,8 @@ public static IEnumerable Get(IEnumerable gameObjects)
ItemType.KeycardCustomSite02 => new Site02KeycardPickup(type),
ItemType.KeycardCustomManagement => new ManagementKeycardPickup(type),
ItemType.KeycardCustomMetalCase => new MetalKeycardPickup(type),
+ ItemType.SurfaceAccessPass => new SingleUseKeycardPickup(type),
+ ItemType.KeycardChaosInsurgency => new ChaosKeycardPickup(type),
_ => new KeycardPickup(keycardPickup),
},
BaseBodyArmorPickup => new BodyArmorPickup(type),
From e30dc9dd23125127550000eff3e2ade741f2e0e0 Mon Sep 17 00:00:00 2001
From: "@Someone" <45270312+Someone-193@users.noreply.github.com>
Date: Mon, 1 Sep 2025 18:33:07 -0400
Subject: [PATCH 32/38] Add Uses property for SingleUseKeycard and implement
functionality
---
.../Items/Keycards/SingleUseKeycard.cs | 29 +++++++
EXILED/Exiled.API/Features/Map.cs | 2 +
.../Keycards/SingleUseKeycardPickup.cs | 4 +
.../Generic/SingleUseKeycardRemainingUses.cs | 81 +++++++++++++++++++
4 files changed, 116 insertions(+)
create mode 100644 EXILED/Exiled.Events/Patches/Generic/SingleUseKeycardRemainingUses.cs
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/SingleUseKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/SingleUseKeycard.cs
index 3b96daa67c..0caff46af8 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/SingleUseKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/SingleUseKeycard.cs
@@ -7,6 +7,8 @@
namespace Exiled.API.Features.Items.Keycards
{
+ using System.Collections.Generic;
+
using Exiled.API.Enums;
using Exiled.API.Features.Pickups;
using Exiled.API.Features.Pickups.Keycards;
@@ -43,6 +45,27 @@ internal SingleUseKeycard(ItemType type)
///
public new SingleUseKeycardItem Base { get; }
+ ///
+ /// Gets or sets the amount of uses remaining on the keycard.
+ ///
+ /// Multiple uses can look strange for clients (they'll run the discard animation, but can reselect the keycard)
+ ///
+ /// Setting this to 0 or lower will destroy the keycard.
+ ///
+ public int Uses
+ {
+ get => RemainingUses.TryGetValue(Serial, out int value) ? value : 1;
+ set
+ {
+ if (value <= 0)
+ {
+ IsDestroyed = true;
+ }
+
+ RemainingUses[Serial] = value;
+ }
+ }
+
///
/// Gets or sets the time delay to destroy the Keycard after being used.
///
@@ -77,6 +100,11 @@ public bool IsDestroyed
set => Base._destroyed = value;
}
+ ///
+ /// Gets a dictionary storing all remaining uses for every .
+ ///
+ internal static Dictionary RemainingUses { get; } = new();
+
///
/// Returns the Keycard in a human readable format.
///
@@ -88,6 +116,7 @@ internal override void ReadPickupInfoBefore(Pickup pickup)
{
if (pickup is SingleUseKeycardPickup singleUseKeycard)
{
+ Uses = singleUseKeycard.Uses;
TimeToDestroy = singleUseKeycard.TimeToDestroy;
Permissions = singleUseKeycard.Permissions;
AllowClosingDoors = singleUseKeycard.AllowClosingDoors;
diff --git a/EXILED/Exiled.API/Features/Map.cs b/EXILED/Exiled.API/Features/Map.cs
index fd1110e338..69648a3f3e 100644
--- a/EXILED/Exiled.API/Features/Map.cs
+++ b/EXILED/Exiled.API/Features/Map.cs
@@ -420,6 +420,8 @@ internal static void ClearCache()
CustomKeycardItem.DataDict.Clear();
+ SingleUseKeycard.RemainingUses.Clear();
+
#pragma warning disable CS0618
Scp559.CakeToWrapper.Clear();
diff --git a/EXILED/Exiled.API/Features/Pickups/Keycards/SingleUseKeycardPickup.cs b/EXILED/Exiled.API/Features/Pickups/Keycards/SingleUseKeycardPickup.cs
index 63f5bf322a..8a79b0d405 100644
--- a/EXILED/Exiled.API/Features/Pickups/Keycards/SingleUseKeycardPickup.cs
+++ b/EXILED/Exiled.API/Features/Pickups/Keycards/SingleUseKeycardPickup.cs
@@ -37,6 +37,9 @@ internal SingleUseKeycardPickup(ItemType type)
{
}
+ ///
+ public int Uses { get; set; } = 1;
+
///
/// Gets or sets the time delay to destroy the Keycard after being used.
///
@@ -62,6 +65,7 @@ internal override void ReadItemInfo(Item item)
base.ReadItemInfo(item);
if (item is SingleUseKeycard singleUseKeycardItem)
{
+ Uses = singleUseKeycardItem.Uses;
TimeToDestroy = singleUseKeycardItem.TimeToDestroy;
Permissions = singleUseKeycardItem.Permissions;
AllowClosingDoors = singleUseKeycardItem.AllowClosingDoors;
diff --git a/EXILED/Exiled.Events/Patches/Generic/SingleUseKeycardRemainingUses.cs b/EXILED/Exiled.Events/Patches/Generic/SingleUseKeycardRemainingUses.cs
new file mode 100644
index 0000000000..c14b89b770
--- /dev/null
+++ b/EXILED/Exiled.Events/Patches/Generic/SingleUseKeycardRemainingUses.cs
@@ -0,0 +1,81 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.Patches.Generic
+{
+ using System.Collections.Generic;
+ using System.Reflection.Emit;
+
+ using Exiled.API.Features.Items.Keycards;
+ using Exiled.API.Features.Pools;
+ using HarmonyLib;
+ using InventorySystem.Items.Keycards;
+
+ using static HarmonyLib.AccessTools;
+
+ ///
+ /// Patches .
+ ///
+ [HarmonyPatch(typeof(SingleUseKeycardItem), nameof(SingleUseKeycardItem.OnUsed))]
+ public class SingleUseKeycardRemainingUses
+ {
+ private static IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator)
+ {
+ List newInstructions = ListPool.Pool.Get(instructions);
+
+ LocalBuilder uses = generator.DeclareLocal(typeof(int));
+
+ Label runLabel = generator.DefineLabel();
+
+ // after the return
+ int index = newInstructions.FindIndex(instruction => instruction.opcode == OpCodes.Ret) + 1;
+
+ // get the original jump label and set the jump to our new instructions
+ object continueLabel = newInstructions[index - 2].operand;
+ newInstructions[index - 2].operand = runLabel;
+
+ newInstructions.InsertRange(index, new[]
+ {
+ // SingleUseKeycard.RemainingUses.TryGetValue(ItemSerial, out int uses);
+ new CodeInstruction(OpCodes.Call, PropertyGetter(typeof(SingleUseKeycard), nameof(SingleUseKeycard.RemainingUses))).WithLabels(runLabel),
+ new(OpCodes.Ldarg_0),
+ new(OpCodes.Callvirt, PropertyGetter(typeof(SingleUseKeycardItem), nameof(SingleUseKeycardItem.ItemSerial))),
+ new(OpCodes.Ldloca, uses),
+ new(OpCodes.Callvirt, Method(typeof(Dictionary), nameof(Dictionary.TryGetValue))),
+
+ // run default behavior (destroying keycard) if no stored uses are found.
+ new(OpCodes.Brfalse, continueLabel),
+
+ // uses--;
+ new(OpCodes.Ldloc, uses),
+ new(OpCodes.Ldc_I4_1),
+ new(OpCodes.Sub),
+ new(OpCodes.Stloc, uses),
+
+ // SingleUseKeycard.RemainingUses[ItemSerial] = uses;
+ new(OpCodes.Call, PropertyGetter(typeof(SingleUseKeycard), nameof(SingleUseKeycard.RemainingUses))),
+ new(OpCodes.Ldarg_0),
+ new(OpCodes.Callvirt, PropertyGetter(typeof(SingleUseKeycardItem), nameof(SingleUseKeycardItem.ItemSerial))),
+ new(OpCodes.Ldloc, uses),
+ new(OpCodes.Callvirt, Method(typeof(Dictionary), "set_Item")),
+
+ // if (uses < 1)
+ // run default behavior (destroying keycard)
+ new(OpCodes.Ldloc, uses),
+ new(OpCodes.Ldc_I4_1),
+ new(OpCodes.Blt, continueLabel),
+
+ // Return;
+ new(OpCodes.Ret),
+ });
+ for (int z = 0; z < newInstructions.Count; z++)
+ yield return newInstructions[z];
+
+ ListPool.Pool.Return(newInstructions);
+ }
+ }
+}
\ No newline at end of file
From 846235e6bfab33cff40646ed8cfd843a54b2f69e Mon Sep 17 00:00:00 2001
From: "@Someone" <45270312+Someone-193@users.noreply.github.com>
Date: Wed, 3 Sep 2025 23:12:46 -0400
Subject: [PATCH 33/38] Fix a bit of silliness
Just slightly more optomized
---
EXILED/Exiled.API/Features/Items/Item.cs | 2 +-
EXILED/Exiled.API/Features/Pickups/Pickup.cs | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/EXILED/Exiled.API/Features/Items/Item.cs b/EXILED/Exiled.API/Features/Items/Item.cs
index 3082a75709..01c71eec71 100644
--- a/EXILED/Exiled.API/Features/Items/Item.cs
+++ b/EXILED/Exiled.API/Features/Items/Item.cs
@@ -321,7 +321,7 @@ public static T Get(ushort serial)
{
ChaosKeycardItem => new ChaosKeycard(type),
SingleUseKeycardItem => new SingleUseKeycard(type),
- _ => keycard.ItemTypeId switch
+ _ => type switch
{
ItemType.KeycardCustomTaskForce => new TaskForceKeycard(type),
ItemType.KeycardCustomSite02 => new Site02Keycard(type),
diff --git a/EXILED/Exiled.API/Features/Pickups/Pickup.cs b/EXILED/Exiled.API/Features/Pickups/Pickup.cs
index 24368655f0..ef1106cf46 100644
--- a/EXILED/Exiled.API/Features/Pickups/Pickup.cs
+++ b/EXILED/Exiled.API/Features/Pickups/Pickup.cs
@@ -318,7 +318,7 @@ public static Pickup Get(ItemPickupBase pickupBase)
_ => new GrenadePickup(timeGrenade),
},
BaseFirearmPickup firearmPickup => new FirearmPickup(firearmPickup),
- BaseKeycardPickup keycardPickup => keycardPickup.ItemId.TypeId switch
+ BaseKeycardPickup keycardPickup => keycardPickup.NetworkInfo.ItemId switch
{
ItemType.KeycardCustomTaskForce => new TaskForceKeycardPickup(keycardPickup),
ItemType.KeycardCustomSite02 => new Site02KeycardPickup(keycardPickup),
From 13ff53539b2f192580819513f48ed558594b25cf Mon Sep 17 00:00:00 2001
From: "@Someone" <45270312+Someone-193@users.noreply.github.com>
Date: Wed, 3 Sep 2025 23:40:26 -0400
Subject: [PATCH 34/38] slight forgor?
---
.../Features/Pickups/Keycards/CustomKeycardPickup.cs | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/EXILED/Exiled.API/Features/Pickups/Keycards/CustomKeycardPickup.cs b/EXILED/Exiled.API/Features/Pickups/Keycards/CustomKeycardPickup.cs
index 82fa98024c..e066e92536 100644
--- a/EXILED/Exiled.API/Features/Pickups/Keycards/CustomKeycardPickup.cs
+++ b/EXILED/Exiled.API/Features/Pickups/Keycards/CustomKeycardPickup.cs
@@ -28,8 +28,6 @@ namespace Exiled.API.Features.Pickups.Keycards
///
public abstract class CustomKeycardPickup : Pickups.KeycardPickup
{
- private static readonly ItemType[] AllKeycards = { ItemType.KeycardJanitor, ItemType.KeycardScientist, ItemType.KeycardResearchCoordinator, ItemType.KeycardZoneManager };
-
///
/// Initializes a new instance of the class.
///
@@ -139,7 +137,7 @@ public ItemType FindMatch(bool matchDesign, bool matchPerms, bool matchColors)
ItemType[] toIterate = Type switch
{
- _ when matchDesign => AllKeycards,
+ _ when !matchDesign => CustomKeycardItem.AllKeycards,
ItemType.KeycardCustomSite02 => CustomKeycardItem.AllSite02,
ItemType.KeycardCustomManagement => CustomKeycardItem.AllManagement,
ItemType.KeycardCustomMetalCase => CustomKeycardItem.AllMetalCase,
From 5bd60b32eb5fb899aeac9d617d80590225049cec Mon Sep 17 00:00:00 2001
From: "@Someone" <45270312+Someone-193@users.noreply.github.com>
Date: Thu, 4 Sep 2025 22:47:05 -0400
Subject: [PATCH 35/38] Fix Rank + Accidental Resync call
---
EXILED/Exiled.API/Features/Items/Keycards/CustomKeycardItem.cs | 3 +++
EXILED/Exiled.API/Features/Pickups/KeycardPickup.cs | 3 ++-
.../Features/Pickups/Keycards/CustomKeycardPickup.cs | 3 +++
3 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycardItem.cs b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycardItem.cs
index 004085b922..e57871f7ef 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycardItem.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycardItem.cs
@@ -246,6 +246,9 @@ public void Resync()
if (this is ISerialNumberKeycard serial)
CustomSerialNumberDetail._customVal = serial.SerialNumber;
+ if (this is IRankKeycard rank)
+ CustomRankDetail._index = rank.Rank;
+
MirrorExtensions.ResyncKeycardItem(this);
}
diff --git a/EXILED/Exiled.API/Features/Pickups/KeycardPickup.cs b/EXILED/Exiled.API/Features/Pickups/KeycardPickup.cs
index 87f0a799a2..fa087b7ab1 100644
--- a/EXILED/Exiled.API/Features/Pickups/KeycardPickup.cs
+++ b/EXILED/Exiled.API/Features/Pickups/KeycardPickup.cs
@@ -9,6 +9,7 @@ namespace Exiled.API.Features.Pickups
{
using Exiled.API.Enums;
using Exiled.API.Features.Items;
+ using Exiled.API.Features.Items.Keycards;
using Exiled.API.Interfaces;
using InventorySystem.Items;
@@ -59,7 +60,7 @@ internal KeycardPickup(ItemType type)
internal override void ReadItemInfo(Item item)
{
base.ReadItemInfo(item);
- if (item is Keycard keycarditem)
+ if (item is Keycard keycarditem and not CustomKeycardItem)
{
Permissions = keycarditem.Permissions;
}
diff --git a/EXILED/Exiled.API/Features/Pickups/Keycards/CustomKeycardPickup.cs b/EXILED/Exiled.API/Features/Pickups/Keycards/CustomKeycardPickup.cs
index e066e92536..c49653301c 100644
--- a/EXILED/Exiled.API/Features/Pickups/Keycards/CustomKeycardPickup.cs
+++ b/EXILED/Exiled.API/Features/Pickups/Keycards/CustomKeycardPickup.cs
@@ -209,6 +209,9 @@ public void Resync()
if (this is ISerialNumberKeycard serial)
CustomSerialNumberDetail._customVal = serial.SerialNumber;
+ if (this is IRankKeycard rank)
+ CustomRankDetail._index = rank.Rank;
+
// can happen if a dev does the big dumb
if (Base is null)
{
From 62f7e2216b1f63e4a5a723e054b7c89cd335a262 Mon Sep 17 00:00:00 2001
From: Yamato
Date: Wed, 10 Sep 2025 11:20:48 +0200
Subject: [PATCH 36/38] PredefinedPerms being editable (not sync)
---
EXILED/Exiled.API/Features/Items/Keycard.cs | 22 ++++++++++++---------
1 file changed, 13 insertions(+), 9 deletions(-)
diff --git a/EXILED/Exiled.API/Features/Items/Keycard.cs b/EXILED/Exiled.API/Features/Items/Keycard.cs
index 6e3cf91dea..e153ebdbda 100644
--- a/EXILED/Exiled.API/Features/Items/Keycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycard.cs
@@ -7,10 +7,9 @@
namespace Exiled.API.Features.Items
{
- using System;
-
using Exiled.API.Enums;
using Exiled.API.Interfaces;
+ using Interactables.Interobjects.DoorUtils;
using InventorySystem.Items.Keycards;
///
@@ -52,13 +51,8 @@ public virtual KeycardPermissions Permissions
{
foreach (DetailBase detail in Base.Details)
{
- switch (detail)
- {
- case PredefinedPermsDetail predefinedPermsDetail:
- return (KeycardPermissions)predefinedPermsDetail.Levels.Permissions;
- case CustomPermsDetail customPermsDetail:
- return (KeycardPermissions)customPermsDetail.GetPermissions(null);
- }
+ if (detail is IDoorPermissionProvider doorPermissionProvider)
+ return (KeycardPermissions)doorPermissionProvider.GetPermissions(null);
}
return KeycardPermissions.None;
@@ -66,6 +60,16 @@ public virtual KeycardPermissions Permissions
set
{
+ foreach (DetailBase detail in Base.Details)
+ {
+ if (detail is PredefinedPermsDetail doorPermissionProvider)
+ {
+ KeycardLevels keycardLevels = new((DoorPermissionFlags)value);
+ doorPermissionProvider._containmentLevel = keycardLevels.Containment;
+ doorPermissionProvider._armoryLevel = keycardLevels.Armory;
+ doorPermissionProvider._adminLevel = keycardLevels.Admin;
+ }
+ }
}
}
From 989f1392ae46e96b7036ea3e9d19c9c5e07e29be Mon Sep 17 00:00:00 2001
From: Yamato
Date: Wed, 10 Sep 2025 13:10:54 +0200
Subject: [PATCH 37/38] Remove blank lines between get and set methods
---
.../Exiled.API/Features/Items/Keycards/CustomKeycardItem.cs | 5 -----
EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs | 4 ----
EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs | 4 ----
.../Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs | 3 ---
.../Features/Pickups/Keycards/CustomKeycardPickup.cs | 5 -----
.../Features/Pickups/Keycards/ManagementKeycardPickup.cs | 2 --
.../Features/Pickups/Keycards/MetalKeycardPickup.cs | 5 -----
.../Features/Pickups/Keycards/Site02KeycardPickup.cs | 4 ----
.../Features/Pickups/Keycards/TaskForceKeycardPickup.cs | 3 ---
9 files changed, 35 deletions(-)
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycardItem.cs b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycardItem.cs
index e57871f7ef..7497cfef56 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycardItem.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/CustomKeycardItem.cs
@@ -58,7 +58,6 @@ internal CustomKeycardItem(ItemType type)
public override KeycardPermissions Permissions
{
get => CustomPermsDetail.CustomPermissions.TryGetValue(Serial, out DoorPermissionFlags flags) ? (KeycardPermissions)flags : KeycardPermissions.None;
-
set
{
CustomPermsDetail.CustomPermissions[Serial] = (DoorPermissionFlags)value;
@@ -73,7 +72,6 @@ public override KeycardPermissions Permissions
public KeycardLevels KeycardLevels
{
get => new((DoorPermissionFlags)Permissions);
-
set
{
CustomPermsDetail.CustomPermissions[Serial] = value.Permissions;
@@ -88,7 +86,6 @@ public KeycardLevels KeycardLevels
public Color PermissionsColor
{
get => DataDict[Serial].PermissionsColor ?? Color.clear;
-
set
{
DataDict[Serial].PermissionsColor = value;
@@ -103,7 +100,6 @@ public Color PermissionsColor
public string ItemName
{
get => DataDict[Serial].ItemName;
-
set
{
DataDict[Serial].ItemName = value;
@@ -118,7 +114,6 @@ public string ItemName
public Color Color
{
get => DataDict[Serial].Color ?? Color.clear;
-
set
{
DataDict[Serial].Color = value;
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs
index 291eb6d558..ed7c963a2b 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/MetalKeycard.cs
@@ -43,7 +43,6 @@ internal MetalKeycard(ItemType type)
public string NameTag
{
get => DataDict[Serial].NameTag;
-
set
{
DataDict[Serial].NameTag = value;
@@ -55,7 +54,6 @@ public string NameTag
public string Label
{
get => DataDict[Serial].Label;
-
set
{
DataDict[Serial].Label = value;
@@ -79,7 +77,6 @@ public Color LabelColor
public byte Wear
{
get => DataDict[Serial].Wear;
-
set
{
DataDict[Serial].Wear = value;
@@ -92,7 +89,6 @@ public byte Wear
public string SerialNumber
{
get => DataDict[Serial].SerialNumber;
-
set
{
DataDict[Serial].SerialNumber = value;
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
index 7b73985bae..5cdf7d842b 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/Site02Keycard.cs
@@ -43,7 +43,6 @@ internal Site02Keycard(ItemType type)
public string NameTag
{
get => DataDict[Serial].NameTag;
-
set
{
DataDict[Serial].NameTag = value;
@@ -55,7 +54,6 @@ public string NameTag
public string Label
{
get => DataDict[Serial].Label;
-
set
{
DataDict[Serial].Label = value;
@@ -67,7 +65,6 @@ public string Label
public Color LabelColor
{
get => DataDict[Serial].LabelColor ?? Color.clear;
-
set
{
DataDict[Serial].LabelColor = value;
@@ -80,7 +77,6 @@ public Color LabelColor
public byte Wear
{
get => DataDict[Serial].Wear;
-
set
{
DataDict[Serial].Wear = value;
diff --git a/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs b/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs
index 86347ad962..8775ee0e98 100644
--- a/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs
+++ b/EXILED/Exiled.API/Features/Items/Keycards/TaskForceKeycard.cs
@@ -43,7 +43,6 @@ internal TaskForceKeycard(ItemType type)
public string NameTag
{
get => DataDict[Serial].NameTag;
-
set
{
DataDict[Serial].NameTag = value;
@@ -55,7 +54,6 @@ public string NameTag
public string SerialNumber
{
get => DataDict[Serial].SerialNumber;
-
set
{
DataDict[Serial].SerialNumber = value;
@@ -68,7 +66,6 @@ public string SerialNumber
public byte Rank
{
get => DataDict[Serial].Rank;
-
set
{
DataDict[Serial].Rank = value;
diff --git a/EXILED/Exiled.API/Features/Pickups/Keycards/CustomKeycardPickup.cs b/EXILED/Exiled.API/Features/Pickups/Keycards/CustomKeycardPickup.cs
index c49653301c..8943575c86 100644
--- a/EXILED/Exiled.API/Features/Pickups/Keycards/CustomKeycardPickup.cs
+++ b/EXILED/Exiled.API/Features/Pickups/Keycards/CustomKeycardPickup.cs
@@ -54,7 +54,6 @@ internal CustomKeycardPickup(ItemType type)
public override KeycardPermissions Permissions
{
get => CustomPermsDetail.CustomPermissions.TryGetValue(Serial, out DoorPermissionFlags flags) ? (KeycardPermissions)flags : KeycardPermissions.None;
-
set
{
CustomPermsDetail.CustomPermissions[Serial] = (DoorPermissionFlags)value;
@@ -69,7 +68,6 @@ public override KeycardPermissions Permissions
public KeycardLevels KeycardLevels
{
get => new((DoorPermissionFlags)Permissions);
-
set
{
CustomPermsDetail.CustomPermissions[Serial] = value.Permissions;
@@ -84,7 +82,6 @@ public KeycardLevels KeycardLevels
public Color PermissionsColor
{
get => CustomKeycardItem.DataDict[Serial].PermissionsColor ?? Color.clear;
-
set
{
CustomKeycardItem.DataDict[Serial].PermissionsColor = value;
@@ -99,7 +96,6 @@ public Color PermissionsColor
public string ItemName
{
get => CustomKeycardItem.DataDict[Serial].ItemName;
-
set
{
CustomKeycardItem.DataDict[Serial].ItemName = value;
@@ -114,7 +110,6 @@ public string ItemName
public Color Color
{
get => CustomKeycardItem.DataDict[Serial].Color ?? Color.clear;
-
set
{
CustomKeycardItem.DataDict[Serial].Color = value;
diff --git a/EXILED/Exiled.API/Features/Pickups/Keycards/ManagementKeycardPickup.cs b/EXILED/Exiled.API/Features/Pickups/Keycards/ManagementKeycardPickup.cs
index 9e745a6776..c2adc99aa0 100644
--- a/EXILED/Exiled.API/Features/Pickups/Keycards/ManagementKeycardPickup.cs
+++ b/EXILED/Exiled.API/Features/Pickups/Keycards/ManagementKeycardPickup.cs
@@ -41,7 +41,6 @@ internal ManagementKeycardPickup(ItemType type)
public string Label
{
get => CustomKeycardItem.DataDict[Serial].Label;
-
set
{
CustomKeycardItem.DataDict[Serial].Label = value;
@@ -53,7 +52,6 @@ public string Label
public Color LabelColor
{
get => CustomKeycardItem.DataDict[Serial].LabelColor ?? Color.clear;
-
set
{
CustomKeycardItem.DataDict[Serial].LabelColor = value;
diff --git a/EXILED/Exiled.API/Features/Pickups/Keycards/MetalKeycardPickup.cs b/EXILED/Exiled.API/Features/Pickups/Keycards/MetalKeycardPickup.cs
index 0e2f02b8aa..cf1c0ea894 100644
--- a/EXILED/Exiled.API/Features/Pickups/Keycards/MetalKeycardPickup.cs
+++ b/EXILED/Exiled.API/Features/Pickups/Keycards/MetalKeycardPickup.cs
@@ -41,7 +41,6 @@ internal MetalKeycardPickup(ItemType type)
public string NameTag
{
get => CustomKeycardItem.DataDict[Serial].NameTag;
-
set
{
CustomKeycardItem.DataDict[Serial].NameTag = value;
@@ -53,7 +52,6 @@ public string NameTag
public string Label
{
get => CustomKeycardItem.DataDict[Serial].Label;
-
set
{
CustomKeycardItem.DataDict[Serial].Label = value;
@@ -65,7 +63,6 @@ public string Label
public Color LabelColor
{
get => CustomKeycardItem.DataDict[Serial].LabelColor ?? Color.clear;
-
set
{
CustomKeycardItem.DataDict[Serial].LabelColor = value;
@@ -78,7 +75,6 @@ public Color LabelColor
public byte Wear
{
get => CustomKeycardItem.DataDict[Serial].Wear;
-
set
{
CustomKeycardItem.DataDict[Serial].Wear = value;
@@ -91,7 +87,6 @@ public byte Wear
public string SerialNumber
{
get => CustomKeycardItem.DataDict[Serial].SerialNumber;
-
set
{
CustomKeycardItem.DataDict[Serial].SerialNumber = value;
diff --git a/EXILED/Exiled.API/Features/Pickups/Keycards/Site02KeycardPickup.cs b/EXILED/Exiled.API/Features/Pickups/Keycards/Site02KeycardPickup.cs
index f21aa8cf40..162ec6a721 100644
--- a/EXILED/Exiled.API/Features/Pickups/Keycards/Site02KeycardPickup.cs
+++ b/EXILED/Exiled.API/Features/Pickups/Keycards/Site02KeycardPickup.cs
@@ -41,7 +41,6 @@ internal Site02KeycardPickup(ItemType type)
public string NameTag
{
get => CustomKeycardItem.DataDict[Serial].NameTag;
-
set
{
CustomKeycardItem.DataDict[Serial].NameTag = value;
@@ -53,7 +52,6 @@ public string NameTag
public string Label
{
get => CustomKeycardItem.DataDict[Serial].Label;
-
set
{
CustomKeycardItem.DataDict[Serial].Label = value;
@@ -65,7 +63,6 @@ public string Label
public Color LabelColor
{
get => CustomKeycardItem.DataDict[Serial].LabelColor ?? Color.clear;
-
set
{
CustomKeycardItem.DataDict[Serial].LabelColor = value;
@@ -78,7 +75,6 @@ public Color LabelColor
public byte Wear
{
get => CustomKeycardItem.DataDict[Serial].Wear;
-
set
{
CustomKeycardItem.DataDict[Serial].Wear = value;
diff --git a/EXILED/Exiled.API/Features/Pickups/Keycards/TaskForceKeycardPickup.cs b/EXILED/Exiled.API/Features/Pickups/Keycards/TaskForceKeycardPickup.cs
index 5cbfca9970..a6874f57d3 100644
--- a/EXILED/Exiled.API/Features/Pickups/Keycards/TaskForceKeycardPickup.cs
+++ b/EXILED/Exiled.API/Features/Pickups/Keycards/TaskForceKeycardPickup.cs
@@ -41,7 +41,6 @@ internal TaskForceKeycardPickup(ItemType type)
public string NameTag
{
get => CustomKeycardItem.DataDict[Serial].NameTag;
-
set
{
CustomKeycardItem.DataDict[Serial].NameTag = value;
@@ -53,7 +52,6 @@ public string NameTag
public string SerialNumber
{
get => CustomKeycardItem.DataDict[Serial].SerialNumber;
-
set
{
CustomKeycardItem.DataDict[Serial].SerialNumber = value;
@@ -66,7 +64,6 @@ public string SerialNumber
public byte Rank
{
get => CustomKeycardItem.DataDict[Serial].Rank;
-
set
{
CustomKeycardItem.DataDict[Serial].Rank = value;
From 29745b43fc286fc3f23df0ff9ad1d043649b62e7 Mon Sep 17 00:00:00 2001
From: Yamato
Date: Wed, 10 Sep 2025 13:14:07 +0200
Subject: [PATCH 38/38] No need of multiple Log combine them all
---
.../Features/Pickups/Keycards/CustomKeycardPickup.cs | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/EXILED/Exiled.API/Features/Pickups/Keycards/CustomKeycardPickup.cs b/EXILED/Exiled.API/Features/Pickups/Keycards/CustomKeycardPickup.cs
index 8943575c86..e2c9374ddc 100644
--- a/EXILED/Exiled.API/Features/Pickups/Keycards/CustomKeycardPickup.cs
+++ b/EXILED/Exiled.API/Features/Pickups/Keycards/CustomKeycardPickup.cs
@@ -210,9 +210,7 @@ public void Resync()
// can happen if a dev does the big dumb
if (Base is null)
{
- Log.Error("Base of CustomKeycardPickup was null! See StackTrace to fix problem.");
- Log.Info(GetType());
- Log.Info(new StackTrace());
+ Log.Error($"Base of CustomKeycardPickup was null! See StackTrace to fix problem.\n{GetType()}\n{new StackTrace()}");
}
MirrorExtensions.ResyncKeycardPickup(this);