context: using System;
  using Server.Network;
  using Server.Prompts;
  using Server.Targeting;
  using Server.Engines.Craft;
  
  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 { get { return 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((int)3); // version
  
              writer.Write((int)_Resource);
              writer.Write(_Crafter);
              writer.Write((int)_Quality);
  
              writer.Write((int)m_MaxRange);
  
              writer.Write((Item)m_Link);
  
              writer.Write((string)m_Description);
              writer.Write((uint)m_KeyVal);
          }
  
          public override void Deserialize(GenericReader reader)
          {
              base.Deserialize(reader);
  
              int version = reader.ReadInt();
  
              switch ( version )
              {
                  case 3:
                      {
                          _Resource = (CraftResource)reader.ReadInt();
                          _Crafter = reader.ReadMobile();
                          _Quality = (ItemQuality)reader.ReadInt();
  
                          goto case 2;
                      }
                  case 2:
                      {
                          m_MaxRange = reader.ReadInt();
  
                          goto case 1;
                      }
                  case 1:
                      {
                          m_Link = reader.ReadItem();
  
                          goto case 0;
                      }
                  case 0:
                      {
                          if (version < 2 || m_MaxRange == 0)
                              m_MaxRange = 3;
  
                          m_Description = reader.ReadString();
  
                          m_KeyVal = reader.ReadUInt();
  
                          break;
                      }
              }
          }
  
          public override void OnDoubleClick(Mobile from)
          {
              if (!IsChildOf(from.Backpack))
              {
                  from.SendLocalizedMessage(501661); // That key is unreachable.
                  return;
              }
  
              Target t;
              int number;
  
              if (m_KeyVal != 0)
              {
                  number = 501662; // What shall I use this key on?
                  t = new UnlockTarget(this);
              }
              else
              {
                  number = 501663; // This key is a key blank. Which key would you like to make a copy of?
                  t = new CopyTarget(this);
              }
  
              from.SendLocalizedMessage(number);
              from.Target = t;
          }
  
          public override void AddCraftedProperties(ObjectPropertyList list)
          {
              string desc;
  
              if (m_KeyVal == 0)
                  desc = "(blank)";
              else if ((desc = m_Description) == null || (desc = desc.Trim()).Length <= 0)
                  desc = null;
  
              if (desc != null)
                  list.Add(desc);
  
              if (_Crafter != null)
              {
  
gt:                 list.Add(1050043, _Crafter.TitleName); // crafted by ~1_NAME~