/// <summary> /// Enumerates over every entities. /// </summary> /// <returns></returns> private IEnumerable <CGObject_C> Enumerate() { var currentObject = (uint)Game.Read <IntPtr>(_currentManager + FirstObject, true); _localGUID = Game.Read <ulong>(_currentManager + LocalGUID, true); while (currentObject != uint.MinValue && currentObject % 2 == uint.MinValue) { CGObject_C entityObject; switch (Game.Read <ObjectType>((int)(currentObject + 0x14), true)) { default: case ObjectType.Object: entityObject = new CGObject_C(new IntPtr(currentObject)); break; case ObjectType.Unit: entityObject = new CGUnit_C(new IntPtr(currentObject)); break; case ObjectType.Player: entityObject = new CGPlayer_C(new IntPtr(currentObject)); break; case ObjectType.GameObject: entityObject = new CGGameObject_C(new IntPtr(currentObject)); break; case ObjectType.Container: entityObject = new CGContainer_C(new IntPtr(currentObject)); break; case ObjectType.Item: entityObject = new CGItem_C(new IntPtr(currentObject)); break; } yield return(entityObject); currentObject = (uint)Game.Read <IntPtr>((int)(currentObject + NextObject), true); } }
/// <summary> /// Called every few milliseconds. This function updates the local cache of known entities. /// </summary> public void Update() { // 8B 34 8A 8B 0D ?? ?? ?? ?? 89 81 ?? ?? ?? ?? 8B 15 ?? ?? ?? ?? // http://i.imgur.com/LIGX6AY.png _currentManager = Game.Read <IntPtr>(Game.Read <int>(0x009BE7E0) + 0x463C, true); _localGUID = Game.Read <ulong>(_currentManager + 0xC8, true); CurrentMap = Game.Read <int>(_currentManager + 0xD4, true); foreach (var oldEntitiy in _entities) { oldEntitiy.Value.BaseAddressUpdated = false; } foreach (var newEntityPtr in Enumerate()) { var updateFieldOffset = Game.Read <IntPtr>(newEntityPtr + 0xC, true); var objectGuid = Game.Read <ObjectGuid>(updateFieldOffset, true); if (_entities.ContainsKey(objectGuid)) { _entities[objectGuid].UpdateBaseAddress(newEntityPtr); OnEntityUpdated?.Invoke(_entities[objectGuid]); } else { switch (Game.Read <ObjectType>(newEntityPtr + 0x14, true)) { default: case ObjectType.Object: _entities[objectGuid] = new CGObject_C(newEntityPtr); break; case ObjectType.Unit: _entities[objectGuid] = new CGUnit_C(newEntityPtr); break; case ObjectType.Player: _entities[objectGuid] = new CGPlayer_C(newEntityPtr); break; case ObjectType.GameObject: _entities[objectGuid] = new CGGameObject_C(newEntityPtr); break; case ObjectType.Container: _entities[objectGuid] = new CGContainer_C(newEntityPtr); break; case ObjectType.Item: _entities[objectGuid] = new CGItem_C(newEntityPtr); break; } OnEntitySpawn?.Invoke(_entities[objectGuid]); _entities[objectGuid].OnSpawn(); } } foreach (var removalKey in _entities.Where(kv => !kv.Value.BaseAddressUpdated).Select(kv => kv.Key).ToList()) { OnEntityDespawn?.Invoke(_entities[removalKey]); _entities[removalKey].OnDespawn(); _entities.Remove(removalKey); } OnWorldUpdate?.Invoke(); }