context: using Server.Engines.Craft;
  using Server.Prompts;
  using Server.Targeting;
  using System;
  
  namespace Server.Items
  {
      public enum KeyType
      {
          Copper = 0x100E,
          Gold = 0x100F,
          Iron = 0x1010,
          Rusty = 0x1013
      }
  
      public interface ILockable
      {
          bool Locked { get; set; }
          uint KeyValue { get; set; }
      }
  
      public class Key : Item, IResource, IQuality
      {
          private string m_Description;
          private uint m_KeyVal;
          private Item m_Link;
          private int m_MaxRange;
  
          private CraftResource _Resource;
          private Mobile _Crafter;
          private ItemQuality _Quality;
  
          [CommandProperty(AccessLevel.GameMaster)]
          public CraftResource Resource { get { return _Resource; } set { _Resource = value; _Resource = value; Hue = CraftResources.GetHue(_Resource); InvalidateProperties(); } }
  
          [CommandProperty(AccessLevel.GameMaster)]
          public Mobile Crafter { get { return _Crafter; } set { _Crafter = value; InvalidateProperties(); } }
  
          [CommandProperty(AccessLevel.GameMaster)]
          public ItemQuality Quality { get { return _Quality; } set { _Quality = value; InvalidateProperties(); } }
  
          public bool PlayerConstructed => true;
  
          [Constructable]
          public Key()
              : this(KeyType.Iron, 0)
          {
          }
  
          [Constructable]
          public Key(KeyType type)
              : this(type, 0)
          {
          }
  
          [Constructable]
          public Key(uint val)
              : this(KeyType.Iron, val)
          {
          }
  
          [Constructable]
          public Key(KeyType type, uint LockVal)
              : this(type, LockVal, null)
          {
              m_KeyVal = LockVal;
          }
  
          public Key(KeyType type, uint LockVal, Item link)
              : base((int)type)
          {
              Weight = 1.0;
  
              m_MaxRange = 3;
              m_KeyVal = LockVal;
              m_Link = link;
          }
  
          public Key(Serial serial)
              : base(serial)
          {
          }
  
          [CommandProperty(AccessLevel.GameMaster)]
          public string Description
          {
              get
              {
                  return m_Description;
              }
              set
              {
                  m_Description = value;
                  InvalidateProperties();
              }
          }
          [CommandProperty(AccessLevel.GameMaster)]
          public int MaxRange
          {
              get
              {
                  return m_MaxRange;
              }
  
              set
              {
                  m_MaxRange = value;
              }
          }
          [CommandProperty(AccessLevel.GameMaster)]
          public uint KeyValue
          {
              get
              {
                  return m_KeyVal;
              }
  
              set
              {
                  m_KeyVal = value;
                  InvalidateProperties();
              }
          }
          [CommandProperty(AccessLevel.GameMaster)]
          public Item Link
          {
              get
              {
                  return m_Link;
              }
  
              set
              {
                  m_Link = value;
              }
          }
          public static uint RandomValue()
          {
              return (uint)(0xFFFFFFFE * Utility.RandomDouble()) + 1;
          }
  
          public static void RemoveKeys(Mobile m, uint keyValue)
          {
              if (keyValue == 0)
                  return;
  
              RemoveKeys(m.Backpack, keyValue);
              RemoveKeys(m.BankBox, keyValue);
          }
  
          public static void RemoveKeys(Container cont, uint keyValue)
          {
              if (cont == null || keyValue == 0)
                  return;
  
              Item[] items = cont.FindItemsByType(new Type[] { typeof(Key), typeof(KeyRing) });
  
              foreach (Item item in items)
              {
                  if (item is Key)
                  {
                      Key key = (Key)item;
  
                      if (key.KeyValue == keyValue)
                          key.Delete();
                  }
                  else
                  {
                      KeyRing keyRing = (KeyRing)item;
  
                      keyRing.RemoveKeys(keyValue);
                  }
              }
          }
  
          public static bool ContainsKey(Container cont, uint keyValue)
          {
              if (cont == null)
                  return false;
  
              Item[] items = cont.FindItemsByType(new Type[] { typeof(Key), typeof(KeyRing) });
  
              foreach (Item item in items)
              {
                  if (item is Key)
                  {
                      Key key = (Key)item;
  
                      if (key.KeyValue == keyValue)
                          return true;
                  }
                  else
                  {
                      KeyRing keyRing = (KeyRing)item;
  
                      if (keyRing.ContainsKey(keyValue))
                          return true;
                  }
              }
  
              return false;
          }
  
          public override void Serialize(GenericWriter writer)
          {
              base.Serialize(writer);
  
              writer.Write(3); // version
  
              writer.Write((int)_Resource);
              writer.Write(_Crafter);
              writer.Write((int)_Quality);
  
              writer.Write(m_MaxRange);
  
              writer.Write(m_Link);
  
              writer.Write(m_Description);
              writer.Write(m_KeyVal);
          }
  
          public override void Deserialize(GenericReader reader)
          {
              base.Deserialize(reader);
  
              int version = reader.ReadInt();
  
              switch (version)
              {
                  case 3:
                      {
                          _Resource = (CraftResource)reader.ReadInt();
  
gt:                         _Crafter = reader.ReadMobile();