So I was thinking.. why make local copy of all objects in object manager each x seconds when we can directly interate through them? Yes, saving local copy every x seconds and then work with it is probably in most cases faster, but I dont really need to loop through whole array that often so it makes big difference.
My projects is just at begining, so I have only defined BaseObject, Unit and Player, but I think everyone who reads this section can write those objects on its own. Also class MemoryManager is just little helper that allows me to read with "reader.xxx" instead of "WowClient.Reader.xxx" cuz I dont want to make reader static nor keep reference in every class.Code:public class BaseObjectCollection : IEnumerable<BaseObject> { internal BaseObjectCollection( uint firstNodeAddress ) { this.firstNodeAddress = firstNodeAddress; } private uint firstNodeAddress; public BaseObject FindByGuid( ulong guid ) { foreach ( BaseObject obj in this ) if ( obj.Guid == guid ) return obj; return null; } #region IEnumerable public IEnumerator<BaseObject> GetEnumerator() { return new BaseObjectCollectionEnumerator( firstNodeAddress ); } IEnumerator IEnumerable.GetEnumerator() { return new BaseObjectCollectionEnumerator( firstNodeAddress ); } #endregion } public class BaseObjectCollectionEnumerator : MemoryManager, IEnumerator<BaseObject> { private const uint nextNodeOffset = 0x3c; private const uint guidOffset = 0x30; private const uint typeOffset = 0x14; internal BaseObjectCollectionEnumerator( uint firstNodeAddress ) { this.firstNodeAddress = firstNodeAddress; } private uint firstNodeAddress; private uint lastNodeAddress; private BaseObject current; #region IEnumerator public void Reset() { current = null; lastNodeAddress = firstNodeAddress; } public bool MoveNext() { uint pCurrent; if ( current == null ) pCurrent = firstNodeAddress; else pCurrent = reader.ReadUInt( ( IntPtr )( lastNodeAddress + nextNodeOffset ) ); if ( pCurrent == 0 || pCurrent % 2 != 0 ) return false; lastNodeAddress = pCurrent; ulong guid = reader.ReadULong( ( IntPtr )( pCurrent + guidOffset ) ); BaseObjectType type = ( BaseObjectType )reader.ReadUInt( ( IntPtr )( pCurrent + typeOffset ) ); switch ( type ) { case BaseObjectType.Container: current = new BaseObject( pCurrent ); break; case BaseObjectType.Corpse: current = new BaseObject( pCurrent ); break; case BaseObjectType.DynamicObject: current = new BaseObject( pCurrent ); break; case BaseObjectType.GameObject: current = new BaseObject( pCurrent ); break; case BaseObjectType.Item: current = new BaseObject( pCurrent ); break; case BaseObjectType.Player: current = new Player( pCurrent ); break; case BaseObjectType.Unit: current = new Unit( pCurrent ); break; default: throw new Exception( "Unknown object type " + type ); } return true; } public BaseObject Current { get { return current; } } object IEnumerator.Current { get { return current; } } #endregion #region IDisposable public void Dispose() { current = null; } #endregion } public enum BaseObjectType { Item = 1, Container = 2, Unit = 3, Player = 4, GameObject = 5, DynamicObject = 6, Corpse = 7 }
Is there something that I forgot, that makes this way of accessing objects bad?