static CallbackResult OnUpdateStats(byte[] data, CallbackResult prevResult) { lock (World.SyncRoot) { if (data[0] != 0x2D) { throw new Exception("Invalid packet passed to OnUpdateStats."); } uint serial = ByteConverter.BigEndian.ToUInt32(data, 1); RealCharacter chr = World.FindRealCharacter(serial); if (chr == null) { Trace.WriteLine(String.Format("Cannot update stats for unknown character (serial=0x{0}).", serial.ToString("X8")), "World"); return(CallbackResult.Normal); } chr.MaxHits = ByteConverter.BigEndian.ToInt16(data, 5); chr.Hits = ByteConverter.BigEndian.ToInt16(data, 7); chr.MaxMana = ByteConverter.BigEndian.ToInt16(data, 9); chr.Mana = ByteConverter.BigEndian.ToInt16(data, 11); chr.MaxStamina = ByteConverter.BigEndian.ToInt16(data, 13); chr.Stamina = ByteConverter.BigEndian.ToInt16(data, 15); ObjectChanged(serial, ObjectChangeType.CharUpdated); return(CallbackResult.Normal); } }
static CallbackResult OnCharacterStatus(byte[] data, CallbackResult prevResult) { lock (World.SyncRoot) { PacketReader reader = new PacketReader(data); if (reader.ReadByte() != 0x11) { throw new Exception("Invalid packet passed to OnCharacterStatus."); } ushort blockSize = reader.ReadUInt16(); if (data.Length != blockSize) { Trace.WriteLine(String.Format("BlockSize ({0}) for dynamic packet 0x11 doesn't meet data lenght ({1}).", blockSize, data.Length), "World"); } uint serial = reader.ReadUInt32(); RealCharacter chr = World.FindRealCharacter(serial); if (chr == null) { Trace.WriteLine(String.Format("Cannot update status for unknown character (serial=0x{0:X8}).", serial), "World"); return(CallbackResult.Normal); } chr.Name = reader.ReadAnsiString(30); chr.Hits = reader.ReadInt16(); chr.MaxHits = reader.ReadInt16(); chr.Renamable = reader.ReadByte() > 0; byte more = reader.ReadByte(); if (more > 0) { byte gender = reader.ReadByte(); chr.Strenght = reader.ReadInt16(); chr.Dexterity = reader.ReadInt16(); chr.Intelligence = reader.ReadInt16(); chr.Stamina = reader.ReadInt16(); chr.MaxStamina = reader.ReadInt16(); chr.Mana = reader.ReadInt16(); chr.MaxMana = reader.ReadInt16(); chr.Gold = reader.ReadInt32(); chr.Armor = reader.ReadUInt16(); chr.Weight = reader.ReadUInt16(); } #if WORLDDEBUG Trace.WriteLine(String.Format("Character status updated ({0}).", chr.Description), "World"); #endif ObjectChanged(serial, ObjectChangeType.CharUpdated, true); return(CallbackResult.Normal); } }
internal void Detach() { RealCharacter chr = World.FindRealCharacter(Container); if (chr != null) { chr.Layers[Layer] = 0; Layer = 0; Container = 0; } }
/// <summary> /// Never returns null. /// </summary> internal static RealCharacter GetRealCharacter(uint serial) { lock (World.SyncRoot) { RealCharacter obj = FindRealCharacter(serial); if (obj != null) { return(obj); } else { return(invalidCharacter); } } }
internal static void Add(RealCharacter character) { lock (World.SyncRoot) { if (character == null) { throw new ArgumentNullException("character"); } if (itemList.ContainsKey(character.Serial)) { throw new InternalErrorException("Serial already exists."); } charList.Add(character.Serial, character); } }
static CallbackResult OnLoginConfirm(byte[] data, CallbackResult prevResult) { lock (World.SyncRoot) { if (data[0] != 0x1B) { throw new Exception("Invalid packet passed to OnLoginConfirm."); } bool expected = (World.PlayerSerial == World.InvalidSerial); uint serial = ByteConverter.BigEndian.ToUInt32(data, 1); if (!expected && World.PlayerSerial != serial) { Trace.WriteLine("Invalid serial in LoginConfirm! Packet ignored.", "World"); return(CallbackResult.Normal); } World.PlayerSerial = serial; RealCharacter chr = World.FindRealCharacter(World.PlayerSerial); if (chr == null) { chr = new RealCharacter(World.PlayerSerial); World.Add(chr); } chr.Graphic = ByteConverter.BigEndian.ToUInt16(data, 9); chr.X = ByteConverter.BigEndian.ToUInt16(data, 11); chr.Y = ByteConverter.BigEndian.ToUInt16(data, 13); chr.Z = ByteConverter.BigEndian.ToSByte(data, 16); chr.Direction = ByteConverter.BigEndian.ToByte(data, 17); WalkHandling.ClearStack(); if (expected) { Trace.WriteLine(String.Format("Player logged in. ({0}).", chr), "World"); } else { Trace.WriteLine("Unexpected LoginConfirm packet.", "World"); } 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); } }
static CallbackResult OnCharacterUpdate(byte[] data, CallbackResult prevResult) { lock (World.SyncRoot) { PacketReader reader = new PacketReader(data); if (reader.ReadByte() != 0x77) { throw new Exception("Invalid packet passed to OnCharacterUpdate."); } 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 WORLDDEBUG Debug.WriteLine(String.Format("Character updated ({0}).", chr.Description), "World"); #endif if (newCharacter) { characterAppeared.InvokeAsync(null, new CharacterAppearedEventArgs(serial)); } ObjectChanged(serial, ObjectChangeType.CharUpdated); return(CallbackResult.Normal); } }
static CallbackResult OnLoginConfirm(byte[] data, CallbackResult prevResult) { lock (World.SyncRoot) { if (data[0] != 0x1B) throw new Exception("Invalid packet passed to OnLoginConfirm."); bool expected = (World.PlayerSerial == World.InvalidSerial); uint serial = ByteConverter.BigEndian.ToUInt32(data, 1); if (!expected && World.PlayerSerial != serial) { Trace.WriteLine("Invalid serial in LoginConfirm! Packet ignored.", "World"); return CallbackResult.Normal; } World.PlayerSerial = serial; RealCharacter chr = World.FindRealCharacter(World.PlayerSerial); if (chr == null) { chr = new RealCharacter(World.PlayerSerial); World.Add(chr); } chr.Graphic = ByteConverter.BigEndian.ToUInt16(data, 9); chr.X = ByteConverter.BigEndian.ToUInt16(data, 11); chr.Y = ByteConverter.BigEndian.ToUInt16(data, 13); chr.Z = ByteConverter.BigEndian.ToSByte(data, 16); chr.Direction = ByteConverter.BigEndian.ToByte(data, 17); WalkHandling.ClearStack(); if (expected) Trace.WriteLine(String.Format("Player logged in. ({0}).", chr), "World"); else Trace.WriteLine("Unexpected LoginConfirm packet.", "World"); return CallbackResult.Normal; } }
static CallbackResult OnCharacterUpdate(byte[] data, CallbackResult prevResult) { lock (World.SyncRoot) { PacketReader reader = new PacketReader(data); if (reader.ReadByte() != 0x77) throw new Exception("Invalid packet passed to OnCharacterUpdate."); 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 WORLDDEBUG Debug.WriteLine(String.Format("Character updated ({0}).", chr.Description), "World"); #endif if (newCharacter) characterAppeared.InvokeAsync(null, new CharacterAppearedEventArgs(serial)); ObjectChanged(serial, ObjectChangeType.CharUpdated); 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; } }
/// <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(RealCharacter character) { lock (World.SyncRoot) { if (character == null) throw new ArgumentNullException("character"); if (itemList.ContainsKey(character.Serial)) throw new InternalErrorException("Serial already exists."); charList.Add(character.Serial, character); } }
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); } }