using System; using System.Collections.Concurrent; using System.Linq; namespace ClassicAssist.UO.Objects { public abstract class EntityCollection where T : Entity { public delegate void dCollectionChanged( int totalCount, bool added, T[] entities ); protected ConcurrentDictionary EntityList; protected EntityCollection() : this( short.MaxValue ) { } protected EntityCollection( int capacity ) { EntityList = new ConcurrentDictionary( 16, capacity ); } public T this[ int s ] { get => EntityList.ContainsKey( s ) ? EntityList[s] : null; set => EntityList[s] = value; } public virtual bool Add( T entity ) { bool changed = EntityList.AddOrUpdate( entity.Serial, entity, ( k, v ) => entity ) != null; if ( changed ) { OnCollectionChanged( true, new[] { entity } ); } return changed; } public virtual bool Add( T[] entities ) { bool changed = false; foreach ( T entity in entities ) { if ( EntityList.AddOrUpdate( entity.Serial, entity, ( k, v ) => entity ) == null ) { continue; } changed = true; } if ( changed ) { OnCollectionChanged( true, entities ); } return changed; } protected T[] GetEntities() { T[] entityArray = new T[EntityList.Values.Count]; EntityList.Values.CopyTo( entityArray, 0 ); return entityArray; } public virtual bool Remove( T entity ) { return Remove( entity.Serial ); } public virtual bool Remove( int serial ) { EntityList.TryRemove( serial, out T val ); if ( val != null ) { OnCollectionChanged( false, new[] { val } ); } return val != null; } public virtual bool Remove( T[] entities ) { bool changed = false; foreach ( T entity in entities ) { if ( Remove( entity.Serial ) ) { changed = true; } } return changed; } internal virtual void Clear() { T[] all = EntityList.Values.ToArray(); EntityList.Clear(); OnCollectionChanged( false, all ); } public event dCollectionChanged CollectionChanged; public virtual void OnCollectionChanged( bool added, T[] entities ) { CollectionChanged?.Invoke( EntityList.Count, added, entities ); } public virtual void RemoveByDistance( int maxDistance, int x, int y ) { T[] items = SelectEntities( i => i is Item item && item.Owner == 0 && UOMath.Distance( x, y, item.X, item.Y ) > maxDistance ); if ( items == null ) { return; } bool changed = Remove( items ); if ( changed ) { OnCollectionChanged( false, items ); } } public virtual T SelectEntity( Func func ) { if ( func == null ) { return null; } T entity = EntityList.Select( m => m.Value ).FirstOrDefault( func ); return entity; } public virtual T[] SelectEntities( Func func ) { return EntityList.Select( m => m.Value ).Where( func ).ToArray(); } protected T GetEntity( int key ) { EntityList.TryGetValue( key, out T val ); return val; } } }