context: #region References
  using System;
  using System.Collections.Generic;
  using System.Diagnostics;
  using System.Drawing;
  using System.Drawing.Imaging;
  using System.IO;
  using System.Linq;
  using System.Threading.Tasks;
  
  using CustomsFramework;
  
  using Server.ContextMenus;
  using Server.Items;
  using Server.Network;
  using Server.Targeting;
  #endregion
  
  namespace Server
  {
      /// <summary>
      ///     Enumeration of item layer values.
      /// </summary>
      public enum Layer : byte
      {
          /// <summary>
          ///     Invalid layer.
          /// </summary>
          Invalid = 0x00,
  
          /// <summary>
          ///     First valid layer. Equivalent to <c>Layer.OneHanded</c>.
          /// </summary>
          FirstValid = 0x01,
  
          /// <summary>
          ///     One handed weapon.
          /// </summary>
          OneHanded = 0x01,
  
          /// <summary>
          ///     Two handed weapon or shield.
          /// </summary>
          TwoHanded = 0x02,
  
          /// <summary>
          ///     Shoes.
          /// </summary>
          Shoes = 0x03,
  
          /// <summary>
          ///     Pants.
          /// </summary>
          Pants = 0x04,
  
          /// <summary>
          ///     Shirts.
          /// </summary>
          Shirt = 0x05,
  
          /// <summary>
          ///     Helmets, hats, and masks.
          /// </summary>
          Helm = 0x06,
  
          /// <summary>
          ///     Gloves.
          /// </summary>
          Gloves = 0x07,
  
          /// <summary>
          ///     Rings.
          /// </summary>
          Ring = 0x08,
  
          /// <summary>
          ///     Talismans.
          /// </summary>
          Talisman = 0x09,
  
          /// <summary>
          ///     Gorgets and necklaces.
          /// </summary>
          Neck = 0x0A,
  
          /// <summary>
          ///     Hair.
          /// </summary>
          Hair = 0x0B,
  
          /// <summary>
          ///     Half aprons.
          /// </summary>
          Waist = 0x0C,
  
          /// <summary>
          ///     Torso, inner layer.
          /// </summary>
          InnerTorso = 0x0D,
  
          /// <summary>
          ///     Bracelets.
          /// </summary>
          Bracelet = 0x0E,
  
          /// <summary>
          ///     Face.
          /// </summary>
          Face = 0x0F,
  
          /// <summary>
          ///     Beards and mustaches.
          /// </summary>
          FacialHair = 0x10,
  
          /// <summary>
          ///     Torso, outer layer.
          /// </summary>
          MiddleTorso = 0x11,
  
          /// <summary>
          ///     Earings.
          /// </summary>
          Earrings = 0x12,
  
          /// <summary>
          ///     Arms and sleeves.
          /// </summary>
          Arms = 0x13,
  
          /// <summary>
          ///     Cloaks.
          /// </summary>
          Cloak = 0x14,
  
          /// <summary>
          ///     Backpacks.
          /// </summary>
          Backpack = 0x15,
  
          /// <summary>
          ///     Torso, outer layer.
          /// </summary>
          OuterTorso = 0x16,
  
          /// <summary>
          ///     Leggings, outer layer.
          /// </summary>
          OuterLegs = 0x17,
  
          /// <summary>
          ///     Leggings, inner layer.
          /// </summary>
          InnerLegs = 0x18,
  
          /// <summary>
          ///     Last valid non-internal layer. Equivalent to <c>Layer.InnerLegs</c>.
          /// </summary>
          LastUserValid = 0x18,
  
          /// <summary>
          ///     Mount item layer.
          /// </summary>
          Mount = 0x19,
  
          /// <summary>
          ///     Vendor 'buy pack' layer.
          /// </summary>
          ShopBuy = 0x1A,
  
          /// <summary>
          ///     Vendor 'resale pack' layer.
          /// </summary>
          ShopResale = 0x1B,
  
          /// <summary>
          ///     Vendor 'sell pack' layer.
          /// </summary>
          ShopSell = 0x1C,
  
          /// <summary>
          ///     Bank box layer.
          /// </summary>
          Bank = 0x1D,
  
          /// <summary>
          /// Unused, using this layer makes you invisible to other players. Strange.
          /// </summary>
          /// 
          Reserved_1 = 0x1E,
  
          /// <summary>
          ///     Secure Trade Layer
          /// </summary>
          SecureTrade = 0x1F,
      }
  
      /// <summary>
      ///     Internal flags used to signal how the item should be updated and resent to nearby clients.
      /// </summary>
      [Flags]
      public enum ItemDelta
      {
          /// <summary>
          ///     Nothing.
          /// </summary>
          None = 0x00000000,
  
          /// <summary>
          ///     Resend the item.
          /// </summary>
          Update = 0x00000001,
  
          /// <summary>
          ///     Resend the item only if it is equiped.
          /// </summary>
          EquipOnly = 0x00000002,
  
          /// <summary>
          ///     Resend the item's properties.
          /// </summary>
          Properties = 0x00000004
      }
  
      /// <summary>
      ///     Enumeration containing possible ways to handle item ownership on death.
      /// </summary>
      public enum DeathMoveResult
      {
          /// <summary>
          ///     The item should be placed onto the corpse.
          /// </summary>
          MoveToCorpse,
  
          /// <summary>
          ///     The item should remain equiped.
          /// </summary>
          RemainEquiped,
  
          /// <summary>
          ///     The item should be placed into the owners backpack.
          /// </summary>
          MoveToBackpack
      }
  
      /// <summary>
      ///     Enumeration containing all possible light types. These are only applicable to light source items, like lanterns, candles, braziers, etc.
      /// </summary>
      public enum LightType
      {
          /// <summary>
          ///     Window shape, arched, ray shining east.
          /// </summary>
          ArchedWindowEast = 0,
  
          /// <summary>
          ///     Medium circular shape.
          /// </summary>
          Circle225 = 1,
  
          /// <summary>
          ///     Small circular shape.
          /// </summary>
          Circle150 = 2,
  
          /// <summary>
          ///     Door shape, shining south.
          /// </summary>
          DoorSouth = 3,
  
          /// <summary>
          ///     Door shape, shining east.
          /// </summary>
          DoorEast = 4,
  
          /// <summary>
          ///     Large semicircular shape (180 degrees), north wall.
          /// </summary>
          NorthBig = 5,
  
          /// <summary>
          ///     Large pie shape (90 degrees), north-east corner.
          /// </summary>
          NorthEastBig = 6,
  
          /// <summary>
          ///     Large semicircular shape (180 degrees), east wall.
          /// </summary>
          EastBig = 7,
  
          /// <summary>
          ///     Large semicircular shape (180 degrees), west wall.
          /// </summary>
          WestBig = 8,
  
          /// <summary>
          ///     Large pie shape (90 degrees), south-west corner.
          /// </summary>
          SouthWestBig = 9,
  
          /// <summary>
          ///     Large semicircular shape (180 degrees), south wall.
          /// </summary>
          SouthBig = 10,
  
          /// <summary>
          ///     Medium semicircular shape (180 degrees), north wall.
          /// </summary>
          NorthSmall = 11,
  
          /// <summary>
          ///     Medium pie shape (90 degrees), north-east corner.
          /// </summary>
          NorthEastSmall = 12,
  
          /// <summary>
          ///     Medium semicircular shape (180 degrees), east wall.
          /// </summary>
          EastSmall = 13,
  
          /// <summary>
          ///     Medium semicircular shape (180 degrees), west wall.
          /// </summary>
          WestSmall = 14,
  
          /// <summary>
          ///     Medium semicircular shape (180 degrees), south wall.
          /// </summary>
          SouthSmall = 15,
  
          /// <summary>
          ///     Shaped like a wall decoration, north wall.
          /// </summary>
          DecorationNorth = 16,
  
          /// <summary>
          ///     Shaped like a wall decoration, north-east corner.
          /// </summary>
          DecorationNorthEast = 17,
  
          /// <summary>
          ///     Small semicircular shape (180 degrees), east wall.
          /// </summary>
          EastTiny = 18,
  
          /// <summary>
          ///     Shaped like a wall decoration, west wall.
          /// </summary>
          DecorationWest = 19,
  
          /// <summary>
          ///     Shaped like a wall decoration, south-west corner.
          /// </summary>
          DecorationSouthWest = 20,
  
          /// <summary>
          ///     Small semicircular shape (180 degrees), south wall.
          /// </summary>
          SouthTiny = 21,
  
          /// <summary>
          ///     Window shape, rectangular, no ray, shining south.
          /// </summary>
          RectWindowSouthNoRay = 22,
  
          /// <summary>
          ///     Window shape, rectangular, no ray, shining east.
          /// </summary>
          RectWindowEastNoRay = 23,
  
          /// <summary>
          ///     Window shape, rectangular, ray shining south.
          /// </summary>
          RectWindowSouth = 24,
  
          /// <summary>
          ///     Window shape, rectangular, ray shining east.
          /// </summary>
          RectWindowEast = 25,
  
          /// <summary>
          ///     Window shape, arched, no ray, shining south.
          /// </summary>
          ArchedWindowSouthNoRay = 26,
  
          /// <summary>
          ///     Window shape, arched, no ray, shining east.
          /// </summary>
          ArchedWindowEastNoRay = 27,
  
          /// <summary>
          ///     Window shape, arched, ray shining south.
          /// </summary>
          ArchedWindowSouth = 28,
  
          /// <summary>
          ///     Large circular shape.
          /// </summary>
          Circle300 = 29,
  
          /// <summary>
          ///     Large pie shape (90 degrees), north-west corner.
          /// </summary>
          NorthWestBig = 30,
  
          /// <summary>
          ///     Negative light. Medium pie shape (90 degrees), south-east corner.
          /// </summary>
          DarkSouthEast = 31,
  
          /// <summary>
          ///     Negative light. Medium semicircular shape (180 degrees), south wall.
          /// </summary>
          DarkSouth = 32,
  
          /// <summary>
          ///     Negative light. Medium pie shape (90 degrees), north-west corner.
          /// </summary>
          DarkNorthWest = 33,
  
          /// <summary>
          ///     Negative light. Medium pie shape (90 degrees), south-east corner. Equivalent to <c>LightType.SouthEast</c>.
          /// </summary>
          DarkSouthEast2 = 34,
  
          /// <summary>
          ///     Negative light. Medium circular shape (180 degrees), east wall.
          /// </summary>
          DarkEast = 35,
  
          /// <summary>
          ///     Negative light. Large circular shape.
          /// </summary>
          DarkCircle300 = 36,
  
          /// <summary>
          ///     Opened door shape, shining south.
          /// </summary>
          DoorOpenSouth = 37,
  
          /// <summary>
          ///     Opened door shape, shining east.
          /// </summary>
          DoorOpenEast = 38,
  
          /// <summary>
          ///     Window shape, square, ray shining east.
          /// </summary>
          SquareWindowEast = 39,
  
          /// <summary>
          ///     Window shape, square, no ray, shining east.
          /// </summary>
          SquareWindowEastNoRay = 40,
  
          /// <summary>
          ///     Window shape, square, ray shining south.
          /// </summary>
          SquareWindowSouth = 41,
  
          /// <summary>
          ///     Window shape, square, no ray, shining south.
          /// </summary>
          SquareWindowSouthNoRay = 42,
  
          /// <summary>
          ///     Empty.
          /// </summary>
          Empty = 43,
  
          /// <summary>
          ///     Window shape, skinny, no ray, shining south.
          /// </summary>
          SkinnyWindowSouthNoRay = 44,
  
          /// <summary>
          ///     Window shape, skinny, ray shining east.
          /// </summary>
          SkinnyWindowEast = 45,
  
          /// <summary>
          ///     Window shape, skinny, no ray, shining east.
          /// </summary>
          SkinnyWindowEastNoRay = 46,
  
          /// <summary>
          ///     Shaped like a hole, shining south.
          /// </summary>
          HoleSouth = 47,
  
          /// <summary>
          ///     Shaped like a hole, shining south.
          /// </summary>
          HoleEast = 48,
  
          /// <summary>
          ///     Large circular shape with a moongate graphic embeded.
          /// </summary>
          Moongate = 49,
  
          /// <summary>
          ///     Unknown usage. Many rows of slightly angled lines.
          /// </summary>
          Strips = 50,
  
          /// <summary>
          ///     Shaped like a small hole, shining south.
          /// </summary>
          SmallHoleSouth = 51,
  
          /// <summary>
          ///     Shaped like a small hole, shining east.
          /// </summary>
          SmallHoleEast = 52,
  
          /// <summary>
          ///     Large semicircular shape (180 degrees), north wall. Identical graphic as <c>LightType.NorthBig</c>, but slightly different positioning.
          /// </summary>
          NorthBig2 = 53,
  
          /// <summary>
          ///     Large semicircular shape (180 degrees), west wall. Identical graphic as <c>LightType.WestBig</c>, but slightly different positioning.
          /// </summary>
          WestBig2 = 54,
  
          /// <summary>
          ///     Large pie shape (90 degrees), north-west corner. Equivalent to <c>LightType.NorthWestBig</c>.
          /// </summary>
          NorthWestBig2 = 55
      }
  
      /// <summary>
      ///     Enumeration of an item's loot and steal state.
      /// </summary>
      public enum LootType : byte
      {
          /// <summary>
          ///     Stealable. Lootable.
          /// </summary>
          Regular = 0,
  
          /// <summary>
          ///     Unstealable. Unlootable, unless owned by a murderer.
          /// </summary>
          Newbied = 1,
  
          /// <summary>
          ///     Unstealable. Unlootable, always.
          /// </summary>
          Blessed = 2,
  
          /// <summary>
          ///     Stealable. Lootable, always.
          /// </summary>
          Cursed = 3
      }
  
      public class BounceInfo
      {
          public Map m_Map;
          public Point3D m_Location, m_WorldLoc;
          public object m_Parent;
          public object m_ParentStack;
          public byte m_GridLocation;
          public Mobile m_Mobile;
  
          public BounceInfo(Mobile from, Item item)
          {
              m_Map = item.Map;
              m_Location = item.Location;
              m_WorldLoc = item.GetWorldLocation();
              m_Parent = item.Parent;
              m_ParentStack = null;
              m_GridLocation = item.GridLocation;
              m_Mobile = from;
          }
  
          private BounceInfo(Map map, Point3D loc, Point3D worldLoc, IEntity parent)
          {
              m_Map = map;
              m_Location = loc;
              m_WorldLoc = worldLoc;
              m_Parent = parent;
              m_ParentStack = null;
          }
  
          public static BounceInfo Deserialize(GenericReader reader)
          {
              if (reader.ReadBool())
              {
                  Map map = reader.ReadMap();
                  Point3D loc = reader.ReadPoint3D();
                  Point3D worldLoc = reader.ReadPoint3D();
  
                  IEntity parent;
  
                  Serial serial = reader.ReadInt();
  
                  if (serial.IsItem)
                  {
                      parent = World.FindItem(serial);
                  }
                  else if (serial.IsMobile)
                  {
                      parent = World.FindMobile(serial);
                  }
                  else
                  {
                      parent = null;
                  }
  
                  return new BounceInfo(map, loc, worldLoc, parent);
              }
              else
              {
                  return null;
              }
          }
  
          public static void Serialize(BounceInfo info, GenericWriter writer)
          {
              if (info == null)
              {
                  writer.Write(false);
              }
              else
              {
                  writer.Write(true);
  
                  writer.Write(info.m_Map);
                  writer.Write(info.m_Location);
                  writer.Write(info.m_WorldLoc);
  
                  if (info.m_Parent is Mobile)
                  {
                      writer.Write((Mobile)info.m_Parent);
                  }
                  else if (info.m_Parent is Item)
                  {
                      writer.Write((Item)info.m_Parent);
                  }
                  else
                  {
                      writer.Write((Serial)0);
                  }
              }
          }
      }
  
      public enum TotalType
      {
          Gold,
          Items,
          Weight,
      }
  
      [Flags]
      public enum ExpandFlag
      {
          None = 0x000,
  
          Name = 0x001,
          Items = 0x002,
          Bounce = 0x004,
          Holder = 0x008,
          Blessed = 0x010,
          TempFlag = 0x020,
          SaveFlag = 0x040,
          Weight = 0x080,
          Spawner = 0x100
      }
  
      public class Item : IEntity, IHued, IComparable<Item>, ISerializable, ISpawnable
      {
          #region Customs Framework
          private List<BaseModule> m_Modules = new List<BaseModule>();
  
          [CommandProperty(AccessLevel.Developer)]
          public List<BaseModule> Modules { get { return m_Modules; } set { m_Modules = value; } }
  
          public BaseModule GetModule(string name)
          {
              return Modules.FirstOrDefault(mod => mod.Name == name);
          }
  
          public BaseModule GetModule(Type type)
          {
              return Modules.FirstOrDefault(mod => mod.GetType() == type);
          }
  
          public List<BaseModule> GetModules(string name)
          {
              return Modules.Where(mod => mod.Name == name).ToList();
          }
  
          public List<BaseModule> SearchModules(string search)
          {
              var keywords = search.ToLower().Split(' ');
              var modules = new List<BaseModule>();
  
              foreach (BaseModule mod in Modules)
              {
                  bool match = true;
                  string name = mod.Name.ToLower();
  
                  foreach (string keyword in keywords)
                  {
                      if (name.IndexOf(keyword, StringComparison.Ordinal) == -1)
                      {
                          match = false;
                      }
                  }
  
                  if (match)
                  {
                      modules.Add(mod);
                  }
              }
  
              return modules;
          }
          #endregion
  
          public static readonly List<Item> EmptyItems = new List<Item>();
  
          public int CompareTo(IEntity other)
          {
              if (other == null)
              {
                  return -1;
              }
  
              return m_Serial.CompareTo(other.Serial);
          }
  
          public int CompareTo(Item other)
          {
              return CompareTo((IEntity)other);
          }
  
          public int CompareTo(object other)
          {
              if (other == null || other is IEntity)
              {
                  return CompareTo((IEntity)other);
              }
  
              throw new ArgumentException();
          }
  
          #region Standard fields
          private Serial m_Serial;
          private Point3D m_Location;
          private int m_ItemID;
          private int m_Hue;
          private int m_Amount;
          private Layer m_Layer;
          private object m_Parent; // Mobile, Item, or null=World
          private Map m_Map;
          private LootType m_LootType;
          private DateTime m_LastMovedTime;
          private Direction m_Direction;
          private LightType m_Light;
          #endregion
  
          private ItemDelta m_DeltaFlags;
          private ImplFlag m_Flags;
  
          #region Packet caches
          private Packet m_WorldPacket;
          private Packet m_WorldPacketSA;
          private Packet m_WorldPacketHS;
          private Packet m_RemovePacket;
  
          private Packet m_OPLPacket;
          private ObjectPropertyList m_PropertyList;
          #endregion
  
          public int TempFlags
          {
              get
              {
                  CompactInfo info = LookupCompactInfo();
  
                  if (info != null)
                  {
                      return info.m_TempFlags;
                  }
  
                  return 0;
              }
              set
              {
                  CompactInfo info = AcquireCompactInfo();
  
                  info.m_TempFlags = value;
  
                  if (info.m_TempFlags == 0)
                  {
                      VerifyCompactInfo();
                  }
              }
          }
  
          public int SavedFlags
          {
              get
              {
                  CompactInfo info = LookupCompactInfo();
  
                  if (info != null)
                  {
                      return info.m_SavedFlags;
                  }
  
                  return 0;
              }
              set
              {
                  CompactInfo info = AcquireCompactInfo();
  
                  info.m_SavedFlags = value;
  
                  if (info.m_SavedFlags == 0)
                  {
                      VerifyCompactInfo();
                  }
              }
          }
  
          /// <summary>
          ///     The <see cref="Mobile" /> who is currently <see cref="Mobile.Holding">holding</see> this item.
          /// </summary>
          public Mobile HeldBy
          {
              get
              {
                  CompactInfo info = LookupCompactInfo();
  
                  if (info != null)
                  {
                      return info.m_HeldBy;
                  }
  
                  return null;
              }
              set
              {
                  CompactInfo info = AcquireCompactInfo();
  
                  info.m_HeldBy = value;
  
                  if (info.m_HeldBy == null)
                  {
                      VerifyCompactInfo();
                  }
              }
          }
          
          private byte m_GridLocation = 0;
  
          [CommandProperty(AccessLevel.GameMaster)]
          public byte GridLocation
          {
              get { return m_GridLocation; }
              set
              {
                  if (Parent is Container)
                  {
                      if (value < 0 || value > 0x7C || !((Container)Parent).IsFreePosition(value))
                      {
                          m_GridLocation = ((Container)Parent).GetNewPosition(0);
                      }
                      else
                      {
                          m_GridLocation = value;
                      }
                  }
                  else
                  {
                      m_GridLocation = value;
                  }
              }
          }
  
          [Flags]
          private enum ImplFlag : byte
          {
              None = 0x00,
              Visible = 0x01,
              Movable = 0x02,
              Deleted = 0x04,
              Stackable = 0x08,
              InQueue = 0x10,
              Insured = 0x20,
              PayedInsurance = 0x40,
              QuestItem = 0x80
          }
  
          private class CompactInfo
          {
              public string m_Name;
  
              public List<Item> m_Items;
              public BounceInfo m_Bounce;
  
              public Mobile m_HeldBy;
              public Mobile m_BlessedFor;
  
              public ISpawner m_Spawner;
  
              public int m_TempFlags;
              public int m_SavedFlags;
  
              public double m_Weight = -1;
          }
  
          private CompactInfo m_CompactInfo;
  
          public ExpandFlag GetExpandFlags()
          {
              CompactInfo info = LookupCompactInfo();
  
              ExpandFlag flags = 0;
  
              if (info != null)
              {
                  if (info.m_BlessedFor != null)
                  {
                      flags |= ExpandFlag.Blessed;
                  }
  
                  if (info.m_Bounce != null)
                  {
                      flags |= ExpandFlag.Bounce;
                  }
  
                  if (info.m_HeldBy != null)
                  {
                      flags |= ExpandFlag.Holder;
                  }
  
                  if (info.m_Items != null)
                  {
                      flags |= ExpandFlag.Items;
                  }
  
                  if (info.m_Name != null)
                  {
                      flags |= ExpandFlag.Name;
                  }
  
                  if (info.m_Spawner != null)
                  {
                      flags |= ExpandFlag.Spawner;
                  }
  
                  if (info.m_SavedFlags != 0)
                  {
                      flags |= ExpandFlag.SaveFlag;
                  }
  
                  if (info.m_TempFlags != 0)
                  {
                      flags |= ExpandFlag.TempFlag;
                  }
  
                  if (info.m_Weight != -1)
                  {
                      flags |= ExpandFlag.Weight;
                  }
              }
  
              return flags;
          }
  
          private CompactInfo LookupCompactInfo()
          {
              return m_CompactInfo;
          }
  
          private CompactInfo AcquireCompactInfo()
          {
              if (m_CompactInfo == null)
              {
                  m_CompactInfo = new CompactInfo();
              }
  
              return m_CompactInfo;
          }
  
          private void ReleaseCompactInfo()
          {
              m_CompactInfo = null;
          }
  
          private void VerifyCompactInfo()
          {
              CompactInfo info = m_CompactInfo;
  
              if (info == null)
              {
                  return;
              }
  
              bool isValid = (info.m_Name != null) || (info.m_Items != null) || (info.m_Bounce != null) || (info.m_HeldBy != null) ||
                             (info.m_BlessedFor != null) || (info.m_Spawner != null) || (info.m_TempFlags != 0) || (info.m_SavedFlags != 0) ||
                             (info.m_Weight != -1);
  
              if (!isValid)
              {
                  ReleaseCompactInfo();
              }
          }
  
          public List<Item> LookupItems()
          {
              if (this is Container)
              {
                  return ((Container)this).m_Items;
              }
  
              CompactInfo info = LookupCompactInfo();
  
              if (info != null)
              {
                  return info.m_Items;
              }
  
              return null;
          }
  
          public List<Item> AcquireItems()
          {
              if (this is Container)
              {
                  Container cont = (Container)this;
  
                  if (cont.m_Items == null)
                  {
                      cont.m_Items = new List<Item>();
                  }
  
                  return cont.m_Items;
              }
  
              CompactInfo info = AcquireCompactInfo();
  
              if (info.m_Items == null)
              {
                  info.m_Items = new List<Item>();
              }
  
              return info.m_Items;
          }
  
          #region Mondain's Legacy
          public static Bitmap GetBitmap(int itemID)
          {
              try
              {
                  return Ultima.Art.GetStatic(itemID);
              }
              catch
              {
                  if (Core.Debug)
                  {
                      Utility.PushColor(ConsoleColor.Red);
                      Console.WriteLine("Ultima Art: Unable to read client files.");
                      Utility.PopColor();
                  }
              }
  
              return null;
          }
  
          public static void Measure(Bitmap bmp, out int xMin, out int yMin, out int xMax, out int yMax)
          {
              Ultima.Art.Measure(bmp, out xMin, out yMin, out xMax, out yMax);
          }
  
          public static Rectangle MeasureBound(Bitmap bmp)
          {
              int xMin, yMin, xMax, yMax;
              Measure(bmp, out xMin, out yMin, out xMax, out yMax);
              return new Rectangle(xMin, yMin, xMax - xMin, yMax - yMin);
          }
  
          public static Size MeasureSize(Bitmap bmp)
          {
              int xMin, yMin, xMax, yMax;
              Measure(bmp, out xMin, out yMin, out xMax, out yMax);
              return new Size(xMax - xMin, yMax - yMin);
          }
          #endregion
  
          private void SetFlag(ImplFlag flag, bool value)
          {
              if (value)
              {
                  m_Flags |= flag;
              }
              else
              {
                  m_Flags &= ~flag;
              }
          }
  
          private bool GetFlag(ImplFlag flag)
          {
              return ((m_Flags & flag) != 0);
          }
  
          public BounceInfo GetBounce()
          {
              CompactInfo info = LookupCompactInfo();
  
              if (info != null)
              {
                  return info.m_Bounce;
              }
  
              return null;
          }
  
          public void RecordBounce(Mobile from, Item parentstack = null)
          {
              CompactInfo info = AcquireCompactInfo();
  
              info.m_Bounce = new BounceInfo(from, this);
              info.m_Bounce.m_ParentStack = parentstack;
          }
  
          public void ClearBounce()
          {
              CompactInfo info = LookupCompactInfo();
  
              if (info != null)
              {
                  BounceInfo bounce = info.m_Bounce;
  
                  if (bounce != null)
                  {
                      info.m_Bounce = null;
  
                      if (bounce.m_Parent is Item)
                      {
                          Item parent = (Item)bounce.m_Parent;
  
                          if (!parent.Deleted)
                          {
                              parent.OnItemBounceCleared(this);
                          }
                      }
                      else if (bounce.m_Parent is Mobile)
                      {
                          Mobile parent = (Mobile)bounce.m_Parent;
  
                          if (!parent.Deleted)
                          {
                              parent.OnItemBounceCleared(this);
                          }
                      }
  
                      VerifyCompactInfo();
                  }
              }
          }
  
          /// <summary>
          ///     Overridable. Virtual event invoked when a client, <paramref name="from" />, invokes a 'help request' for the Item. Seemingly no longer functional in newer clients.
          /// </summary>
          public virtual void OnHelpRequest(Mobile from)
          { }
  
          /// <summary>
          ///     Overridable. Method checked to see if the item can be traded.
          /// </summary>
          /// <returns>True if the trade is allowed, false if not.</returns>
          public virtual bool AllowSecureTrade(Mobile from, Mobile to, Mobile newOwner, bool accepted)
          {
              return true;
          }
  
          /// <summary>
          ///     Overridable. Virtual event invoked when a trade has completed, either successfully or not.
          /// </summary>
          public virtual void OnSecureTrade(Mobile from, Mobile to, Mobile newOwner, bool accepted)
          { }
  
          /// <summary>
          ///     Overridable. Method checked to see if the elemental resistances of this Item conflict with another Item on the
          ///     <see
          ///         cref="Mobile" />
          ///     .
          /// </summary>
          /// <returns>
          ///     <list type="table">
          ///         <item>
          ///             <term>True</term>
          ///             <description>
          ///                 There is a confliction. The elemental resistance bonuses of this Item should not be applied to the
          ///                 <see
          ///                     cref="Mobile" />
          ///             </description>
          ///         </item>
          ///         <item>
          ///             <term>False</term>
          ///             <description>There is no confliction. The bonuses should be applied.</description>
          ///         </item>
          ///     </list>
          /// </returns>
          public virtual bool CheckPropertyConfliction(Mobile m)
          {
              return false;
          }
  
          /// <summary>
          ///     Overridable. Sends the <see cref="PropertyList">object property list</see> to <paramref name="from" />.
          /// </summary>
          public virtual void SendPropertiesTo(Mobile from)
          {
              from.Send(PropertyList);
          }
  
          /// <summary>
          ///     Overridable. Adds the name of this item to the given <see cref="ObjectPropertyList" />. This method should be
          ///     overriden if the item requires a complex naming format.
          /// </summary>
          public virtual void AddNameProperty(ObjectPropertyList list)
          {
              string name = Name ?? String.Empty;
  
              if (String.IsNullOrWhiteSpace(name))
              {
                  if (m_Amount <= 1)
                  {
                      list.Add(LabelNumber);
                  }
                  else
                  {
                      list.Add(1050039, "{0}\t#{1}", m_Amount, LabelNumber); // ~1_NUMBER~ ~2_ITEMNAME~
                  }
              }
              else
              {
                  if (m_Amount <= 1)
                  {
                      list.Add(name);
                  }
                  else
                  {
                      list.Add(1050039, "{0}\t{1}", m_Amount, Name); // ~1_NUMBER~ ~2_ITEMNAME~
                  }
              }
          }
  
          /// <summary>
          ///     Overridable. Adds the loot type of this item to the given <see cref="ObjectPropertyList" />. By default, this will be either 'blessed', 'cursed', or 'insured'.
          /// </summary>
          public virtual void AddLootTypeProperty(ObjectPropertyList list)
          {
              if (DisplayLootType)
              {               
                  if (m_LootType == LootType.Blessed)
                  {
                      list.Add(1038021); // blessed
                  }
                  else if (m_LootType == LootType.Cursed)
                  {
                      list.Add(1049643); // cursed
                  }
                  else if (Insured)
                  {
                      list.Add(1061682); // <b>insured</b>
                  }
              }
          }
  
          /// <summary>
          ///     Overridable. Adds any elemental resistances of this item to the given <see cref="ObjectPropertyList" />.
          /// </summary>
          public virtual void AddResistanceProperties(ObjectPropertyList list)
          {
              int v = PhysicalResistance;
  
              if (v != 0)
              {
                  list.Add(1060448, v.ToString()); // physical resist ~1_val~%
              }
  
              v = FireResistance;
  
              if (v != 0)
              {
                  list.Add(1060447, v.ToString()); // fire resist ~1_val~%
              }
  
              v = ColdResistance;
  
              if (v != 0)
              {
                  list.Add(1060445, v.ToString()); // cold resist ~1_val~%
              }
  
              v = PoisonResistance;
  
              if (v != 0)
              {
                  list.Add(1060449, v.ToString()); // poison resist ~1_val~%
              }
  
              v = EnergyResistance;
  
              if (v != 0)
              {
                  list.Add(1060446, v.ToString()); // energy resist ~1_val~%
              }
          }
  
          /// <summary>
          ///     Overridable. Determines whether the item will show <see cref="AddWeightProperty" />.
          /// </summary>
          public virtual bool DisplayWeight
          {
              get
              {
                  if (!Core.ML)
                  {
                      return false;
                  }
  
                  if (!Movable && !(IsLockedDown || IsSecure) && ItemData.Weight == 255)
                  {
                      return false;
                  }
  
                  return true;
              }
          }
  
          /// <summary>
          ///     Overridable. Adds header properties. By default, this invokes <see cref="AddNameProperty" />,
          ///     <see
          ///         cref="AddBlessedForProperty" />
          ///     (if applicable), and <see cref="AddLootTypeProperty" /> (if
          ///     <see
          ///         cref="DisplayLootType" />
          ///     ).
          /// </summary>
          public virtual void AddNameProperties(ObjectPropertyList list)
          {
              AddNameProperty(list);
  
              if (IsSecure)
              {
                  AddSecureProperty(list);
              }
              else if (IsLockedDown)
              {
                  AddLockedDownProperty(list);
              }
  
              AddCraftedProperties(list);
              AddLootTypeProperty(list);
              AddUsesRemainingProperties(list);
              AddWeightProperty(list);
  
              AppendChildNameProperties(list);
  
              if (QuestItem)
              {
                  AddQuestItemProperty(list);
              }
          }
  
          /// <summary>
          /// Overrideable, used to add crafted by, excpetional, etc properties to items
          /// </summary>
          /// <param name="list"></param>
          public virtual void AddCraftedProperties(ObjectPropertyList list)
          {
          }
  
          /// <summary>
          /// Overrideable, used for IUsesRemaining UsesRemaining property
          /// </summary>
          /// <param name="list"></param>
          public virtual void AddUsesRemainingProperties(ObjectPropertyList list)
          {
          }
  
          /// <summary>
          ///     Overridable. Displays cliloc 1072788-1072789.
          /// </summary>
          public virtual void AddWeightProperty(ObjectPropertyList list)
          {
              if (DisplayWeight && Weight > 0)
              {
                  int weight = PileWeight + TotalWeight;
  
                  if (weight == 1)
                  {
                      list.Add(1072788, weight.ToString()); //Weight: ~1_WEIGHT~ stone
                  }
                  else
                  {
                      list.Add(1072789, weight.ToString()); //Weight: ~1_WEIGHT~ stones
                  }
              }
          }
  
          /// <summary>
          ///     Overridable. Adds the "Quest Item" property to the given <see cref="ObjectPropertyList" />.
          /// </summary>
          public virtual void AddQuestItemProperty(ObjectPropertyList list)
          {
              list.Add(1072351); // Quest Item
          }
  
          /// <summary>
          ///     Overridable. Adds the "Locked Down & Secure" property to the given <see cref="ObjectPropertyList" />.
          /// </summary>
          public virtual void AddSecureProperty(ObjectPropertyList list)
          {
              list.Add(501644); // locked down & secure
          }
  
          /// <summary>
          ///     Overridable. Adds the "Locked Down" property to the given <see cref="ObjectPropertyList" />.
          /// </summary>
          public virtual void AddLockedDownProperty(ObjectPropertyList list)
          {
              list.Add(501643); // locked down
          }
  
          /// <summary>
          ///     Overridable. Adds the "Blessed for ~1_NAME~" property to the given <see cref="ObjectPropertyList" />.
          /// </summary>
          public virtual void AddBlessedForProperty(ObjectPropertyList list, Mobile m)
          {
              list.Add(1062203, "{0}", m.Name); // Blessed for ~1_NAME~
          }
  
          public virtual void AddItemSocketProperties(ObjectPropertyList list)
          {
              if (Sockets != null)
              {
                  foreach (var socket in Sockets)
                  {
                      socket.GetProperties(list);
                  }
              }
          }
  
          public virtual void AddItemPowerProperties(ObjectPropertyList list)
          {
          }
  
          /// <summary>
          ///     Overridable. Fills an <see cref="ObjectPropertyList" /> with everything applicable. By default, this invokes
          ///     <see
          ///         cref="AddNameProperties" />
          ///     , then <see cref="Item.GetChildProperties">Item.GetChildProperties</see> or
          ///     <see
          ///         cref="Mobile.GetChildProperties">
          ///         Mobile.GetChildProperties
          ///     </see>
          ///     . This method should be overriden to add any custom properties.
          /// </summary>
          public virtual void GetProperties(ObjectPropertyList list)
          {
              AddNameProperties(list);
  
              AddItemSocketProperties(list);
  
              if (Spawner != null)
              {
                  Spawner.GetSpawnProperties(this, list);
              }
  
              AddItemPowerProperties(list);
          }
  
          /// <summary>
          ///     Overridable. Event invoked when a child (<paramref name="item" />) is building it's <see cref="ObjectPropertyList" />. Recursively calls
          ///     <see
          ///         cref="Item.GetChildProperties">
          ///         Item.GetChildProperties
          ///     </see>
          ///     or <see cref="Mobile.GetChildProperties">Mobile.GetChildProperties</see>.
          /// </summary>
          public virtual void GetChildProperties(ObjectPropertyList list, Item item)
          {
              if (m_Parent is Item)
              {
                  ((Item)m_Parent).GetChildProperties(list, item);
              }
              else if (m_Parent is Mobile)
              {
                  ((Mobile)m_Parent).GetChildProperties(list, item);
              }
          }
  
          /// <summary>
          ///     Overridable. Event invoked when a child (<paramref name="item" />) is building it's Name
          ///     <see
          ///         cref="ObjectPropertyList" />
          ///     . Recursively calls <see cref="Item.GetChildProperties">Item.GetChildNameProperties</see> or
          ///     <see
          ///         cref="Mobile.GetChildProperties">
          ///         Mobile.GetChildNameProperties
          ///     </see>
          ///     .
          /// </summary>
          public virtual void GetChildNameProperties(ObjectPropertyList list, Item item)
          {
              if (m_Parent is Item)
              {
                  ((Item)m_Parent).GetChildNameProperties(list, item);
              }
              else if (m_Parent is Mobile)
              {
                  ((Mobile)m_Parent).GetChildNameProperties(list, item);
              }
          }
  
          public virtual bool IsChildVisibleTo(Mobile m, Item child)
          {
              return true;
          }
  
          public void Bounce(Mobile from)
          {
              if (m_Parent is Item)
              {
                  ((Item)m_Parent).RemoveItem(this);
              }
              else if (m_Parent is Mobile)
              {
                  ((Mobile)m_Parent).RemoveItem(this);
              }
  
              m_Parent = null;
  
              BounceInfo bounce = GetBounce();
  
              if (bounce != null)
              {
                  var stack = bounce.m_ParentStack;
  
                  if (stack is Item)
                  {
                      var s = (Item)stack;
  
                      if (!s.Deleted)
                      {
                          if (s.IsAccessibleTo(from))
                          {
                              s.StackWith(from, this);
                          }
                      }
                  }
  
                  var parent = bounce.m_Parent;
  
                  if (parent is Item && !((Item)parent).Deleted)
                  {
                      Item p = (Item)parent;
                      var root = p.RootParent;
  
                      if (p.IsAccessibleTo(from) && (!(root is Mobile) || ((Mobile)root).CheckNonlocalDrop(from, this, p)))
                      {
                          Location = bounce.m_Location;
  
                          p.AddItem(this);
                      }
                      else
                      {
                          MoveToWorld(from.Location, from.Map);
                      }
                  }
                  else if (parent is Mobile && !((Mobile)parent).Deleted)
                  {
                      if (!((Mobile)parent).EquipItem(this))
                      {
                          MoveToWorld(bounce.m_WorldLoc, bounce.m_Map);
                      }
                  }
                  else
                  {
                      MoveToWorld(bounce.m_WorldLoc, bounce.m_Map);
                  }
  
                  ClearBounce();
              }
              else
              {
                  MoveToWorld(from.Location, from.Map);
              }
          }
  
          /// <summary>
          ///     Overridable. Method checked to see if this item may be equiped while casting a spell. By default, this returns false. It is overriden on spellbook and spell channeling weapons or shields.
          /// </summary>
          /// <returns>True if it may, false if not.</returns>
          /// <example>
          ///     <code>
          /// 	public override bool AllowEquipedCast( Mobile from )
          /// 	{
          /// 		if ( from.Int &gt;= 100 )
          /// 			return true;
          /// 		
          /// 		return base.AllowEquipedCast( from );
          ///  }</code>
          ///     When placed in an Item script, the item may be cast when equiped if the <paramref name="from" /> has 100 or more intelligence. Otherwise, it will drop to their backpack.
          /// </example>
          public virtual bool AllowEquipedCast(Mobile from)
          {
              return false;
          }
  
          public virtual bool CheckConflictingLayer(Mobile m, Item item, Layer layer)
          {
              return (m_Layer == layer);
          }
  
          public virtual bool CanEquip(Mobile m)
          {
              return m_Layer != Layer.Invalid && m.FindItemOnLayer(m_Layer) == null && CheckEquip(m, true);
          }
  
          public virtual bool CheckEquip(Mobile m, bool message)
          {
              if (m == null || m.Deleted)
              {
                  return false;
              }
  
              if (this == m.Mount || this == m.Backpack || this == m.FindBankNoCreate())
              {
                  return true;
              }
  
              var e = new CheckEquipItemEventArgs(m, this, message);
  
              EventSink.InvokeCheckEquipItem(e);
  
              if (e.Item != this || e.Item.Deleted || e.Block)
              {
                  return false;
              }
  
              if (m.AccessLevel < AccessLevel.GameMaster && BlessedFor != null && BlessedFor != m)
              {
                  if (message)
                  {
                      m.SendMessage("You do not own that item.");
                  }
  
                  return false;
              }
  
              return true;
          }
  
          public virtual void GetChildContextMenuEntries(Mobile from, List<ContextMenuEntry> list, Item item)
          {
              if (m_Parent is Item)
              {
                  ((Item)m_Parent).GetChildContextMenuEntries(from, list, item);
              }
              else if (m_Parent is Mobile)
              {
                  ((Mobile)m_Parent).GetChildContextMenuEntries(from, list, item);
              }
          }
  
          public virtual void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
          {
              if (m_Parent is Item)
              {
                  ((Item)m_Parent).GetChildContextMenuEntries(from, list, this);
              }
              else if (m_Parent is Mobile)
              {
                  ((Mobile)m_Parent).GetChildContextMenuEntries(from, list, this);
              }
  
              if (from.Region != null)
              {
                  from.Region.GetContextMenuEntries(from, list, this);
              }
  
              if (Spawner != null)
              {
                  Spawner.GetSpawnContextEntries(this, from, list);
              }
          }
  
          public virtual bool DisplayContextMenu(Mobile from)
          {
              return ContextMenu.Display(from, this);
          }
  
          public virtual bool VerifyMove(Mobile from)
          {
              return Movable;
          }
  
          public virtual void OnParentKill(Mobile target, Container corpse)
          { }
  
          public virtual DeathMoveResult OnParentDeath(Mobile parent)
          {
              if (!Movable)
              {
                  return DeathMoveResult.RemainEquiped;
              }
              else if (parent.KeepsItemsOnDeath)
              {
                  return DeathMoveResult.MoveToBackpack;
              }
              else if (CheckBlessed(parent))
              {
                  return DeathMoveResult.MoveToBackpack;
              }
              else if (CheckNewbied() && parent.Kills < 5)
              {
                  return DeathMoveResult.MoveToBackpack;
              }
              else if (parent.Player && Nontransferable)
              {
                  return DeathMoveResult.MoveToBackpack;
              }
              else
              {
                  return DeathMoveResult.MoveToCorpse;
              }
          }
  
          public virtual DeathMoveResult OnInventoryDeath(Mobile parent)
          {
              if (!Movable)
              {
                  return DeathMoveResult.MoveToBackpack;
              }
              else if (parent.KeepsItemsOnDeath)
              {
                  return DeathMoveResult.MoveToBackpack;
              }
              else if (CheckBlessed(parent))
              {
                  return DeathMoveResult.MoveToBackpack;
              }
              else if (CheckNewbied() && parent.Kills < 5)
              {
                  return DeathMoveResult.MoveToBackpack;
              }
              else if (parent.Player && Nontransferable)
              {
                  return DeathMoveResult.MoveToBackpack;
              }
              else
              {
                  return DeathMoveResult.MoveToCorpse;
              }
          }
  
          /// <summary>
          ///     Moves the Item to <paramref name="location" />. The Item does not change maps.
          /// </summary>
          public virtual void MoveToWorld(Point3D location)
          {
              MoveToWorld(location, m_Map);
          }
  
          public void LabelTo(Mobile to, int number)
          {
              to.Send(new MessageLocalized(m_Serial, m_ItemID, MessageType.Label, 0x3B2, 3, number, "", ""));
          }
  
          public void LabelTo(Mobile to, int number, string args)
          {
              to.Send(new MessageLocalized(m_Serial, m_ItemID, MessageType.Label, 0x3B2, 3, number, "", args));
          }
  
          public void LabelTo(Mobile to, string text)
          {
              to.Send(new UnicodeMessage(m_Serial, m_ItemID, MessageType.Label, 0x3B2, 3, "ENU", "", text));
          }
  
          public void LabelTo(Mobile to, string format, params object[] args)
          {
              LabelTo(to, String.Format(format, args));
          }
  
          public void LabelToAffix(Mobile to, int number, AffixType type, string affix)
          {
              to.Send(new MessageLocalizedAffix(m_Serial, m_ItemID, MessageType.Label, 0x3B2, 3, number, "", type, affix, ""));
          }
  
          public void LabelToAffix(Mobile to, int number, AffixType type, string affix, string args)
          {
              to.Send(new MessageLocalizedAffix(m_Serial, m_ItemID, MessageType.Label, 0x3B2, 3, number, "", type, affix, args));
          }
  
          public virtual void LabelLootTypeTo(Mobile to)
          {
              if (m_LootType == LootType.Blessed)
              {
                  LabelTo(to, 1041362); // (blessed)
              }
              else if (m_LootType == LootType.Cursed)
              {
                  LabelTo(to, "(cursed)");
              }
          }
  
          public bool AtWorldPoint(int x, int y)
          {
              return (m_Parent == null && m_Location.m_X == x && m_Location.m_Y == y);
          }
  
          public bool AtPoint(int x, int y)
          {
              return (m_Location.m_X == x && m_Location.m_Y == y);
          }
  
          /// <summary>
          ///     Moves the Item to a given <paramref name="location" /> and <paramref name="map" />.
          /// </summary>
          public void MoveToWorld(Point3D location, Map map)
          {
              if (Deleted)
              {
                  return;
              }
  
              Point3D oldLocation = GetWorldLocation();
              Point3D oldRealLocation = m_Location;
  
              SetLastMoved();
  
              if (Parent is Mobile)
              {
                  ((Mobile)Parent).RemoveItem(this);
              }
              else if (Parent is Item)
              {
                  ((Item)Parent).RemoveItem(this);
              }
  
              if (m_Map != map)
              {
                  Map old = m_Map;
  
                  if (m_Map != null)
                  {
                      m_Map.OnLeave(this);
  
                      if (oldLocation.m_X != 0)
                      {
                          var eable = m_Map.GetClientsInRange(oldLocation, Core.GlobalRadarRange - 4);
  
                          foreach (NetState state in eable)
                          {
                              Mobile m = state.Mobile;
  
                              if (Utility.InRange(oldLocation, m.Location, GetUpdateRange(m)))
                              {
                                  state.Send(RemovePacket);
                              }
                          }
  
                          eable.Free();
                      }
                  }
  
                  m_Location = location;
                  OnLocationChange(oldRealLocation);
  
                  ReleaseWorldPackets();
  
                  var items = LookupItems();
  
                  if (items != null)
                  {
                      for (int i = 0; i < items.Count; ++i)
                      {
                          items[i].Map = map;
                      }
                  }
  
                  m_Map = map;
  
                  if (m_Map != null)
                  {
                      m_Map.OnEnter(this);
                  }
  
                  OnMapChange();
  
                  if (m_Map != null)
                  {
                      var eable = m_Map.GetClientsInRange(m_Location, Core.GlobalRadarRange);
  
                      foreach (NetState state in eable)
                      {
                          Mobile m = state.Mobile;
  
                          if (m.CanSee(this) && Utility.InRange(m_Location, m.Location, GetUpdateRange(m)))
                          {
                              SendInfoTo(state);
                          }
                      }
  
                      eable.Free();
                  }
  
                  RemDelta(ItemDelta.Update);
  
                  if (old == null || old == Map.Internal)
                  {
                      InvalidateProperties();
                  }
              }
              else if (m_Map != null)
              {
                  IPooledEnumerable<NetState> eable;
  
                  if (oldLocation.m_X != 0)
                  {
                      eable = m_Map.GetClientsInRange(oldLocation, Core.GlobalMaxUpdateRange);
  
                      foreach (NetState state in eable)
                      {
                          Mobile m = state.Mobile;
  
                          if (!m.InUpdateRange(location))
                          {
                              state.Send(RemovePacket);
                          }
                      }
  
                      eable.Free();
                  }
  
                  Point3D oldInternalLocation = m_Location;
  
                  m_Location = location;
                  OnLocationChange(oldRealLocation);
  
                  ReleaseWorldPackets();
  
                  eable = m_Map.GetClientsInRange(m_Location, Core.GlobalMaxUpdateRange);
  
                  foreach (NetState state in eable)
                  {
                      Mobile m = state.Mobile;
  
                      if (m.CanSee(this) && m.InUpdateRange(m_Location))
                      {
                          SendInfoTo(state);
                      }
                  }
  
                  eable.Free();
  
                  m_Map.OnMove(oldInternalLocation, this);
  
                  RemDelta(ItemDelta.Update);
              }
              else
              {
                  Map = map;
                  Location = location;
              }
          }
  
          [CommandProperty(AccessLevel.GameMaster)]
          public bool HonestyItem { get; set; }
  
          /// <summary>
          ///     Has the item been deleted?
          /// </summary>
          public bool Deleted { get { return GetFlag(ImplFlag.Deleted); } }
  
          [CommandProperty(AccessLevel.GameMaster)]
          public LootType LootType
          {
              get { return m_LootType; }
              set
              {
                  if (m_LootType != value)
                  {
                      m_LootType = value;
  
                      if (DisplayLootType)
                      {
                          InvalidateProperties();
                      }
                  }
              }
          }
  
          /// <summary>
          ///		If true the item should be considered an artifact
          /// </summary>
          [CommandProperty(AccessLevel.GameMaster)]
          public virtual bool IsArtifact
          {
              get { return this is IArtifact && ((IArtifact)this).ArtifactRarity > 0; }
          }
  
          private static TimeSpan m_DDT = TimeSpan.FromMinutes(Config.Get("General.DefaultItemDecayTime", 60));
  
          public static TimeSpan DefaultDecayTime { get { return m_DDT; } set { m_DDT = value; } }
  
          [CommandProperty(AccessLevel.GameMaster)]
          public virtual int DecayMultiplier { get { return 1; } }
  
          [CommandProperty(AccessLevel.GameMaster)]
          public virtual bool DefaultDecaySetting { get { return true; } }
  
          [CommandProperty(AccessLevel.Decorator)]
          public virtual TimeSpan DecayTime { get { return TimeSpan.FromMinutes(m_DDT.TotalMinutes * DecayMultiplier); } }
  
          [CommandProperty(AccessLevel.Decorator)]
          public virtual bool Decays
          {
              get
              {
                  // TODO: Make item decay an option on the spawner
                  return DefaultDecaySetting && Movable && Visible && !HonestyItem/* && Spawner == null*/;
              }
          }
  
          [CommandProperty(AccessLevel.GameMaster)]
          public TimeSpan TimeToDecay
          {
              get
              {
                  return TimeSpan.FromMinutes((DecayTime - (DateTime.UtcNow - LastMoved)).TotalMinutes);
              }
          }
  
          public virtual bool OnDecay()
          {
              return (Decays && Parent == null && Map != Map.Internal && Region.Find(Location, Map).OnDecay(this));
          }
  
          public void SetLastMoved()
          {
              m_LastMovedTime = DateTime.UtcNow;
          }
  
          public DateTime LastMoved { get { return m_LastMovedTime; } set { m_LastMovedTime = value; } }
  
          public virtual bool StackIgnoreItemID { get { return false; } }
          public virtual bool StackIgnoreHue { get { return false; } }
          public virtual bool StackIgnoreName { get { return false; } }
  
          public bool StackWith(Mobile from, Item dropped)
          {
              return StackWith(from, dropped, true);
          }
  
          public virtual bool StackWith(Mobile from, Item dropped, bool playSound)
          {
              if (WillStack(from, dropped))
              {
                  if (m_LootType != dropped.m_LootType)
                  {
                      m_LootType = LootType.Regular;
                  }
  
                  Amount += dropped.Amount;
                  dropped.Delete();
  
                  if (playSound && from != null)
                  {
                      int soundID = GetDropSound();
  
                      if (soundID == -1)
                      {
                          soundID = 0x42;
                      }
  
                      from.SendSound(soundID, GetWorldLocation());
                  }
  
                  return true;
              }
  
              return false;
          }
  
          public virtual bool WillStack(Mobile from, Item item)
          {
              if (item == this || item.GetType() != GetType())
              {
                  return false;
              }
  
              if (!item.Stackable || !Stackable)
              {
                  return false;
              }
  
              if (item.Nontransferable || Nontransferable)
              {
                  return false;
              }
  
              if ((!item.StackIgnoreItemID || !StackIgnoreItemID) && item.ItemID != ItemID)
              {
                  return false;
              }
  
              if ((!item.StackIgnoreHue || !StackIgnoreHue) && item.Hue != Hue)
              {
                  return false;
              }
  
              if ((!item.StackIgnoreName || !StackIgnoreName) && item.Name != Name)
              {
                  return false;
              }
  
              if (item.Amount + Amount > 60000)
              {
                  return false;
              }
  
              if ((Sockets == null && item.Sockets != null) || (Sockets != null && item.Sockets == null))
              {
                  return false;
              }
              else  if (Sockets != null && item.Sockets != null)
              {
                  if (Sockets.Any(s => !item.HasSocket(s.GetType())))
                  {
                      return false;
                  }
  
                  if (item.Sockets.Any(s => !HasSocket(s.GetType())))
                  {
                      return false;
                  }
              }
  
              return true;
          }
  
          public virtual bool OnDragDrop(Mobile from, Item dropped)
          {
              if (Parent is Container)
              {
                  return ((Container)Parent).OnStackAttempt(from, this, dropped);
              }
  
              return StackWith(from, dropped);
          }
  
          public Rectangle2D GetGraphicBounds()
          {
              int itemID = m_ItemID;
              bool doubled = m_Amount > 1;
  
              if (itemID >= 0xEEA && itemID <= 0xEF2) // Are we coins?
              {
                  int coinBase = (itemID - 0xEEA) / 3;
                  coinBase *= 3;
                  coinBase += 0xEEA;
  
                  doubled = false;
  
                  if (m_Amount <= 1)
                  {
                      // A single coin
                      itemID = coinBase;
                  }
                  else if (m_Amount <= 5)
                  {
                      // A stack of coins
                      itemID = coinBase + 1;
                  }
                  else // m_Amount > 5
                  {
                      // A pile of coins
                      itemID = coinBase + 2;
                  }
              }
  
              Rectangle2D bounds = ItemBounds.Table[itemID & 0x3FFF];
  
              if (doubled)
              {
                  bounds.Set(bounds.X, bounds.Y, bounds.Width + 5, bounds.Height + 5);
              }
  
              return bounds;
          }
  
          [CommandProperty(AccessLevel.Decorator)]
          public bool Stackable { get { return GetFlag(ImplFlag.Stackable); } set { SetFlag(ImplFlag.Stackable, value); } }
  
          private readonly object _rpl = new object();
  
          public Packet RemovePacket
          {
              get
              {
                  if (m_RemovePacket == null)
                  {
                      lock (_rpl)
                      {
                          if (m_RemovePacket == null)
                          {
                              m_RemovePacket = new RemoveItem(this);
                              m_RemovePacket.SetStatic();
                          }
                      }
                  }
  
                  return m_RemovePacket;
              }
          }
  
          private readonly object _opll = new object();
  
          public Packet OPLPacket
          {
              get
              {
                  if (m_OPLPacket == null)
                  {
                      lock (_opll)
                      {
                          if (m_OPLPacket == null)
                          {
                              m_OPLPacket = new OPLInfo(PropertyList);
                              m_OPLPacket.SetStatic();
                          }
                      }
                  }
  
                  return m_OPLPacket;
              }
          }
  
          public ObjectPropertyList PropertyList
          {
              get
              {
                  if (m_PropertyList == null)
                  {
                      m_PropertyList = new ObjectPropertyList(this);
  
                      GetProperties(m_PropertyList);
                      AppendChildProperties(m_PropertyList);
  
                      m_PropertyList.Terminate();
                      m_PropertyList.SetStatic();
                  }
  
                  return m_PropertyList;
              }
          }
  
          public virtual void AppendChildProperties(ObjectPropertyList list)
          {
              if (m_Parent is Item)
              {
                  ((Item)m_Parent).GetChildProperties(list, this);
              }
              else if (m_Parent is Mobile)
              {
                  ((Mobile)m_Parent).GetChildProperties(list, this);
              }
          }
  
          public virtual void AppendChildNameProperties(ObjectPropertyList list)
          {
              if (m_Parent is Item)
              {
                  ((Item)m_Parent).GetChildNameProperties(list, this);
              }
              else if (m_Parent is Mobile)
              {
                  ((Mobile)m_Parent).GetChildNameProperties(list, this);
              }
          }
  
          public void ClearProperties()
          {
              Packet.Release(ref m_PropertyList);
              Packet.Release(ref m_OPLPacket);
          }
  
          public void InvalidateProperties()
          {
              if (!ObjectPropertyList.Enabled)
              {
                  return;
              }
  
              if (m_Map != null && m_Map != Map.Internal && !World.Loading)
              {
                  ObjectPropertyList oldList = m_PropertyList;
                  m_PropertyList = null;
                  ObjectPropertyList newList = PropertyList;
  
                  if (oldList == null || oldList.Hash != newList.Hash)
                  {
                      Packet.Release(ref m_OPLPacket);
                      Delta(ItemDelta.Properties);
                  }
              }
              else
              {
                  ClearProperties();
              }
          }
  
          private readonly object _wpl = new object();
          private readonly object _wplsa = new object();
          private readonly object _wplhs = new object();
  
          public Packet WorldPacket
          {
              get
              {
                  // This needs to be invalidated when any of the following changes:
                  //  - ItemID
                  //  - Amount
                  //  - Location
                  //  - Hue
                  //  - Packet Flags
                  //  - Direction
  
                  if (m_WorldPacket == null)
                  {
                      lock (_wpl)
                      {
                          if (m_WorldPacket == null)
                          {
                              m_WorldPacket = new WorldItem(this);
                              m_WorldPacket.SetStatic();
                          }
                      }
                  }
  
                  return m_WorldPacket;
              }
          }
  
          public Packet WorldPacketSA
          {
              get
              {
                  // This needs to be invalidated when any of the following changes:
                  //  - ItemID
                  //  - Amount
                  //  - Location
                  //  - Hue
                  //  - Packet Flags
                  //  - Direction
  
                  if (m_WorldPacketSA == null)
                  {
                      lock (_wplsa)
                      {
                          if (m_WorldPacketSA == null)
                          {
                              m_WorldPacketSA = new WorldItemSA(this);
                              m_WorldPacketSA.SetStatic();
                          }
                      }
                  }
  
                  return m_WorldPacketSA;
              }
          }
  
          public virtual Packet WorldPacketHS
          {
              get
              {
                  // This needs to be invalidated when any of the following changes:
                  //  - ItemID
                  //  - Amount
                  //  - Location
                  //  - Hue
                  //  - Packet Flags
                  //  - Direction
  
                  if (m_WorldPacketHS == null)
                  {
                      lock (_wplhs)
                      {
                          if (m_WorldPacketHS == null)
                          {
                              m_WorldPacketHS = new WorldItemHS(this);
                              m_WorldPacketHS.SetStatic();
                          }
                      }
                  }
  
                  return m_WorldPacketHS;
              }
          }
  
          public virtual void ReleaseWorldPackets()
          {
              Packet.Release(ref m_WorldPacket);
              Packet.Release(ref m_WorldPacketSA);
              Packet.Release(ref m_WorldPacketHS);
          }
  
          [CommandProperty(AccessLevel.Decorator)]
          public bool Visible
          {
              get { return GetFlag(ImplFlag.Visible); }
              set
              {
                  if (GetFlag(ImplFlag.Visible) != value)
                  {
                      SetFlag(ImplFlag.Visible, value);
                      ReleaseWorldPackets();
  
                      if (m_Map != null && m_Map != Map.Internal)
                      {
                          Point3D worldLoc = GetWorldLocation();
  
                          var eable = m_Map.GetClientsInRange(worldLoc, Core.GlobalMaxUpdateRange);
  
                          foreach (NetState state in eable)
                          {
                              Mobile m = state.Mobile;
  
                              if (!m.CanSee(this) && m.InRange(worldLoc, GetUpdateRange(m)))
                              {
                                  state.Send(RemovePacket);
                              }
                          }
  
                          eable.Free();
                      }
  
                      Delta(ItemDelta.Update);
                  }
              }
          }
  
          [CommandProperty(AccessLevel.Decorator)]
          public bool Movable
          {
              get { return GetFlag(ImplFlag.Movable); }
              set
              {
                  if (GetFlag(ImplFlag.Movable) != value)
                  {
                      SetFlag(ImplFlag.Movable, value);
                      ReleaseWorldPackets();
                      Delta(ItemDelta.Update);
                  }
              }
          }
  
          public virtual bool ForceShowProperties { get { return IsLockedDown || IsSecure; } }
  
          public virtual int GetPacketFlags()
          {
              int flags = 0;
  
              if (!Visible)
              {
                  flags |= 0x80;
              }
  
              if (Movable || ForceShowProperties)
              {
                  flags |= 0x20;
              }
  
              return flags;
          }
  
          public virtual bool OnMoveOff(Mobile m)
          {
              return true;
          }
  
          public virtual bool OnMoveOver(Mobile m)
          {
              return true;
          }
  
          public virtual bool HandlesOnMovement { get { return false; } }
  
          public virtual void OnMovement(Mobile m, Point3D oldLocation)
          { }
  
          public void Internalize()
          {
              MoveToWorld(Point3D.Zero, Map.Internal);
          }
  
          public virtual void OnMapChange()
          { }
  
          public virtual void OnRemoved(object parent)
          { }
  
          public virtual void OnAdded(object parent)
          { }
  
          [CommandProperty(AccessLevel.Counselor, AccessLevel.Decorator)]
          public Map Map
          {
              get { return m_Map; }
              set
              {
                  if (m_Map != value)
                  {
                      Map old = m_Map;
  
                      if (m_Map != null && m_Parent == null)
                      {
                          m_Map.OnLeave(this);
                          SendRemovePacket();
                      }
  
                      var items = LookupItems();
  
                      if (items != null)
                      {
                          for (int i = 0; i < items.Count; ++i)
                          {
                              items[i].Map = value;
                          }
                      }
  
                      m_Map = value;
  
                      if (m_Map != null && m_Parent == null)
                      {
                          m_Map.OnEnter(this);
                      }
  
                      Delta(ItemDelta.Update);
  
                      OnMapChange();
  
                      if (old == null || old == Map.Internal)
                      {
                          InvalidateProperties();
                      }
                  }
              }
          }
  
          [Flags]
          private enum SaveFlag
          {
              None = 0x00000000,
              Direction = 0x00000001,
              Bounce = 0x00000002,
              LootType = 0x00000004,
              LocationFull = 0x00000008,
              ItemID = 0x00000010,
              Hue = 0x00000020,
              Amount = 0x00000040,
              Layer = 0x00000080,
              Name = 0x00000100,
              Parent = 0x00000200,
              Items = 0x00000400,
              WeightNot1or0 = 0x00000800,
              Map = 0x00001000,
              Visible = 0x00002000,
              Movable = 0x00004000,
              Stackable = 0x00008000,
              WeightIs0 = 0x00010000,
              LocationSByteZ = 0x00020000,
              LocationShortXY = 0x00040000,
              LocationByteXY = 0x00080000,
              ImplFlags = 0x00100000,
              InsuredFor = 0x00200000,
              BlessedFor = 0x00400000,
              HeldBy = 0x00800000,
              IntWeight = 0x01000000,
              SavedFlags = 0x02000000,
              NullWeight = 0x04000000,
              Light = 0x08000000
          }
  
          private static void SetSaveFlag(ref SaveFlag flags, SaveFlag toSet, bool setIf)
          {
              if (setIf)
              {
                  flags |= toSet;
              }
          }
  
          private static bool GetSaveFlag(SaveFlag flags, SaveFlag toGet)
          {
              return ((flags & toGet) != 0);
          }
  
          int ISerializable.TypeReference { get { return m_TypeRef; } }
  
          int ISerializable.SerialIdentity { get { return m_Serial; } }
  
          public virtual void Serialize(GenericWriter writer)
          {
              writer.Write(14); // version
  
              // 14
              writer.Write(Sockets != null ? Sockets.Count : 0);
  			
  			if(Sockets != null)
  			{
  				foreach(var socket in Sockets)
  				{
  					ItemSocket.Save(socket, writer);
  				}
  			}
  
  			// 13: Merge sync
              // 12: Light no longer backed by Direction
  
              // 11
              writer.Write(m_GridLocation);
  
              // 10: Honesty moved to ItemSockets
  
              // 9
              SaveFlag flags = SaveFlag.None;
  
              int x = m_Location.m_X, y = m_Location.m_Y, z = m_Location.m_Z;
  
              if (x != 0 || y != 0 || z != 0)
              {
                  if (x >= short.MinValue && x <= short.MaxValue && y >= short.MinValue && y <= short.MaxValue && z >= sbyte.MinValue &&
                      z <= sbyte.MaxValue)
                  {
                      if (x != 0 || y != 0)
                      {
                          if (x >= byte.MinValue && x <= byte.MaxValue && y >= byte.MinValue && y <= byte.MaxValue)
                          {
                              flags |= SaveFlag.LocationByteXY;
                          }
                          else
                          {
                              flags |= SaveFlag.LocationShortXY;
                          }
                      }
  
                      if (z != 0)
                      {
                          flags |= SaveFlag.LocationSByteZ;
                      }
                  }
                  else
                  {
                      flags |= SaveFlag.LocationFull;
                  }
              }
  
              var info = LookupCompactInfo();
              var items = LookupItems();
  
              if (m_Direction != Direction.North)
              {
                  flags |= SaveFlag.Direction;
              }
  
              if (m_Light != 0)
              {
                  flags |= SaveFlag.Light;
              }
  
              if (info != null && info.m_Bounce != null)
              {
                  flags |= SaveFlag.Bounce;
              }
  
              if (m_LootType != LootType.Regular)
              {
                  flags |= SaveFlag.LootType;
              }
  
              if (m_ItemID != 0)
              {
                  flags |= SaveFlag.ItemID;
              }
  
              if (m_Hue != 0)
              {
                  flags |= SaveFlag.Hue;
              }
  
              if (m_Amount != 1)
              {
                  flags |= SaveFlag.Amount;
              }
  
              if (m_Layer != Layer.Invalid)
              {
                  flags |= SaveFlag.Layer;
              }
  
              if (info != null && info.m_Name != null)
              {
                  flags |= SaveFlag.Name;
              }
  
              if (m_Parent != null)
              {
                  flags |= SaveFlag.Parent;
              }
  
              if (items != null && items.Count > 0)
              {
                  flags |= SaveFlag.Items;
              }
  
              if (m_Map != Map.Internal)
              {
                  flags |= SaveFlag.Map;
              }
  
              if (info != null && info.m_BlessedFor != null && !info.m_BlessedFor.Deleted)
              {
                  flags |= SaveFlag.BlessedFor;
              }
  
              if (info != null && info.m_HeldBy != null && !info.m_HeldBy.Deleted)
              {
                  flags |= SaveFlag.HeldBy;
              }
  
              if (info != null && info.m_SavedFlags != 0)
              {
                  flags |= SaveFlag.SavedFlags;
              }
  
              if (info == null || info.m_Weight == -1)
              {
                  flags |= SaveFlag.NullWeight;
              }
              else if (info.m_Weight == 0.0)
              {
                  flags |= SaveFlag.WeightIs0;
              }
              else if (info.m_Weight != 1.0)
              {
                  if (info.m_Weight == (int)info.m_Weight)
                  {
                      flags |= SaveFlag.IntWeight;
                  }
                  else
                  {
                      flags |= SaveFlag.WeightNot1or0;
                  }
              }
  
              var implFlags = (m_Flags & (ImplFlag.Visible | ImplFlag.Movable | ImplFlag.Stackable | ImplFlag.Insured |
                                          ImplFlag.PayedInsurance | ImplFlag.QuestItem));
  
              if (implFlags != (ImplFlag.Visible | ImplFlag.Movable))
              {
                  flags |= SaveFlag.ImplFlags;
              }
  
              writer.Write((int)flags);
  
              /* begin last moved time optimization */
              long ticks = m_LastMovedTime.Ticks;
              long now = DateTime.UtcNow.Ticks;
  
              TimeSpan d;
  
              try
              {
                  d = new TimeSpan(ticks - now);
              }
              catch
              {
                  if (ticks < now)
                  {
                      d = TimeSpan.MaxValue;
                  }
                  else
                  {
                      d = TimeSpan.MaxValue;
                  }
              }
  
              double minutes = -d.TotalMinutes;
  
              if (minutes < int.MinValue)
              {
                  minutes = int.MinValue;
              }
              else if (minutes > int.MaxValue)
              {
                  minutes = int.MaxValue;
              }
  
              writer.WriteEncodedInt((int)minutes);
              /* end */
  
              if (GetSaveFlag(flags, SaveFlag.Direction))
              {
                  writer.Write((byte)m_Direction);
              }
  
              if (GetSaveFlag(flags, SaveFlag.Light))
              {
                  writer.Write((byte)m_Light);
              }
  
              if (GetSaveFlag(flags, SaveFlag.Bounce))
              {
                  // ReSharper disable once PossibleNullReferenceException
                  BounceInfo.Serialize(info.m_Bounce, writer);
              }
  
              if (GetSaveFlag(flags, SaveFlag.LootType))
              {
                  writer.Write((byte)m_LootType);
              }
  
              if (GetSaveFlag(flags, SaveFlag.LocationFull))
              {
                  writer.WriteEncodedInt(x);
                  writer.WriteEncodedInt(y);
                  writer.WriteEncodedInt(z);
              }
              else
              {
                  if (GetSaveFlag(flags, SaveFlag.LocationByteXY))
                  {
                      writer.Write((byte)x);
                      writer.Write((byte)y);
                  }
                  else if (GetSaveFlag(flags, SaveFlag.LocationShortXY))
                  {
                      writer.Write((short)x);
                      writer.Write((short)y);
                  }
  
                  if (GetSaveFlag(flags, SaveFlag.LocationSByteZ))
                  {
                      writer.Write((sbyte)z);
                  }
              }
  
              if (GetSaveFlag(flags, SaveFlag.ItemID))
              {
                  writer.WriteEncodedInt(m_ItemID);
              }
  
              if (GetSaveFlag(flags, SaveFlag.Hue))
              {
                  writer.WriteEncodedInt(m_Hue);
              }
  
              if (GetSaveFlag(flags, SaveFlag.Amount))
              {
                  writer.WriteEncodedInt(m_Amount);
              }
  
              if (GetSaveFlag(flags, SaveFlag.Layer))
              {
                  writer.Write((byte)m_Layer);
              }
  
              if (GetSaveFlag(flags, SaveFlag.Name))
              {
                  writer.Write(info.m_Name);
              }
  
              if (GetSaveFlag(flags, SaveFlag.Parent))
              {
                  if (m_Parent is Mobile && !((Mobile)m_Parent).Deleted)
                  {
                      writer.Write(((Mobile)m_Parent).Serial);
                  }
                  else if (m_Parent is Item && !((Item)m_Parent).Deleted)
                  {
                      writer.Write(((Item)m_Parent).Serial);
                  }
                  else
                  {
                      writer.Write(Serial.MinusOne);
                  }
              }
  
              if (GetSaveFlag(flags, SaveFlag.Items))
              {
                  writer.Write(items, false);
              }
  
              if (GetSaveFlag(flags, SaveFlag.IntWeight))
              {
                  writer.WriteEncodedInt((int)info.m_Weight);
              }
              else if (GetSaveFlag(flags, SaveFlag.WeightNot1or0))
              {
                  writer.Write(info.m_Weight);
              }
  
              if (GetSaveFlag(flags, SaveFlag.Map))
              {
                  writer.Write(m_Map);
              }
  
              if (GetSaveFlag(flags, SaveFlag.ImplFlags))
              {
                  writer.WriteEncodedInt((int)implFlags);
              }
  
              if (GetSaveFlag(flags, SaveFlag.InsuredFor))
              {
                  writer.Write((Mobile)null);
              }
  
              if (GetSaveFlag(flags, SaveFlag.BlessedFor))
              {
                  writer.Write(info.m_BlessedFor);
              }
  
              if (GetSaveFlag(flags, SaveFlag.HeldBy))
              {
                  writer.Write(info.m_HeldBy);
              }
  
              if (GetSaveFlag(flags, SaveFlag.SavedFlags))
              {
                  writer.WriteEncodedInt(info.m_SavedFlags);
              }
          }
  
          public IPooledEnumerable<IEntity> GetObjectsInRange(int range)
          {
              Map map = m_Map;
  
              if (map == null)
              {
                  return Map.NullEnumerable<IEntity>.Instance;
              }
  
              if (m_Parent == null)
              {
                  return map.GetObjectsInRange(m_Location, range);
              }
  
              return map.GetObjectsInRange(GetWorldLocation(), range);
          }
  
          public IPooledEnumerable<Item> GetItemsInRange(int range)
          {
              Map map = m_Map;
  
              if (map == null)
              {
                  return Map.NullEnumerable<Item>.Instance;
              }
  
              if (m_Parent == null)
              {
                  return map.GetItemsInRange(m_Location, range);
              }
  
              return map.GetItemsInRange(GetWorldLocation(), range);
          }
  
          public IPooledEnumerable<Mobile> GetMobilesInRange(int range)
          {
              Map map = m_Map;
  
              if (map == null)
              {
                  return Map.NullEnumerable<Mobile>.Instance;
              }
  
              if (m_Parent == null)
              {
                  return map.GetMobilesInRange(m_Location, range);
              }
  
              return map.GetMobilesInRange(GetWorldLocation(), range);
          }
  
          public IPooledEnumerable<NetState> GetClientsInRange(int range)
          {
              Map map = m_Map;
  
              if (map == null)
              {
                  return Map.NullEnumerable<NetState>.Instance;
              }
  
              if (m_Parent == null)
              {
                  return map.GetClientsInRange(m_Location, range);
              }
  
              return map.GetClientsInRange(GetWorldLocation(), range);
          }
  
          private static int m_LockedDownFlag;
          private static int m_SecureFlag;
  
          public static int LockedDownFlag { get { return m_LockedDownFlag; } set { m_LockedDownFlag = value; } }
  
          public static int SecureFlag { get { return m_SecureFlag; } set { m_SecureFlag = value; } }
  
          public bool IsLockedDown
          {
              get { return GetTempFlag(m_LockedDownFlag); }
              set
              {
                  SetTempFlag(m_LockedDownFlag, value);
                  InvalidateProperties();
  
                  OnLockDownChange();
              }
          }
  
          public virtual void OnLockDownChange()
          {
          }
  
          public bool IsSecure
          {
              get { return GetTempFlag(m_SecureFlag); }
              set
              {
                  SetTempFlag(m_SecureFlag, value);
                  InvalidateProperties();
  
                  OnSecureChange();
              }
          }
  
          public virtual void OnSecureChange()
          {
          }
  
          public bool GetTempFlag(int flag)
          {
              CompactInfo info = LookupCompactInfo();
  
              if (info == null)
              {
                  return false;
              }
  
              return ((info.m_TempFlags & flag) != 0);
          }
  
          public void SetTempFlag(int flag, bool value)
          {
              CompactInfo info = AcquireCompactInfo();
  
              if (value)
              {
                  info.m_TempFlags |= flag;
              }
              else
              {
                  info.m_TempFlags &= ~flag;
              }
  
              if (info.m_TempFlags == 0)
              {
                  VerifyCompactInfo();
              }
          }
  
          public bool GetSavedFlag(int flag)
          {
              CompactInfo info = LookupCompactInfo();
  
              if (info == null)
              {
                  return false;
              }
  
              return ((info.m_SavedFlags & flag) != 0);
          }
  
          public void SetSavedFlag(int flag, bool value)
          {
              CompactInfo info = AcquireCompactInfo();
  
              if (value)
              {
                  info.m_SavedFlags |= flag;
              }
              else
              {
                  info.m_SavedFlags &= ~flag;
              }
  
              if (info.m_SavedFlags == 0)
              {
                  VerifyCompactInfo();
              }
          }
  
          public virtual void Deserialize(GenericReader reader)
          {
              int version = reader.ReadInt();
  
              SetLastMoved();
  
              switch (version)
              {
                  case 14:
                      var socketCount = reader.ReadInt();
  
                      for(int i = 0; i < socketCount; i++)
                      {
                          ItemSocket.Load(this, reader);
                      }
  
                      goto case 13;
  				case 13:
                  case 12:
                  case 11:
                      m_GridLocation = reader.ReadByte();
                      goto case 10;
                  case 10:
                      {
                          // Honesty removed to ItemSockets
                          if (version < 14)
                          {
                              reader.ReadDateTime();
                              reader.ReadBool();
                              reader.ReadMobile();
                              reader.ReadString();
  
                              HonestyItem = reader.ReadBool();
                          }
  
                          goto case 9;
                      }
                  case 9:
                  case 8:
                  case 7:
                  case 6:
                      {
                          SaveFlag flags = (SaveFlag)reader.ReadInt();
  
  
gt:                         if (version < 7)