예제 #1
0
        private static void ObjectChanged(uint serial, ObjectChangeType changeType, bool isStatusUpdate)
        {
            objectCallbacks.InvokeAsync(new ObjectChangedEventArgs(serial, changeType, isStatusUpdate));

            if (changeType == ObjectChangeType.ItemUpdated || changeType == ObjectChangeType.Removed)
            {
                ObjectChangeType subChange = (changeType == ObjectChangeType.Removed) ? ObjectChangeType.SubItemRemoved : ObjectChangeType.SubItemUpdated;

                RealItem item = World.FindRealItem(serial);
                if (item != null)
                {
                    do
                    {
                        RealObject obj = World.FindRealObject(item.Container);

                        if (obj != null)
                        {
                            objectCallbacks.InvokeAsync(new ObjectChangedEventArgs(obj.Serial, serial, subChange));
                        }

                        item = obj as RealItem;
                    }while (item != null);
                }
            }
        }
예제 #2
0
        static uint AddToContainerData(PacketReader reader, out bool isNew)
        {
            uint serial = reader.ReadUInt32();

            RealItem item = World.FindRealItem(serial);
            if (item == null) {
                item = new RealItem(serial);
                World.Add(item);
                isNew = true;
            }
            else {
                isNew = false;
            }

            item.Detach();

            item.Graphic = reader.ReadUInt16();

            byte unknown = reader.ReadByte();

            item.Amount = reader.ReadUInt16();

            item.X = reader.ReadUInt16();
            item.Y = reader.ReadUInt16();
            item.Z = 0;
            item.Container = reader.ReadUInt32();
            item.Color = reader.ReadUInt16();

            #if WORLDDEBUG
            Trace.WriteLine(String.Format("Item updated ({0}).", item.Description), "World");
            #endif

            return serial;
        }
예제 #3
0
파일: World.cs 프로젝트: byterj/phoenix
 /// <summary>
 /// Never returns null.
 /// </summary>
 internal static RealItem GetRealItem(uint serial)
 {
     lock (World.SyncRoot) {
         RealItem obj = FindRealItem(serial);
         if (obj != null)
         {
             return(obj);
         }
         else
         {
             return(invalidItem);
         }
     }
 }
예제 #4
0
        static CallbackResult OnObjectRemove(byte[] data, CallbackResult prevResult)
        {
            lock (World.SyncRoot) {
                if (data[0] != 0x1D)
                {
                    throw new Exception("Invalid packet passed to OnObjectRemove.");
                }

                uint serial = ByteConverter.BigEndian.ToUInt32(data, 1);

                if (serial != World.PlayerSerial)
                {
                    // Get item before we remove it, so we know its parent
                    // It will be null for chars, thats ok
                    RealItem item = World.FindRealItem(serial);

                    if (World.Remove(serial))
                    {
                        Trace.WriteLine(String.Format("Object 0x{0:X8} removed from world.", serial), "World");
                    }
                    else
                    {
                        Trace.WriteLine(String.Format("Cannot remove 0x{0:X8}. Object doesn't exist.", serial), "World");
                    }

                    // Invoke all events manually
                    objectCallbacks.InvokeAsync(new ObjectChangedEventArgs(serial, ObjectChangeType.Removed));

                    while (item != null)
                    {
                        RealObject obj = World.FindRealObject(item.Container);

                        if (obj != null)
                        {
                            objectCallbacks.InvokeAsync(new ObjectChangedEventArgs(obj.Serial, serial, ObjectChangeType.SubItemRemoved));
                        }

                        item = obj as RealItem;
                    }

                    return(CallbackResult.Normal);
                }
                else
                {
                    Trace.WriteLine("Cannot remove player. Packet dropped.", "World");
                    return(CallbackResult.Eat);
                }
            }
        }
예제 #5
0
파일: World.cs 프로젝트: byterj/phoenix
        internal static void Add(RealItem item)
        {
            lock (World.SyncRoot) {
                if (item == null)
                {
                    throw new ArgumentNullException("item");
                }
                if (itemList.ContainsKey(item.Serial))
                {
                    throw new InternalErrorException("Serial already exists.");
                }

                itemList.Add(item.Serial, item);
            }
        }
예제 #6
0
        static CallbackResult OnCharacterAddItem(byte[] data, CallbackResult prevResult)
        {
            lock (World.SyncRoot) {
                if (data[0] != 0x2E)
                {
                    throw new Exception("Invalid packet passed to OnCharacterAddItem.");
                }

                uint serial = ByteConverter.BigEndian.ToUInt32(data, 1);

                bool     isNew = false;
                RealItem item  = World.FindRealItem(serial);
                if (item == null)
                {
                    item = new RealItem(serial);
                    World.Add(item);
                    isNew = true;
                }

                item.Detach();

                item.Graphic = ByteConverter.BigEndian.ToUInt16(data, 5);
                item.Layer   = ByteConverter.BigEndian.ToByte(data, 8);
                item.Color   = ByteConverter.BigEndian.ToUInt16(data, 13);

                item.Container = ByteConverter.BigEndian.ToUInt32(data, 9);

                RealCharacter chr = World.FindRealCharacter(item.Container);
                if (chr != null)
                {
                    chr.Layers[item.Layer] = item.Serial;
                }

#if WORLDDEBUG
                Trace.WriteLine(String.Format("Item updated ({0}).", item.Description), "World");
#endif
                if (isNew)
                {
                    itemAdded.InvokeAsync(null, new ObjectChangedEventArgs(serial, ObjectChangeType.NewItem));
                }

                itemUpdated.InvokeAsync(null, new ObjectChangedEventArgs(serial, ObjectChangeType.ItemUpdated));
                ObjectChanged(serial, ObjectChangeType.ItemUpdated);

                return(CallbackResult.Normal);
            }
        }
예제 #7
0
        /// <summary>
        /// Finds out whether item is in this container or not.
        /// </summary>
        /// <param name="serial">Item serial.</param>
        /// <returns></returns>
        public bool Contains(Serial serial)
        {
            lock (World.SyncRoot) {
                RealItem item = World.FindRealItem(serial);

                while (item != null && (this.serial == 0 || item.Container != 0))
                {
                    if (item.Container == this.serial)
                    {
                        return(true);
                    }
                    else
                    {
                        item = searchSubContainers ? World.FindRealItem(item.Container) : null;
                    }
                }

                return(false);
            }
        }
예제 #8
0
        static uint AddToContainerData(PacketReader reader, out bool isNew)
        {
            uint serial = reader.ReadUInt32();

            RealItem item = World.FindRealItem(serial);

            if (item == null)
            {
                item = new RealItem(serial);
                World.Add(item);
                isNew = true;
            }
            else
            {
                isNew = false;
            }

            item.Detach();

            item.Graphic = reader.ReadUInt16();

            byte unknown = reader.ReadByte();

            item.Amount = reader.ReadUInt16();

            item.X         = reader.ReadUInt16();
            item.Y         = reader.ReadUInt16();
            item.Z         = 0;
            item.Container = reader.ReadUInt32();
            item.Color     = reader.ReadUInt16();

#if WORLDDEBUG
            Trace.WriteLine(String.Format("Item updated ({0}).", item.Description), "World");
#endif

            return(serial);
        }
예제 #9
0
        static CallbackResult OnOpenContainer(byte[] data, CallbackResult prevResult)
        {
            lock (World.SyncRoot) {
                if (data[0] != 0x24)
                {
                    throw new Exception("Invalid packet passed to OnOpenContainer.");
                }

                uint   serial = ByteConverter.BigEndian.ToUInt32(data, 1);
                ushort gump   = ByteConverter.BigEndian.ToUInt16(data, 5);

                RealItem container = World.FindRealItem(serial);
                if (container == null)
                {
                    Trace.WriteLine("Cannot open non-existing container.", "World");
                    return(CallbackResult.Normal);
                }

                // Items will be populated later.
                List <uint> removeList = new List <uint>();

                World.GetContainerContents(container.Serial, removeList);

                for (int i = 0; i < removeList.Count; i++)
                {
                    World.ItemList.Remove(removeList[i]);
                }

                container.Opened = true;

                Trace.WriteLine(String.Format("Opening container 0x{0}..", serial.ToString("X8")), "World");

                ObjectChanged(serial, ObjectChangeType.ItemOpened);

                return(CallbackResult.Normal);
            }
        }
예제 #10
0
        static CallbackResult OnItemDetails(byte[] data, CallbackResult prevResult)
        {
            lock (World.SyncRoot) {
                PacketReader reader = new PacketReader(data);

                byte id = reader.ReadByte();
                if (id != 0x1A) throw new Exception("Invalid packet passed to OnItemDetails.");

                ushort blockSize = reader.ReadUInt16();

                if (blockSize != reader.Length)
                    return CallbackResult.Normal;

                uint serial = reader.ReadUInt32();

                bool isNew = false;
                RealItem item = World.FindRealItem(serial);
                if (item == null) {
                    item = new RealItem(serial);
                    World.Add(item);
                    isNew = true;
                }

                ushort dispId = reader.ReadUInt16();

                if ((serial & 0x80000000) != 0) {
                    item.Amount = reader.ReadUInt16();
                }

                if ((dispId & 0x8000) != 0) {
                    dispId += reader.ReadByte();
                }

                item.Graphic = (ushort)(dispId & 0x7FFF);

                ushort x = reader.ReadUInt16();
                item.X = (ushort)(x & 0x7FFF);

                ushort y = reader.ReadUInt16();
                item.Y = (ushort)(y & 0x3FFF);

                if ((x & 0x8000) != 0) {
                    byte direction = reader.ReadByte();
                }

                item.Z = reader.ReadSByte();

                if ((y & 0x8000) != 0) {
                    item.Color = reader.ReadUInt16();
                }

                if ((y & 0x4000) != 0) {
                    item.Flags = reader.ReadByte();
                }

                item.Detach();

            #if WORLDDEBUG
                Trace.WriteLine(String.Format("Item updated ({0}).", item.Description), "World");
            #endif
                if (isNew)
                    itemAdded.InvokeAsync(null, new ObjectChangedEventArgs(serial, ObjectChangeType.NewItem));

                ObjectChanged(serial, ObjectChangeType.ItemUpdated);
                itemUpdated.InvokeAsync(null, new ObjectChangedEventArgs(item.Serial, ObjectChangeType.ItemUpdated));

                return CallbackResult.Normal;
            }
        }
예제 #11
0
        static CallbackResult OnCharacterInformation(byte[] data, CallbackResult prevResult)
        {
            lock (World.SyncRoot) {
                PacketReader reader = new PacketReader(data);

                if (reader.ReadByte() != 0x78) throw new Exception("Invalid packet passed to OnCharacterInformation.");

                ushort blockSize = reader.ReadUInt16();
                if (data.Length != blockSize)
                    Trace.WriteLine(String.Format("BlockSize ({0}) for dynamic packet 0x78 doesn't meet data lenght ({1}).", data.Length), "World");

                bool newCharacter = false;
                uint serial = reader.ReadUInt32();

                RealCharacter chr = World.FindRealCharacter(serial);
                if (chr == null) {
                    chr = new RealCharacter(serial);
                    World.Add(chr);
                    newCharacter = true;
                }

                chr.Graphic = reader.ReadUInt16();
                chr.X = reader.ReadUInt16();
                chr.Y = reader.ReadUInt16();
                chr.Z = reader.ReadSByte();

                chr.Direction = reader.ReadByte();
                chr.Color = reader.ReadUInt16();
                chr.Flags = reader.ReadByte();
                chr.Notoriety = reader.ReadByte();

                if (newCharacter)
                    characterAppeared.InvokeAsync(null, new CharacterAppearedEventArgs(serial));

                ObjectChanged(serial, ObjectChangeType.CharUpdated);

                // Items
                while (reader.Offset < blockSize) {
                    uint itemSerial = reader.ReadUInt32();

                    if (itemSerial == 0)
                        return CallbackResult.Normal;

                    bool isNew = false;
                    RealItem item = World.FindRealItem(itemSerial);
                    if (item == null) {
                        item = new RealItem(itemSerial);
                        World.Add(item);
                        isNew = true;
                    }

                    item.Detach();

                    ushort graphic = reader.ReadUInt16();
                    item.Graphic = (ushort)(graphic & 0x7FFF);

                    item.Layer = reader.ReadByte();

                    if ((graphic & 0x8000) != 0) {
                        item.Color = reader.ReadUInt16();
                    }

                    item.Container = chr.Serial;
                    chr.Layers[item.Layer] = item.Serial;

            #if WORLDDEBUG
                    Trace.WriteLine(String.Format("Item updated ({0}).", item.Description), "World");
            #endif
                    if (isNew)
                        itemAdded.InvokeAsync(null, new ObjectChangedEventArgs(serial, ObjectChangeType.NewItem));

                    itemUpdated.InvokeAsync(null, new ObjectChangedEventArgs(serial, ObjectChangeType.ItemUpdated));
                    ObjectChanged(itemSerial, ObjectChangeType.ItemUpdated);
                }

            #if WORLDDEBUG
                Trace.WriteLine(String.Format("Character updated ({0}).", chr), "World");
            #endif

                return CallbackResult.Normal;
            }
        }
예제 #12
0
        static CallbackResult OnCharacterAddItem(byte[] data, CallbackResult prevResult)
        {
            lock (World.SyncRoot) {
                if (data[0] != 0x2E) throw new Exception("Invalid packet passed to OnCharacterAddItem.");

                uint serial = ByteConverter.BigEndian.ToUInt32(data, 1);

                bool isNew = false;
                RealItem item = World.FindRealItem(serial);
                if (item == null) {
                    item = new RealItem(serial);
                    World.Add(item);
                    isNew = true;
                }

                item.Detach();

                item.Graphic = ByteConverter.BigEndian.ToUInt16(data, 5);
                item.Layer = ByteConverter.BigEndian.ToByte(data, 8);
                item.Color = ByteConverter.BigEndian.ToUInt16(data, 13);

                item.Container = ByteConverter.BigEndian.ToUInt32(data, 9);

                RealCharacter chr = World.FindRealCharacter(item.Container);
                if (chr != null) {
                    chr.Layers[item.Layer] = item.Serial;
                }

            #if WORLDDEBUG
                Trace.WriteLine(String.Format("Item updated ({0}).", item.Description), "World");
            #endif
                if (isNew)
                    itemAdded.InvokeAsync(null, new ObjectChangedEventArgs(serial, ObjectChangeType.NewItem));

                itemUpdated.InvokeAsync(null, new ObjectChangedEventArgs(serial, ObjectChangeType.ItemUpdated));
                ObjectChanged(serial, ObjectChangeType.ItemUpdated);

                return CallbackResult.Normal;
            }
        }
예제 #13
0
파일: World.cs 프로젝트: byterj/phoenix
        /// <param name="limit">Maximum count of items that can be deleted.</param>
        public static void CleanUp(int limit)
        {
            if (Core.LoggedIn)
            {
                System.Diagnostics.Stopwatch watch = new Stopwatch();
                watch.Start();

                List <uint> itemRemoveList = new List <uint>();
                List <uint> charRemoveList = new List <uint>();

                lock (SyncRoot) {
                    if (playerSerial != 0 && playerSerial != uint.MaxValue)
                    {
                        foreach (KeyValuePair <uint, RealItem> pair in itemList)
                        {
                            RealItem item = pair.Value;
                            int      dist = item.GetDistance(World.RealPlayer);
                            if ((item.Container == 0 && dist > cleanUpDistance) ||
                                (item.Container != 0 && !itemList.ContainsKey(item.Container) && !charList.ContainsKey(item.Container)))
                            {
                                itemRemoveList.Add(item.Serial);
                                GetContainerContents(item.Serial, itemRemoveList);
                            }

                            if (itemRemoveList.Count > limit)
                            {
                                break;
                            }
                        }

                        foreach (KeyValuePair <uint, RealCharacter> pair in charList)
                        {
                            RealCharacter chr = pair.Value;
                            if (chr.GetDistance(World.RealPlayer) > cleanUpDistance)
                            {
                                charRemoveList.Add(chr.Serial);

                                for (int l = 0; l < chr.Layers.Length; l++)
                                {
                                    if (chr.Layers[l] != 0)
                                    {
                                        itemRemoveList.Add(chr.Layers[l]);
                                        GetContainerContents(chr.Layers[l], itemRemoveList);
                                    }
                                }

                                if (charRemoveList.Count > limit)
                                {
                                    break;
                                }
                            }
                        }

                        for (int i = 0; i < charRemoveList.Count; i++)
                        {
                            charList.Remove(charRemoveList[i]);
                        }

                        for (int i = 0; i < itemRemoveList.Count; i++)
                        {
                            itemList.Remove(itemRemoveList[i]);
                        }
                    }
                }

                watch.Stop();

                if (itemRemoveList.Count > 0 || charRemoveList.Count > 0)
                {
                    Trace.WriteLine(String.Format("World cleaned ({0} seconds). Wiped items: {1} characters: {2}", watch.ElapsedMilliseconds / 1000.0f, itemRemoveList.Count, charRemoveList.Count), "World");
                    Trace.WriteLine(String.Format("{0} items {1} characters.", itemList.Count, charList.Count), "World");
                }
            }

            worldCleaned.InvokeAsync(null, EventArgs.Empty);
        }
예제 #14
0
        internal static void Add(RealItem item)
        {
            lock (World.SyncRoot) {
                if (item == null) throw new ArgumentNullException("item");
                if (itemList.ContainsKey(item.Serial))
                    throw new InternalErrorException("Serial already exists.");

                itemList.Add(item.Serial, item);
            }
        }
예제 #15
0
        static CallbackResult OnItemDetails(byte[] data, CallbackResult prevResult)
        {
            lock (World.SyncRoot) {
                PacketReader reader = new PacketReader(data);

                byte id = reader.ReadByte();
                if (id != 0x1A)
                {
                    throw new Exception("Invalid packet passed to OnItemDetails.");
                }

                ushort blockSize = reader.ReadUInt16();

                if (blockSize != reader.Length)
                {
                    return(CallbackResult.Normal);
                }

                uint serial = reader.ReadUInt32();

                bool     isNew = false;
                RealItem item  = World.FindRealItem(serial);
                if (item == null)
                {
                    item = new RealItem(serial);
                    World.Add(item);
                    isNew = true;
                }

                ushort dispId = reader.ReadUInt16();

                if ((serial & 0x80000000) != 0)
                {
                    item.Amount = reader.ReadUInt16();
                }

                if ((dispId & 0x8000) != 0)
                {
                    dispId += reader.ReadByte();
                }

                item.Graphic = (ushort)(dispId & 0x7FFF);

                ushort x = reader.ReadUInt16();
                item.X = (ushort)(x & 0x7FFF);

                ushort y = reader.ReadUInt16();
                item.Y = (ushort)(y & 0x3FFF);

                if ((x & 0x8000) != 0)
                {
                    byte direction = reader.ReadByte();
                }

                item.Z = reader.ReadSByte();

                if ((y & 0x8000) != 0)
                {
                    item.Color = reader.ReadUInt16();
                }

                if ((y & 0x4000) != 0)
                {
                    item.Flags = reader.ReadByte();
                }

                item.Detach();

#if WORLDDEBUG
                Trace.WriteLine(String.Format("Item updated ({0}).", item.Description), "World");
#endif
                if (isNew)
                {
                    itemAdded.InvokeAsync(null, new ObjectChangedEventArgs(serial, ObjectChangeType.NewItem));
                }

                ObjectChanged(serial, ObjectChangeType.ItemUpdated);
                itemUpdated.InvokeAsync(null, new ObjectChangedEventArgs(item.Serial, ObjectChangeType.ItemUpdated));

                return(CallbackResult.Normal);
            }
        }
예제 #16
0
        static CallbackResult OnCharacterInformation(byte[] data, CallbackResult prevResult)
        {
            lock (World.SyncRoot) {
                PacketReader reader = new PacketReader(data);

                if (reader.ReadByte() != 0x78)
                {
                    throw new Exception("Invalid packet passed to OnCharacterInformation.");
                }

                ushort blockSize = reader.ReadUInt16();
                if (data.Length != blockSize)
                {
                    Trace.WriteLine(String.Format("BlockSize ({0}) for dynamic packet 0x78 doesn't meet data lenght ({1}).", data.Length), "World");
                }

                bool newCharacter = false;
                uint serial       = reader.ReadUInt32();

                RealCharacter chr = World.FindRealCharacter(serial);
                if (chr == null)
                {
                    chr = new RealCharacter(serial);
                    World.Add(chr);
                    newCharacter = true;
                }

                chr.Graphic = reader.ReadUInt16();
                chr.X       = reader.ReadUInt16();
                chr.Y       = reader.ReadUInt16();
                chr.Z       = reader.ReadSByte();

                chr.Direction = reader.ReadByte();
                chr.Color     = reader.ReadUInt16();
                chr.Flags     = reader.ReadByte();
                chr.Notoriety = reader.ReadByte();

                if (newCharacter)
                {
                    characterAppeared.InvokeAsync(null, new CharacterAppearedEventArgs(serial));
                }

                ObjectChanged(serial, ObjectChangeType.CharUpdated);

                // Items
                while (reader.Offset < blockSize)
                {
                    uint itemSerial = reader.ReadUInt32();

                    if (itemSerial == 0)
                    {
                        return(CallbackResult.Normal);
                    }

                    bool     isNew = false;
                    RealItem item  = World.FindRealItem(itemSerial);
                    if (item == null)
                    {
                        item = new RealItem(itemSerial);
                        World.Add(item);
                        isNew = true;
                    }

                    item.Detach();

                    ushort graphic = reader.ReadUInt16();
                    item.Graphic = (ushort)(graphic & 0x7FFF);

                    item.Layer = reader.ReadByte();

                    if ((graphic & 0x8000) != 0)
                    {
                        item.Color = reader.ReadUInt16();
                    }

                    item.Container         = chr.Serial;
                    chr.Layers[item.Layer] = item.Serial;

#if WORLDDEBUG
                    Trace.WriteLine(String.Format("Item updated ({0}).", item.Description), "World");
#endif
                    if (isNew)
                    {
                        itemAdded.InvokeAsync(null, new ObjectChangedEventArgs(serial, ObjectChangeType.NewItem));
                    }

                    itemUpdated.InvokeAsync(null, new ObjectChangedEventArgs(serial, ObjectChangeType.ItemUpdated));
                    ObjectChanged(itemSerial, ObjectChangeType.ItemUpdated);
                }

#if WORLDDEBUG
                Trace.WriteLine(String.Format("Character updated ({0}).", chr), "World");
#endif

                return(CallbackResult.Normal);
            }
        }