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); } } }
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; }
/// <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); } } }
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); } } }
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); } }
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); } }
/// <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); } }
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); }
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); } }
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; } }
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; } }
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; } }
/// <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); }
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); } }
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); } }
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); } }