diff --git a/Scripts/Engines/Quests/The Summoning/Mobiles/Chyloth.cs b/Scripts/Engines/Quests/The Summoning/Mobiles/Chyloth.cs index f258d48ec..ccd8d1598 100644 --- a/Scripts/Engines/Quests/The Summoning/Mobiles/Chyloth.cs +++ b/Scripts/Engines/Quests/The Summoning/Mobiles/Chyloth.cs @@ -177,21 +177,20 @@ namespace Server.Engines.Quests.Doom Party p = PartySystem.Party.Get(from); - if (p != null) - for (int i = 0; i < p.Members.Count; ++i) + for (int i = 0; i < p?.Members.Count; ++i) + { + PartyMemberInfo pmi = p.Members[i]; + Mobile member = pmi.Mobile; + + if (member != from && member.Map == Map.Malas && member.Region.IsPartOf("Doom")) { - PartyMemberInfo pmi = p.Members[i]; - Mobile member = pmi.Mobile; + if (AngryAt == member) + AngryAt = null; - if (member != from && member.Map == Map.Malas && member.Region.IsPartOf("Doom")) - { - if (AngryAt == member) - AngryAt = null; - - member.CloseGump(); - member.SendGump(new ChylothPartyGump(from, member)); - } + member.CloseGump(); + member.SendGump(new ChylothPartyGump(from, member)); } + } if (AngryAt == from) AngryAt = null; diff --git a/Scripts/Items/Special/House Raffle/HouseRaffleStone.cs b/Scripts/Items/Special/House Raffle/HouseRaffleStone.cs index b6c887fe1..ba20c1f90 100644 --- a/Scripts/Items/Special/House Raffle/HouseRaffleStone.cs +++ b/Scripts/Items/Special/House Raffle/HouseRaffleStone.cs @@ -16,10 +16,7 @@ namespace Server.Items { From = from; - if (From.NetState != null) - Address = From.NetState.Address; - else - Address = IPAddress.None; + Address = From.NetState?.Address ?? IPAddress.None; Date = DateTime.UtcNow; } @@ -367,9 +364,7 @@ namespace Server.Items public string FormatPrice() { - if (m_TicketPrice == 0) - return "FREE"; - return $"{m_TicketPrice} gold"; + return m_TicketPrice == 0 ? "FREE" : $"{m_TicketPrice} gold"; } public override void GetProperties(ObjectPropertyList list) diff --git a/Server/Item.cs b/Server/Item.cs index 272fb2361..42f40cfcb 100644 --- a/Server/Item.cs +++ b/Server/Item.cs @@ -31,177 +31,6 @@ using Server.Targeting; namespace Server { - /// - /// Enumeration of item layer values. - /// - public enum Layer : byte - { - /// - /// Invalid layer. - /// - Invalid = 0x00, - - /// - /// First valid layer. Equivalent to Layer.OneHanded. - /// - FirstValid = 0x01, - - /// - /// One handed weapon. - /// - OneHanded = 0x01, - - /// - /// Two handed weapon or shield. - /// - TwoHanded = 0x02, - - /// - /// Shoes. - /// - Shoes = 0x03, - - /// - /// Pants. - /// - Pants = 0x04, - - /// - /// Shirts. - /// - Shirt = 0x05, - - /// - /// Helmets, hats, and masks. - /// - Helm = 0x06, - - /// - /// Gloves. - /// - Gloves = 0x07, - - /// - /// Rings. - /// - Ring = 0x08, - - /// - /// Talismans. - /// - Talisman = 0x09, - - /// - /// Gorgets and necklaces. - /// - Neck = 0x0A, - - /// - /// Hair. - /// - Hair = 0x0B, - - /// - /// Half aprons. - /// - Waist = 0x0C, - - /// - /// Torso, inner layer. - /// - InnerTorso = 0x0D, - - /// - /// Bracelets. - /// - Bracelet = 0x0E, - - /// - /// Unused. - /// - Unused_xF = 0x0F, - - /// - /// Beards and mustaches. - /// - FacialHair = 0x10, - - /// - /// Torso, outer layer. - /// - MiddleTorso = 0x11, - - /// - /// Earings. - /// - Earrings = 0x12, - - /// - /// Arms and sleeves. - /// - Arms = 0x13, - - /// - /// Cloaks. - /// - Cloak = 0x14, - - /// - /// Backpacks. - /// - Backpack = 0x15, - - /// - /// Torso, outer layer. - /// - OuterTorso = 0x16, - - /// - /// Leggings, outer layer. - /// - OuterLegs = 0x17, - - /// - /// Leggings, inner layer. - /// - InnerLegs = 0x18, - - /// - /// Last valid non-internal layer. Equivalent to Layer.InnerLegs. - /// - LastUserValid = 0x18, - - /// - /// Mount item layer. - /// - Mount = 0x19, - - /// - /// Vendor 'buy pack' layer. - /// - ShopBuy = 0x1A, - - /// - /// Vendor 'resale pack' layer. - /// - ShopResale = 0x1B, - - /// - /// Vendor 'sell pack' layer. - /// - ShopSell = 0x1C, - - /// - /// Bank box layer. - /// - Bank = 0x1D, - - /// - /// Last valid layer. Equivalent to Layer.Bank. - /// - LastValid = 0x1D - } - /// /// Internal flags used to signal how the item should be updated and resent to nearby clients. /// @@ -250,295 +79,6 @@ namespace Server MoveToBackpack } - /// - /// Enumeration containing all possible light types. These are only applicable to light source items, like lanterns, candles, - /// braziers, etc. - /// - public enum LightType - { - /// - /// Window shape, arched, ray shining east. - /// - ArchedWindowEast, - - /// - /// Medium circular shape. - /// - Circle225, - - /// - /// Small circular shape. - /// - Circle150, - - /// - /// Door shape, shining south. - /// - DoorSouth, - - /// - /// Door shape, shining east. - /// - DoorEast, - - /// - /// Large semicircular shape (180 degrees), north wall. - /// - NorthBig, - - /// - /// Large pie shape (90 degrees), north-east corner. - /// - NorthEastBig, - - /// - /// Large semicircular shape (180 degrees), east wall. - /// - EastBig, - - /// - /// Large semicircular shape (180 degrees), west wall. - /// - WestBig, - - /// - /// Large pie shape (90 degrees), south-west corner. - /// - SouthWestBig, - - /// - /// Large semicircular shape (180 degrees), south wall. - /// - SouthBig, - - /// - /// Medium semicircular shape (180 degrees), north wall. - /// - NorthSmall, - - /// - /// Medium pie shape (90 degrees), north-east corner. - /// - NorthEastSmall, - - /// - /// Medium semicircular shape (180 degrees), east wall. - /// - EastSmall, - - /// - /// Medium semicircular shape (180 degrees), west wall. - /// - WestSmall, - - /// - /// Medium semicircular shape (180 degrees), south wall. - /// - SouthSmall, - - /// - /// Shaped like a wall decoration, north wall. - /// - DecorationNorth, - - /// - /// Shaped like a wall decoration, north-east corner. - /// - DecorationNorthEast, - - /// - /// Small semicircular shape (180 degrees), east wall. - /// - EastTiny, - - /// - /// Shaped like a wall decoration, west wall. - /// - DecorationWest, - - /// - /// Shaped like a wall decoration, south-west corner. - /// - DecorationSouthWest, - - /// - /// Small semicircular shape (180 degrees), south wall. - /// - SouthTiny, - - /// - /// Window shape, rectangular, no ray, shining south. - /// - RectWindowSouthNoRay, - - /// - /// Window shape, rectangular, no ray, shining east. - /// - RectWindowEastNoRay, - - /// - /// Window shape, rectangular, ray shining south. - /// - RectWindowSouth, - - /// - /// Window shape, rectangular, ray shining east. - /// - RectWindowEast, - - /// - /// Window shape, arched, no ray, shining south. - /// - ArchedWindowSouthNoRay, - - /// - /// Window shape, arched, no ray, shining east. - /// - ArchedWindowEastNoRay, - - /// - /// Window shape, arched, ray shining south. - /// - ArchedWindowSouth, - - /// - /// Large circular shape. - /// - Circle300, - - /// - /// Large pie shape (90 degrees), north-west corner. - /// - NorthWestBig, - - /// - /// Negative light. Medium pie shape (90 degrees), south-east corner. - /// - DarkSouthEast, - - /// - /// Negative light. Medium semicircular shape (180 degrees), south wall. - /// - DarkSouth, - - /// - /// Negative light. Medium pie shape (90 degrees), north-west corner. - /// - DarkNorthWest, - - /// - /// Negative light. Medium pie shape (90 degrees), south-east corner. Equivalent to LightType.SouthEast. - /// - DarkSouthEast2, - - /// - /// Negative light. Medium circular shape (180 degrees), east wall. - /// - DarkEast, - - /// - /// Negative light. Large circular shape. - /// - DarkCircle300, - - /// - /// Opened door shape, shining south. - /// - DoorOpenSouth, - - /// - /// Opened door shape, shining east. - /// - DoorOpenEast, - - /// - /// Window shape, square, ray shining east. - /// - SquareWindowEast, - - /// - /// Window shape, square, no ray, shining east. - /// - SquareWindowEastNoRay, - - /// - /// Window shape, square, ray shining south. - /// - SquareWindowSouth, - - /// - /// Window shape, square, no ray, shining south. - /// - SquareWindowSouthNoRay, - - /// - /// Empty. - /// - Empty, - - /// - /// Window shape, skinny, no ray, shining south. - /// - SkinnyWindowSouthNoRay, - - /// - /// Window shape, skinny, ray shining east. - /// - SkinnyWindowEast, - - /// - /// Window shape, skinny, no ray, shining east. - /// - SkinnyWindowEastNoRay, - - /// - /// Shaped like a hole, shining south. - /// - HoleSouth, - - /// - /// Shaped like a hole, shining south. - /// - HoleEast, - - /// - /// Large circular shape with a moongate graphic embeded. - /// - Moongate, - - /// - /// Unknown usage. Many rows of slightly angled lines. - /// - Strips, - - /// - /// Shaped like a small hole, shining south. - /// - SmallHoleSouth, - - /// - /// Shaped like a small hole, shining east. - /// - SmallHoleEast, - - /// - /// Large semicircular shape (180 degrees), north wall. Identical graphic as LightType.NorthBig, but slightly different - /// positioning. - /// - NorthBig2, - - /// - /// Large semicircular shape (180 degrees), west wall. Identical graphic as LightType.WestBig, but slightly different - /// positioning. - /// - WestBig2, - - /// - /// Large pie shape (90 degrees), north-west corner. Equivalent to LightType.NorthWestBig. - /// - NorthWestBig2 - } - /// /// Enumeration of an item's loot and steal state. /// @@ -659,7 +199,7 @@ namespace Server Spawner = 0x100 } - public class Item : IHued, IComparable, ISerializable, ISpawnable + public class Item : IHued, IComparable, ISerializable, ISpawnable, IPropertyListObject { public const int QuestItemHue = 0x4EA; // Hmmmm... "for EA"? public static readonly List EmptyItems = new List(); @@ -670,14 +210,6 @@ namespace Server private static int m_OpenSlots; - private object _opll = new object(); - - private object _rpl = new object(); - - private object _wpl = new object(); - private object _wplhs = new object(); - private object _wplsa = new object(); - private CompactInfo m_CompactInfo; private ItemDelta m_DeltaFlags; @@ -808,138 +340,20 @@ namespace Server set => SetFlag(ImplFlag.Stackable, value); } - public Packet RemovePacket - { - get - { - if (m_RemovePacket == null) - lock (_rpl) - { - if (m_RemovePacket == null) - { - m_RemovePacket = new RemoveItem(this); - m_RemovePacket.SetStatic(); - } - } + public Packet RemovePacket => StaticPacketHandlers.GetRemoveEntityPacket(this); + public OPLInfo OPLPacket => StaticPacketHandlers.GetOPLInfoPacket(this); + public ObjectPropertyList PropertyList => StaticPacketHandlers.GetOPLPacket(this); - return m_RemovePacket; - } - } - - 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 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 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; - } - } + // World packets need to be invalidated when any of the following changes: + // - ItemID + // - Amount + // - Location + // - Hue + // - Packet Flags + // - Direction + public Packet WorldPacket => StaticPacketHandlers.GetWorldItemPacket(this); + public Packet WorldPacketSA => StaticPacketHandlers.GetWorldItemSAPacket(this); + public Packet WorldPacketHS => StaticPacketHandlers.GetWorldItemHSPacket(this); [CommandProperty(AccessLevel.GameMaster)] public bool Visible @@ -1523,7 +937,7 @@ namespace Server } } - public void ProcessDelta() + public virtual void ProcessDelta() { ItemDelta flags = m_DeltaFlags; @@ -1532,220 +946,159 @@ namespace Server Map map = m_Map; - if (map != null && !Deleted) + if (map == null || Deleted) + return; + + Point3D worldLoc = GetWorldLocation(); + bool update = (flags & ItemDelta.Update) != 0; + + if (update && m_Parent is Container contParent && !contParent.IsPublicContainer) { - bool sendOPLUpdate = ObjectPropertyList.Enabled && (flags & ItemDelta.Properties) != 0; + Mobile rootParent = contParent.RootParent as Mobile; + Mobile tradeRecip = null; - if (m_Parent is Container contParent && !contParent.IsPublicContainer) - if ((flags & ItemDelta.Update) != 0) - { - Point3D worldLoc = GetWorldLocation(); - - Mobile rootParent = contParent.RootParent as Mobile; - Mobile tradeRecip = null; - - if (rootParent != null) - { - NetState ns = rootParent.NetState; - - if (ns != null) - if (rootParent.CanSee(this) && rootParent.InRange(worldLoc, GetUpdateRange(rootParent))) - { - if (ns.ContainerGridLines) - ns.Send(new ContainerContentUpdate6017(this)); - else - ns.Send(new ContainerContentUpdate(this)); - - if (ObjectPropertyList.Enabled) - ns.Send(OPLPacket); - } - } - - SecureTradeContainer stc = GetSecureTradeCont(); - - SecureTrade st = stc?.Trade; - - if (st != null) - { - Mobile test = st.From.Mobile; - - if (test != null && test != rootParent) - tradeRecip = test; - - test = st.To.Mobile; - - if (test != null && test != rootParent) - tradeRecip = test; - - NetState ns = tradeRecip?.NetState; - - if (ns != null) - if (tradeRecip.CanSee(this) && tradeRecip.InRange(worldLoc, GetUpdateRange(tradeRecip))) - { - if (ns.ContainerGridLines) - ns.Send(new ContainerContentUpdate6017(this)); - else - ns.Send(new ContainerContentUpdate(this)); - - if (ObjectPropertyList.Enabled) - ns.Send(OPLPacket); - } - } - - List openers = contParent.Openers; - - if (openers != null) - lock (openers) - { - for (int i = 0; i < openers.Count; ++i) - { - Mobile mob = openers[i]; - - int range = GetUpdateRange(mob); - - if (mob.Map != map || !mob.InRange(worldLoc, range)) - { - openers.RemoveAt(i--); - } - else - { - if (mob == rootParent || mob == tradeRecip) - continue; - - NetState ns = mob.NetState; - - if (ns != null) - if (mob.CanSee(this)) - { - if (ns.ContainerGridLines) - ns.Send(new ContainerContentUpdate6017(this)); - else - ns.Send(new ContainerContentUpdate(this)); - - if (ObjectPropertyList.Enabled) - ns.Send(OPLPacket); - } - } - } - - if (openers.Count == 0) - contParent.Openers = null; - } - - return; - } - - if ((flags & ItemDelta.Update) != 0) + if (rootParent != null) { - Packet p = null; - Point3D worldLoc = GetWorldLocation(); + NetState ns = rootParent.NetState; - IPooledEnumerable eable = map.GetClientsInRange(worldLoc, GetMaxUpdateRange()); - - foreach (NetState state in eable) - { - Mobile m = state.Mobile; - - if (m.CanSee(this) && m.InRange(worldLoc, GetUpdateRange(m))) + if (ns != null) + if (rootParent.CanSee(this) && rootParent.InRange(worldLoc, GetUpdateRange(rootParent))) { - if (m_Parent == null) + if (ns.ContainerGridLines) + ns.Send(new ContainerContentUpdate6017(this)); + else + ns.Send(new ContainerContentUpdate(this)); + + if (ObjectPropertyList.Enabled) + ns.Send(OPLPacket); + } + } + + SecureTrade st = GetSecureTradeCont()?.Trade; + + if (st != null) + { + Mobile test = st.From.Mobile; + + if (test != null && test != rootParent) + tradeRecip = test; + + test = st.To.Mobile; + + if (test != null && test != rootParent) + tradeRecip = test; + + NetState ns = tradeRecip?.NetState; + + if (ns != null && tradeRecip.CanSee(this) && tradeRecip.InRange(worldLoc, GetUpdateRange(tradeRecip))) + { + if (ns.ContainerGridLines) + ns.Send(new ContainerContentUpdate6017(this)); + else + ns.Send(new ContainerContentUpdate(this)); + + if (ObjectPropertyList.Enabled) + ns.Send(OPLPacket); + } + } + + List openers = contParent.Openers; + + if (openers != null) + lock (openers) + { + for (int i = 0; i < openers.Count; ++i) + { + Mobile mob = openers[i]; + + int range = GetUpdateRange(mob); + + if (mob.Map != map || !mob.InRange(worldLoc, range)) { - SendInfoTo(state, ObjectPropertyList.Enabled); + openers.RemoveAt(i--); } else { - if (p == null) - { - if (m_Parent is Item) - { - if (state.ContainerGridLines) - state.Send(new ContainerContentUpdate6017(this)); - else - state.Send(new ContainerContentUpdate(this)); - } - else if (m_Parent is Mobile) - { - p = new EquipUpdate(this); - p.Acquire(); + if (mob == rootParent || mob == tradeRecip) + continue; - state.Send(p); - } - } - else - { - state.Send(p); - } + NetState ns = mob.NetState; - if (ObjectPropertyList.Enabled) state.Send(OPLPacket); + if (ns != null && mob.CanSee(this)) + { + if (ns.ContainerGridLines) + ns.Send(new ContainerContentUpdate6017(this)); + else + ns.Send(new ContainerContentUpdate(this)); + + if (ObjectPropertyList.Enabled) + ns.Send(OPLPacket); + } } } + + if (openers.Count == 0) + contParent.Openers = null; } - if (p != null) - Packet.Release(p); + return; + } - eable.Free(); - sendOPLUpdate = false; - } - else if ((flags & ItemDelta.EquipOnly) != 0) + Packet p = null; + + IPooledEnumerable eable = map.GetClientsInRange(worldLoc, GetMaxUpdateRange()); + + foreach (NetState state in eable) + { + Mobile m = state.Mobile; + + if (m.CanSee(this) && m.InRange(worldLoc, GetUpdateRange(m))) { - if (m_Parent is Mobile) + if (update) { - Packet p = null; - Point3D worldLoc = GetWorldLocation(); - - IPooledEnumerable eable = map.GetClientsInRange(worldLoc, GetMaxUpdateRange()); - - foreach (NetState state in eable) + if (m_Parent == null) + SendInfoTo(state, ObjectPropertyList.Enabled); + else { - Mobile m = state.Mobile; - - if (m.CanSee(this) && m.InRange(worldLoc, GetUpdateRange(m))) + if (p != null) + state.Send(p); + else if (m_Parent is Item) { - //if ( sendOPLUpdate ) - // state.Send( RemovePacket ); - - if (p == null) - p = Packet.Acquire(new EquipUpdate(this)); + if (state.ContainerGridLines) + state.Send(new ContainerContentUpdate6017(this)); + else + state.Send(new ContainerContentUpdate(this)); + } + else if (m_Parent is Mobile) + { + p = new EquipUpdate(this); + p.Acquire(); state.Send(p); - - if (ObjectPropertyList.Enabled) - state.Send(OPLPacket); } + + if (ObjectPropertyList.Enabled) + state.Send(OPLPacket); } - - Packet.Release(p); - - eable.Free(); - sendOPLUpdate = false; } - } - - if (sendOPLUpdate) - { - Point3D worldLoc = GetWorldLocation(); - IPooledEnumerable eable = map.GetClientsInRange(worldLoc, GetMaxUpdateRange()); - - foreach (NetState state in eable) + else if ((flags & ItemDelta.EquipOnly) != 0 && m_Parent is Mobile) { - Mobile m = state.Mobile; + state.Send(p ?? (p = Packet.Acquire(new EquipUpdate(this)))); - if (m.CanSee(this) && m.InRange(worldLoc, GetUpdateRange(m))) + if (ObjectPropertyList.Enabled) state.Send(OPLPacket); - } - - eable.Free(); + } else if (ObjectPropertyList.Enabled && (flags & ItemDelta.Properties) != 0) + state.Send(OPLPacket); } + + Packet.Release(p); + eable.Free(); } } public virtual void Delete() { - if (Deleted) - return; - - if (!World.OnDelete(this)) + if (Deleted || !World.OnDelete(this)) return; OnDelete(); @@ -2700,8 +2053,8 @@ namespace Server public void ClearProperties() { - Packet.Release(ref m_PropertyList); - Packet.Release(ref m_OPLPacket); + StaticPacketHandlers.FreeOPLPacket(this); + StaticPacketHandlers.FreeOPLInfoPacket(this); } public void InvalidateProperties() @@ -2711,13 +2064,11 @@ namespace Server if (m_Map != null && m_Map != Map.Internal && !World.Loading) { - ObjectPropertyList oldList = m_PropertyList; - m_PropertyList = null; - ObjectPropertyList newList = PropertyList; + ObjectPropertyList oldList = StaticPacketHandlers.FreeOPLPacket(this); - if (oldList == null || oldList.Hash != newList.Hash) + if (oldList?.Hash != PropertyList.Hash) { - Packet.Release(ref m_OPLPacket); + StaticPacketHandlers.FreeOPLInfoPacket(this); Delta(ItemDelta.Properties); } } @@ -2729,9 +2080,7 @@ namespace Server public void ReleaseWorldPackets() { - Packet.Release(ref m_WorldPacket); - Packet.Release(ref m_WorldPacketSA); - Packet.Release(ref m_WorldPacketHS); + StaticPacketHandlers.FreeWorldItemPackets(this); } public virtual int GetPacketFlags() @@ -3485,9 +2834,9 @@ namespace Server public virtual void FreeCache() { ReleaseWorldPackets(); - Packet.Release(ref m_RemovePacket); - Packet.Release(ref m_OPLPacket); - Packet.Release(ref m_PropertyList); + StaticPacketHandlers.FreeRemoveItemPacket(this); + StaticPacketHandlers.FreeOPLInfoPacket(this); + StaticPacketHandlers.FreeOPLPacket(this); } public void PublicOverheadMessage(MessageType type, int hue, bool ascii, string text) @@ -4387,18 +3736,6 @@ namespace Server #endregion - #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 - #region Location Location Location! public virtual void OnLocationChange(Point3D oldLocation) diff --git a/Server/Layer.cs b/Server/Layer.cs new file mode 100644 index 000000000..936917bf6 --- /dev/null +++ b/Server/Layer.cs @@ -0,0 +1,173 @@ +namespace Server +{ + /// + /// Enumeration of item layer values. + /// + public enum Layer : byte + { + /// + /// Invalid layer. + /// + Invalid = 0x00, + + /// + /// First valid layer. Equivalent to Layer.OneHanded. + /// + FirstValid = 0x01, + + /// + /// One handed weapon. + /// + OneHanded = 0x01, + + /// + /// Two handed weapon or shield. + /// + TwoHanded = 0x02, + + /// + /// Shoes. + /// + Shoes = 0x03, + + /// + /// Pants. + /// + Pants = 0x04, + + /// + /// Shirts. + /// + Shirt = 0x05, + + /// + /// Helmets, hats, and masks. + /// + Helm = 0x06, + + /// + /// Gloves. + /// + Gloves = 0x07, + + /// + /// Rings. + /// + Ring = 0x08, + + /// + /// Talismans. + /// + Talisman = 0x09, + + /// + /// Gorgets and necklaces. + /// + Neck = 0x0A, + + /// + /// Hair. + /// + Hair = 0x0B, + + /// + /// Half aprons. + /// + Waist = 0x0C, + + /// + /// Torso, inner layer. + /// + InnerTorso = 0x0D, + + /// + /// Bracelets. + /// + Bracelet = 0x0E, + + /// + /// Unused. + /// + Unused_xF = 0x0F, + + /// + /// Beards and mustaches. + /// + FacialHair = 0x10, + + /// + /// Torso, outer layer. + /// + MiddleTorso = 0x11, + + /// + /// Earings. + /// + Earrings = 0x12, + + /// + /// Arms and sleeves. + /// + Arms = 0x13, + + /// + /// Cloaks. + /// + Cloak = 0x14, + + /// + /// Backpacks. + /// + Backpack = 0x15, + + /// + /// Torso, outer layer. + /// + OuterTorso = 0x16, + + /// + /// Leggings, outer layer. + /// + OuterLegs = 0x17, + + /// + /// Leggings, inner layer. + /// + InnerLegs = 0x18, + + /// + /// Last valid non-internal layer. Equivalent to Layer.InnerLegs. + /// + LastUserValid = 0x18, + + /// + /// Mount item layer. + /// + Mount = 0x19, + + /// + /// Vendor 'buy pack' layer. + /// + ShopBuy = 0x1A, + + /// + /// Vendor 'resale pack' layer. + /// + ShopResale = 0x1B, + + /// + /// Vendor 'sell pack' layer. + /// + ShopSell = 0x1C, + + /// + /// Bank box layer. + /// + Bank = 0x1D, + + /// + /// Last valid layer. Equivalent to Layer.Bank. + /// + LastValid = 0x1D + } +} diff --git a/Server/LightType.cs b/Server/LightType.cs new file mode 100644 index 000000000..cdab2e58b --- /dev/null +++ b/Server/LightType.cs @@ -0,0 +1,287 @@ +namespace Server +{ + public enum LightType + { + /// + /// Window shape, arched, ray shining east. + /// + ArchedWindowEast, + + /// + /// Medium circular shape. + /// + Circle225, + + /// + /// Small circular shape. + /// + Circle150, + + /// + /// Door shape, shining south. + /// + DoorSouth, + + /// + /// Door shape, shining east. + /// + DoorEast, + + /// + /// Large semicircular shape (180 degrees), north wall. + /// + NorthBig, + + /// + /// Large pie shape (90 degrees), north-east corner. + /// + NorthEastBig, + + /// + /// Large semicircular shape (180 degrees), east wall. + /// + EastBig, + + /// + /// Large semicircular shape (180 degrees), west wall. + /// + WestBig, + + /// + /// Large pie shape (90 degrees), south-west corner. + /// + SouthWestBig, + + /// + /// Large semicircular shape (180 degrees), south wall. + /// + SouthBig, + + /// + /// Medium semicircular shape (180 degrees), north wall. + /// + NorthSmall, + + /// + /// Medium pie shape (90 degrees), north-east corner. + /// + NorthEastSmall, + + /// + /// Medium semicircular shape (180 degrees), east wall. + /// + EastSmall, + + /// + /// Medium semicircular shape (180 degrees), west wall. + /// + WestSmall, + + /// + /// Medium semicircular shape (180 degrees), south wall. + /// + SouthSmall, + + /// + /// Shaped like a wall decoration, north wall. + /// + DecorationNorth, + + /// + /// Shaped like a wall decoration, north-east corner. + /// + DecorationNorthEast, + + /// + /// Small semicircular shape (180 degrees), east wall. + /// + EastTiny, + + /// + /// Shaped like a wall decoration, west wall. + /// + DecorationWest, + + /// + /// Shaped like a wall decoration, south-west corner. + /// + DecorationSouthWest, + + /// + /// Small semicircular shape (180 degrees), south wall. + /// + SouthTiny, + + /// + /// Window shape, rectangular, no ray, shining south. + /// + RectWindowSouthNoRay, + + /// + /// Window shape, rectangular, no ray, shining east. + /// + RectWindowEastNoRay, + + /// + /// Window shape, rectangular, ray shining south. + /// + RectWindowSouth, + + /// + /// Window shape, rectangular, ray shining east. + /// + RectWindowEast, + + /// + /// Window shape, arched, no ray, shining south. + /// + ArchedWindowSouthNoRay, + + /// + /// Window shape, arched, no ray, shining east. + /// + ArchedWindowEastNoRay, + + /// + /// Window shape, arched, ray shining south. + /// + ArchedWindowSouth, + + /// + /// Large circular shape. + /// + Circle300, + + /// + /// Large pie shape (90 degrees), north-west corner. + /// + NorthWestBig, + + /// + /// Negative light. Medium pie shape (90 degrees), south-east corner. + /// + DarkSouthEast, + + /// + /// Negative light. Medium semicircular shape (180 degrees), south wall. + /// + DarkSouth, + + /// + /// Negative light. Medium pie shape (90 degrees), north-west corner. + /// + DarkNorthWest, + + /// + /// Negative light. Medium pie shape (90 degrees), south-east corner. Equivalent to LightType.SouthEast. + /// + DarkSouthEast2, + + /// + /// Negative light. Medium circular shape (180 degrees), east wall. + /// + DarkEast, + + /// + /// Negative light. Large circular shape. + /// + DarkCircle300, + + /// + /// Opened door shape, shining south. + /// + DoorOpenSouth, + + /// + /// Opened door shape, shining east. + /// + DoorOpenEast, + + /// + /// Window shape, square, ray shining east. + /// + SquareWindowEast, + + /// + /// Window shape, square, no ray, shining east. + /// + SquareWindowEastNoRay, + + /// + /// Window shape, square, ray shining south. + /// + SquareWindowSouth, + + /// + /// Window shape, square, no ray, shining south. + /// + SquareWindowSouthNoRay, + + /// + /// Empty. + /// + Empty, + + /// + /// Window shape, skinny, no ray, shining south. + /// + SkinnyWindowSouthNoRay, + + /// + /// Window shape, skinny, ray shining east. + /// + SkinnyWindowEast, + + /// + /// Window shape, skinny, no ray, shining east. + /// + SkinnyWindowEastNoRay, + + /// + /// Shaped like a hole, shining south. + /// + HoleSouth, + + /// + /// Shaped like a hole, shining south. + /// + HoleEast, + + /// + /// Large circular shape with a moongate graphic embedded. + /// + Moongate, + + /// + /// Unknown usage. Many rows of slightly angled lines. + /// + Strips, + + /// + /// Shaped like a small hole, shining south. + /// + SmallHoleSouth, + + /// + /// Shaped like a small hole, shining east. + /// + SmallHoleEast, + + /// + /// Large semicircular shape (180 degrees), north wall. Identical graphic as LightType.NorthBig, but slightly different + /// positioning. + /// + NorthBig2, + + /// + /// Large semicircular shape (180 degrees), west wall. Identical graphic as LightType.WestBig, but slightly different + /// positioning. + /// + WestBig2, + + /// + /// Large pie shape (90 degrees), north-west corner. Equivalent to LightType.NorthWestBig. + /// + NorthWestBig2 + } +} diff --git a/Server/Mobile.cs b/Server/Mobile.cs index 9cad11436..5e2af0c95 100644 --- a/Server/Mobile.cs +++ b/Server/Mobile.cs @@ -457,7 +457,7 @@ namespace Server /// /// Base class representing players, npcs, and creatures. /// - public class Mobile : IHued, IComparable, ISerializable, ISpawnable + public class Mobile : IHued, IComparable, ISerializable, ISpawnable, IPropertyListObject { private const int WarmodeCatchCount = 4; // Allow four warmode changes in 0.5 seconds, any more will be delay for two seconds @@ -551,14 +551,8 @@ namespace Server private string m_NameMod; - private Packet m_OPLPacket; - - private ObjectPropertyList m_PropertyList; - private QuestArrow m_QuestArrow; - private Packet m_RemovePacket; - private int m_SolidHueOverride = -1; private StatLockType m_StrLock, m_DexLock, m_IntLock; @@ -1783,59 +1777,9 @@ namespace Server public Region Region => m_Region ?? (Map == null ? Map.Internal.DefaultRegion : Map.DefaultRegion); - public Packet RemovePacket - { - get - { - if (m_RemovePacket == null) - lock (rpLock) - { - if (m_RemovePacket == null) - { - m_RemovePacket = new RemoveMobile(this); - m_RemovePacket.SetStatic(); - } - } - - return m_RemovePacket; - } - } - - public Packet OPLPacket - { - get - { - if (m_OPLPacket == null) - lock (oplLock) - { - 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); - - m_PropertyList.Terminate(); - m_PropertyList.SetStatic(); - } - - return m_PropertyList; - } - } + public Packet RemovePacket => StaticPacketHandlers.GetRemoveEntityPacket(this); + public OPLInfo OPLPacket => StaticPacketHandlers.GetOPLInfoPacket(this); + public ObjectPropertyList PropertyList => StaticPacketHandlers.GetOPLPacket(this); [CommandProperty(AccessLevel.GameMaster)] public int SolidHueOverride @@ -6765,17 +6709,17 @@ namespace Server return delta != 0 ? body : 0; } - public void FreeCache() + public virtual void FreeCache() { - Packet.Release(ref m_RemovePacket); - Packet.Release(ref m_PropertyList); - Packet.Release(ref m_OPLPacket); + StaticPacketHandlers.FreeRemoveItemPacket(this); + StaticPacketHandlers.FreeOPLInfoPacket(this); + StaticPacketHandlers.FreeOPLPacket(this); } public void ClearProperties() { - Packet.Release(ref m_PropertyList); - Packet.Release(ref m_OPLPacket); + StaticPacketHandlers.FreeOPLPacket(this); + StaticPacketHandlers.FreeOPLInfoPacket(this); } public void InvalidateProperties() @@ -6785,13 +6729,11 @@ namespace Server if (m_Map != null && m_Map != Map.Internal && !World.Loading) { - ObjectPropertyList oldList = m_PropertyList; - Packet.Release(ref m_PropertyList); - ObjectPropertyList newList = PropertyList; + ObjectPropertyList oldList = StaticPacketHandlers.FreeOPLPacket(this); - if (oldList == null || oldList.Hash != newList.Hash) + if (oldList?.Hash != PropertyList.Hash) { - Packet.Release(ref m_OPLPacket); + StaticPacketHandlers.FreeOPLInfoPacket(this); Delta(MobileDelta.Properties); } } @@ -6808,148 +6750,148 @@ namespace Server Point3D oldLocation = m_Location; - if (oldLocation != newLocation) + if (oldLocation == newLocation) + return; + + m_Location = newLocation; + UpdateRegion(); + + BankBox box = FindBankNoCreate(); + + if (box?.Opened == true) + box.Close(); + + m_NetState?.ValidateAllTrades(); + + m_Map?.OnMove(oldLocation, this); + + if (isTeleport && m_NetState != null && (!m_NetState.HighSeas || !NoMoveHS)) { - m_Location = newLocation; - UpdateRegion(); + m_NetState.Sequence = 0; - BankBox box = FindBankNoCreate(); + if (m_NetState.StygianAbyss) + m_NetState.Send(new MobileUpdate(this)); + else + m_NetState.Send(new MobileUpdateOld(this)); - if (box?.Opened == true) - box.Close(); + ClearFastwalkStack(); + } - m_NetState?.ValidateAllTrades(); + Map map = m_Map; - m_Map?.OnMove(oldLocation, this); + if (map != null) + { + // First, send a remove message to everyone who can no longer see us. (inOldRange && !inNewRange) - if (isTeleport && m_NetState != null && (!m_NetState.HighSeas || !NoMoveHS)) + IPooledEnumerable eable = map.GetClientsInRange(oldLocation); + + foreach (NetState ns in eable) + if (ns != m_NetState && !Utility.InUpdateRange(newLocation, ns.Mobile.Location)) + ns.Send(RemovePacket); + + eable.Free(); + + NetState ourState = m_NetState; + + // Check to see if we are attached to a client + if (ourState != null) { - m_NetState.Sequence = 0; + IPooledEnumerable eeable = map.GetObjectsInRange(newLocation, Core.GlobalMaxUpdateRange); - if (m_NetState.StygianAbyss) - m_NetState.Send(new MobileUpdate(this)); - else - m_NetState.Send(new MobileUpdateOld(this)); + // We are attached to a client, so it's a bit more complex. We need to send new items and people to ourself, and ourself to other clients - ClearFastwalkStack(); - } + foreach (IEntity o in eeable) + if (o is Item item) + { + int range = item.GetUpdateRange(this); + Point3D loc = item.Location; - Map map = m_Map; + if (!Utility.InRange(oldLocation, loc, range) && Utility.InRange(newLocation, loc, range) && + CanSee(item)) + item.SendInfoTo(ourState); + } + else if (o != this && o is Mobile m) + { + if (!Utility.InUpdateRange(newLocation, m.m_Location)) + continue; - if (map != null) - { - // First, send a remove message to everyone who can no longer see us. (inOldRange && !inNewRange) + bool inOldRange = Utility.InUpdateRange(oldLocation, m.m_Location); - IPooledEnumerable eable = map.GetClientsInRange(oldLocation); - - foreach (NetState ns in eable) - if (ns != m_NetState && !Utility.InUpdateRange(newLocation, ns.Mobile.Location)) - ns.Send(RemovePacket); - - eable.Free(); - - NetState ourState = m_NetState; - - // Check to see if we are attached to a client - if (ourState != null) - { - IPooledEnumerable eeable = map.GetObjectsInRange(newLocation, Core.GlobalMaxUpdateRange); - - // We are attached to a client, so it's a bit more complex. We need to send new items and people to ourself, and ourself to other clients - - foreach (IEntity o in eeable) - if (o is Item item) + if (m.m_NetState != null && + (isTeleport && (!m.m_NetState.HighSeas || !NoMoveHS) || !inOldRange) && m.CanSee(this)) { - int range = item.GetUpdateRange(this); - Point3D loc = item.Location; + m.m_NetState.Send(MobileIncoming.Create(m.m_NetState, m, this)); - if (!Utility.InRange(oldLocation, loc, range) && Utility.InRange(newLocation, loc, range) && - CanSee(item)) - item.SendInfoTo(ourState); - } - else if (o != this && o is Mobile m) - { - if (!Utility.InUpdateRange(newLocation, m.m_Location)) - continue; - - bool inOldRange = Utility.InUpdateRange(oldLocation, m.m_Location); - - if (m.m_NetState != null && - (isTeleport && (!m.m_NetState.HighSeas || !NoMoveHS) || !inOldRange) && m.CanSee(this)) - { - m.m_NetState.Send(MobileIncoming.Create(m.m_NetState, m, this)); - - if (m.m_NetState.StygianAbyss) - { - //if ( m_Poison != null ) - m.m_NetState.Send(new HealthbarPoison(this)); - - //if ( m_Blessed || m_YellowHealthbar ) - m.m_NetState.Send(new HealthbarYellow(this)); - } - - if (IsDeadBondedPet) - m.m_NetState.Send(new BondedStatus(0, Serial, 1)); - - if (ObjectPropertyList.Enabled) m.m_NetState.Send(OPLPacket); - } - - if (inOldRange || !CanSee(m)) - continue; - - ourState.Send(MobileIncoming.Create(ourState, this, m)); - - if (ourState.StygianAbyss) - { - //if ( m.Poisoned ) - ourState.Send(new HealthbarPoison(m)); - - //if ( m.Blessed || m.YellowHealthbar ) - ourState.Send(new HealthbarYellow(m)); - } - - if (m.IsDeadBondedPet) - ourState.Send(new BondedStatus(0, m.Serial, 1)); - - if (ObjectPropertyList.Enabled) ourState.Send(m.OPLPacket); - } - - eeable.Free(); - } - else - { - eable = map.GetClientsInRange(newLocation); - - // We're not attached to a client, so simply send an Incoming - foreach (NetState ns in eable) - if ((isTeleport && (!ns.HighSeas || !NoMoveHS) || - !Utility.InUpdateRange(oldLocation, ns.Mobile.Location)) && ns.Mobile.CanSee(this)) - { - ns.Send(MobileIncoming.Create(ns, ns.Mobile, this)); - - if (ns.StygianAbyss) + if (m.m_NetState.StygianAbyss) { //if ( m_Poison != null ) - ns.Send(new HealthbarPoison(this)); + m.m_NetState.Send(new HealthbarPoison(this)); //if ( m_Blessed || m_YellowHealthbar ) - ns.Send(new HealthbarYellow(this)); + m.m_NetState.Send(new HealthbarYellow(this)); } if (IsDeadBondedPet) - ns.Send(new BondedStatus(0, Serial, 1)); + m.m_NetState.Send(new BondedStatus(0, Serial, 1)); - if (ObjectPropertyList.Enabled) ns.Send(OPLPacket); + if (ObjectPropertyList.Enabled) m.m_NetState.Send(OPLPacket); } - eable.Free(); - } + if (inOldRange || !CanSee(m)) + continue; + + ourState.Send(MobileIncoming.Create(ourState, this, m)); + + if (ourState.StygianAbyss) + { + //if ( m.Poisoned ) + ourState.Send(new HealthbarPoison(m)); + + //if ( m.Blessed || m.YellowHealthbar ) + ourState.Send(new HealthbarYellow(m)); + } + + if (m.IsDeadBondedPet) + ourState.Send(new BondedStatus(0, m.Serial, 1)); + + if (ObjectPropertyList.Enabled) ourState.Send(m.OPLPacket); + } + + eeable.Free(); } + else + { + eable = map.GetClientsInRange(newLocation); - OnLocationChange(oldLocation); + // We're not attached to a client, so simply send an Incoming + foreach (NetState ns in eable) + if ((isTeleport && (!ns.HighSeas || !NoMoveHS) || + !Utility.InUpdateRange(oldLocation, ns.Mobile.Location)) && ns.Mobile.CanSee(this)) + { + ns.Send(MobileIncoming.Create(ns, ns.Mobile, this)); - Region.OnLocationChanged(this, oldLocation); + if (ns.StygianAbyss) + { + //if ( m_Poison != null ) + ns.Send(new HealthbarPoison(this)); + + //if ( m_Blessed || m_YellowHealthbar ) + ns.Send(new HealthbarYellow(this)); + } + + if (IsDeadBondedPet) + ns.Send(new BondedStatus(0, Serial, 1)); + + if (ObjectPropertyList.Enabled) ns.Send(OPLPacket); + } + + eable.Free(); + } } + + OnLocationChange(oldLocation); + + Region.OnLocationChanged(this, oldLocation); } /// diff --git a/Server/Network/Packets.cs b/Server/Network/Packets.cs index 3da633219..a08633c70 100644 --- a/Server/Network/Packets.cs +++ b/Server/Network/Packets.cs @@ -1035,9 +1035,8 @@ namespace Server.Network int hue = item.Hue; - if (parent != null) - if (parent.SolidHueOverride >= 0) - hue = parent.SolidHueOverride; + if (parent?.SolidHueOverride >= 0) + hue = parent.SolidHueOverride; m_Stream.Write(item.Serial); m_Stream.Write((short)item.ItemID); @@ -2019,19 +2018,11 @@ namespace Server.Network } } - public sealed class RemoveItem : Packet + public sealed class RemoveEntity : Packet { - public RemoveItem(Item item) : base(0x1D, 5) + public RemoveEntity(IEntity entity) : base(0x1D, 5) { - m_Stream.Write(item.Serial); - } - } - - public sealed class RemoveMobile : Packet - { - public RemoveMobile(Mobile m) : base(0x1D, 5) - { - m_Stream.Write(m.Serial); + m_Stream.Write(entity.Serial); } } @@ -4363,38 +4354,9 @@ namespace Server.Network return p; } - public static void Release(ref ObjectPropertyList p) - { - p?.Release(); - - p = null; - } - - public static void Release(ref RemoveItem p) - { - p?.Release(); - - p = null; - } - - public static void Release(ref RemoveMobile p) - { - p?.Release(); - - p = null; - } - - public static void Release(ref OPLInfo p) - { - p?.Release(); - - p = null; - } - public static void Release(ref Packet p) { p?.Release(); - p = null; } diff --git a/Server/Network/StaticPacketHandlers.cs b/Server/Network/StaticPacketHandlers.cs new file mode 100644 index 000000000..ff09ffd50 --- /dev/null +++ b/Server/Network/StaticPacketHandlers.cs @@ -0,0 +1,115 @@ +using System.Collections.Concurrent; + +namespace Server.Network +{ + public static class StaticPacketHandlers + { + private static ConcurrentDictionary OPLInfoPackets = new ConcurrentDictionary(); + private static ConcurrentDictionary ObjectPropertyListPackets = new ConcurrentDictionary(); + private static ConcurrentDictionary RemoveEntityPackets = new ConcurrentDictionary(); + + private static ConcurrentDictionary WorldItemPackets = new ConcurrentDictionary(); + private static ConcurrentDictionary WorldItemSAPackets = new ConcurrentDictionary(); + private static ConcurrentDictionary WorldItemHSPackets = new ConcurrentDictionary(); + + public static OPLInfo GetOPLInfoPacket(IPropertyListObject obj) + { + return OPLInfoPackets.GetOrAdd(obj, value => + { + OPLInfo packet = new OPLInfo(value.PropertyList); + packet.SetStatic(); + return packet; + }); + } + + public static OPLInfo FreeOPLInfoPacket(IPropertyListObject obj) + { + if (OPLInfoPackets.TryRemove(obj, out OPLInfo p)) + Packet.Release(p); + + return p; + } + + public static ObjectPropertyList GetOPLPacket(IPropertyListObject obj) + { + return ObjectPropertyListPackets.GetOrAdd(obj, value => + { + ObjectPropertyList list = new ObjectPropertyList(value); + + value.GetProperties(list); + if (value is Item item) + item.AppendChildProperties(list); + + list.Terminate(); + list.SetStatic(); + return list; + }); + } + + public static ObjectPropertyList FreeOPLPacket(IPropertyListObject obj) + { + if (ObjectPropertyListPackets.TryRemove(obj, out ObjectPropertyList list)) + Packet.Release(list); + + return list; + } + + public static RemoveEntity GetRemoveEntityPacket(IEntity entity) + { + return RemoveEntityPackets.GetOrAdd(entity, value => + { + RemoveEntity packet = new RemoveEntity(value); + packet.SetStatic(); + return packet; + }); + } + + public static void FreeRemoveItemPacket(IEntity entity) + { + if (RemoveEntityPackets.TryRemove(entity, out RemoveEntity p)) + Packet.Release(p); + } + + public static WorldItem GetWorldItemPacket(Item item) + { + return WorldItemPackets.GetOrAdd(item, value => + { + WorldItem packet = new WorldItem(value); + packet.SetStatic(); + return packet; + }); + } + + public static WorldItemSA GetWorldItemSAPacket(Item item) + { + return WorldItemSAPackets.GetOrAdd(item, value => + { + WorldItemSA packet = new WorldItemSA(value); + packet.SetStatic(); + return packet; + }); + } + + public static WorldItemHS GetWorldItemHSPacket(Item item) + { + return WorldItemHSPackets.GetOrAdd(item, value => + { + WorldItemHS packet = new WorldItemHS(value); + packet.SetStatic(); + return packet; + }); + } + + public static void FreeWorldItemPackets(Item item) + { + if (WorldItemPackets.TryRemove(item, out WorldItem wi)) + Packet.Release(wi); + + if (WorldItemSAPackets.TryRemove(item, out WorldItemSA wisa)) + Packet.Release(wisa); + + if (WorldItemHSPackets.TryRemove(item, out WorldItemHS wihs)) + Packet.Release(wihs); + } + } +} diff --git a/Server/ObjectPropertyList.cs b/Server/ObjectPropertyList.cs index 756147113..b56e1c1da 100644 --- a/Server/ObjectPropertyList.cs +++ b/Server/ObjectPropertyList.cs @@ -24,6 +24,14 @@ using Server.Network; namespace Server { + public interface IPropertyListObject : IEntity + { + ObjectPropertyList PropertyList{ get; } + OPLInfo OPLPacket{ get; } + + void GetProperties(ObjectPropertyList list); + } + public sealed class ObjectPropertyList : Packet { private static byte[] m_Buffer = new byte[1024]; @@ -191,4 +199,4 @@ namespace Server m_Stream.Write(list.Hash); } } -} \ No newline at end of file +} diff --git a/Server/Server.csproj b/Server/Server.csproj index ef557a862..6fbb90173 100644 --- a/Server/Server.csproj +++ b/Server/Server.csproj @@ -155,6 +155,8 @@ + + @@ -169,6 +171,7 @@ + @@ -260,4 +263,4 @@ - + \ No newline at end of file