1+ using System . Diagnostics . CodeAnalysis ;
12using Intersect . Client . Core ;
23using Intersect . Client . Entities . Events ;
34using Intersect . Client . Entities . Projectiles ;
@@ -28,10 +29,8 @@ public partial class Entity : IEntity
2829{
2930 public int AnimationFrame { get ; set ; }
3031
31- //Entity Animations
32- public readonly List < Animation > Animations = [ ] ;
33-
34- public readonly Dictionary < AnimationSource , Animation > AnimationsBySource = [ ] ;
32+ private readonly List < Animation > _animations = [ ] ;
33+ private readonly Dictionary < AnimationSource , Animation > _animationsBySource = [ ] ;
3534
3635 //Animation Timer (for animated sprites)
3736 public long AnimationTimer { get ; set ; }
@@ -67,6 +66,8 @@ public partial class Entity : IEntity
6766
6867 private Guid [ ] _equipment = new Guid [ Options . Instance . Equipment . Slots . Count ] ;
6968
69+ public bool HasAnimations => _animations . Count > 0 ;
70+
7071 public Guid [ ] Equipment
7172 {
7273 get => _equipment ;
@@ -375,7 +376,7 @@ public virtual void Load(EntityPacket? packet)
375376 }
376377 }
377378
378- foreach ( var anim in Animations )
379+ foreach ( var anim in _animations )
379380 {
380381 animsToClear . Add ( anim ) ;
381382 if ( ! anim . InfiniteLoop )
@@ -405,7 +406,7 @@ public virtual void Load(EntityPacket? packet)
405406 }
406407 }
407408
408- ClearAnimations ( animsToClear ) ;
409+ RemoveAnimations ( animsToClear ) ;
409410 AddAnimations ( animsToAdd ) ;
410411
411412 Vital = packet . Vital ;
@@ -479,11 +480,11 @@ public virtual void Load(EntityPacket? packet)
479480 }
480481 }
481482
482- public void AddAnimations ( List < AnimationBase > anims )
483+ public void AddAnimations ( List < AnimationBase > animationDescriptors )
483484 {
484- foreach ( var anim in anims )
485+ foreach ( var animationDescriptor in animationDescriptors )
485486 {
486- Animations . Add ( new Animation ( anim , true , false , - 1 , this ) ) ;
487+ TryAddAnimation ( new Animation ( animationDescriptor , true , false , - 1 , this ) ) ;
487488 }
488489 }
489490
@@ -515,16 +516,19 @@ public virtual bool IsAllyOf(Player en)
515516 return false ;
516517 }
517518
518- public void ClearAnimations ( List < Animation > ? anims )
519+ public void ClearAnimations ( ) => RemoveAnimations ( _animations ) ;
520+
521+ public void RemoveAnimations ( IEnumerable < Animation > animations , bool dispose = true )
519522 {
520- anims ??= Animations ;
521- if ( anims . Count > 0 )
523+ var animationsToRemove = animations . ToArray ( ) ;
524+ foreach ( var animation in animationsToRemove )
522525 {
523- for ( var i = 0 ; i < anims . Count ; i ++ )
526+ if ( dispose )
524527 {
525- anims [ i ] . Dispose ( ) ;
526- _ = Animations . Remove ( anims [ i ] ) ;
528+ animation . Dispose ( ) ;
527529 }
530+
531+ _ = TryRemoveAnimation ( animation ) ;
528532 }
529533 }
530534
@@ -537,7 +541,7 @@ public virtual void Dispose()
537541 _ = RenderList . Remove ( this ) ;
538542 }
539543
540- ClearAnimations ( null ) ;
544+ ClearAnimations ( ) ;
541545 GC . SuppressFinalize ( this ) ;
542546 mDisposed = true ;
543547 }
@@ -758,6 +762,7 @@ public virtual bool Update()
758762 {
759763 for ( var z = 0 ; z < Options . Instance . Equipment . Slots . Count ; z ++ )
760764 {
765+ var equipmentAnimation = EquipmentAnimations [ z ] ;
761766 if ( Equipment [ z ] != Guid . Empty && ( this != Globals . Me || MyEquipment [ z ] < Options . Instance . Player . MaxInventory ) )
762767 {
763768 var itemId = Guid . Empty ;
@@ -774,47 +779,30 @@ public virtual bool Update()
774779 itemId = Equipment [ z ] ;
775780 }
776781
777- var itm = ItemBase . Get ( itemId ) ;
778- AnimationBase ? anim = null ;
779- if ( itm != null )
782+ if ( ItemBase . TryGet ( itemId , out var itemDescriptor ) &&
783+ itemDescriptor . EquipmentAnimation is { } animationDescriptor )
780784 {
781- anim = itm . EquipmentAnimation ;
782- }
783-
784- if ( anim != null )
785- {
786- if ( EquipmentAnimations [ z ] != null &&
787- ( EquipmentAnimations [ z ] ! . MyBase != anim || EquipmentAnimations [ z ] ! . Disposed ( ) ) )
785+ if ( equipmentAnimation != null &&
786+ ( equipmentAnimation . MyBase != animationDescriptor || equipmentAnimation . IsDisposed ) )
788787 {
789- EquipmentAnimations [ z ] ! . Dispose ( ) ;
790- _ = Animations . Remove ( EquipmentAnimations [ z ] ! ) ;
788+ TryRemoveAnimation ( equipmentAnimation , dispose : true ) ;
791789 EquipmentAnimations [ z ] = null ;
792790 }
793791
794- if ( EquipmentAnimations [ z ] == null )
795- {
796- EquipmentAnimations [ z ] = new Animation ( anim , true , true , - 1 , this ) ;
797- Animations . Add ( EquipmentAnimations [ z ] ! ) ;
798- }
792+ equipmentAnimation = new Animation ( animationDescriptor , true , true , - 1 , this ) ;
793+ EquipmentAnimations [ z ] = equipmentAnimation ;
794+ _animations . Add ( equipmentAnimation ) ;
799795 }
800- else
796+ else if ( equipmentAnimation != null )
801797 {
802- if ( EquipmentAnimations [ z ] != null )
803- {
804- EquipmentAnimations [ z ] ! . Dispose ( ) ;
805- _ = Animations . Remove ( EquipmentAnimations [ z ] ! ) ;
806- EquipmentAnimations [ z ] = null ;
807- }
798+ TryRemoveAnimation ( equipmentAnimation , dispose : true ) ;
799+ EquipmentAnimations [ z ] = null ;
808800 }
809801 }
810- else
802+ else if ( equipmentAnimation != null )
811803 {
812- if ( EquipmentAnimations [ z ] != null )
813- {
814- EquipmentAnimations [ z ] ! . Dispose ( ) ;
815- _ = Animations . Remove ( EquipmentAnimations [ z ] ! ) ;
816- EquipmentAnimations [ z ] = null ;
817- }
804+ TryRemoveAnimation ( equipmentAnimation , dispose : true ) ;
805+ EquipmentAnimations [ z ] = null ;
818806 }
819807 }
820808 }
@@ -840,30 +828,30 @@ public virtual bool Update()
840828
841829 CalculateOrigin ( ) ;
842830
843- List < Animation > ? animsToRemove = null ;
844- foreach ( var animInstance in Animations )
831+ List < Animation > ? disposedAnimations = null ;
832+ foreach ( var animation in _animations )
845833 {
846- animInstance . Update ( ) ;
834+ animation . Update ( ) ;
847835
848836 //If disposed mark to be removed and continue onward
849- if ( animInstance . Disposed ( ) )
837+ if ( animation . IsDisposed )
850838 {
851- animsToRemove ??= [ ] ;
852- animsToRemove . Add ( animInstance ) ;
839+ disposedAnimations ??= [ ] ;
840+ disposedAnimations . Add ( animation ) ;
853841 continue ;
854842 }
855843
856844 if ( IsStealthed || IsHidden )
857845 {
858- animInstance . Hide ( ) ;
846+ animation . Hide ( ) ;
859847 }
860848 else
861849 {
862- animInstance . Show ( ) ;
850+ animation . Show ( ) ;
863851 }
864852
865- var animationDirection = animInstance . AutoRotate ? Dir : default ;
866- animInstance . SetPosition (
853+ var animationDirection = animation . AutoRotate ? Dir : default ;
854+ animation . SetPosition (
867855 ( int ) Math . Ceiling ( Center . X ) ,
868856 ( int ) Math . Ceiling ( Center . Y ) ,
869857 X ,
@@ -873,12 +861,9 @@ public virtual bool Update()
873861 ) ;
874862 }
875863
876- if ( animsToRemove != null )
864+ if ( disposedAnimations != null )
877865 {
878- foreach ( var anim in animsToRemove )
879- {
880- _ = Animations . Remove ( anim ) ;
881- }
866+ RemoveAnimations ( disposedAnimations ) ;
882867 }
883868
884869 mLastUpdate = Timing . Global . Milliseconds ;
@@ -888,6 +873,79 @@ public virtual bool Update()
888873 return true ;
889874 }
890875
876+ public bool TryAddAnimation ( Animation animation , AnimationSource animationSource = default )
877+ {
878+ if ( animationSource != default )
879+ {
880+ if ( _animationsBySource . TryGetValue ( animationSource , out var existingAnimation ) )
881+ {
882+ if ( ! TryRemoveAnimation ( existingAnimation , animationSource ) )
883+ {
884+ return false ;
885+ }
886+ }
887+ }
888+
889+ _animationsBySource [ animationSource ] = animation ;
890+ _animations . Add ( animation ) ;
891+ return true ;
892+ }
893+
894+ public bool TryRemoveAnimation ( AnimationSource animationSource , bool dispose = false ) => TryRemoveAnimation (
895+ animationSource : animationSource ,
896+ dispose : dispose ,
897+ animation : out _
898+ ) ;
899+
900+ public bool TryRemoveAnimation ( AnimationSource animationSource , [ NotNullWhen ( true ) ] out Animation ? animation ) =>
901+ TryRemoveAnimation ( animationSource : animationSource , dispose : false , animation : out animation ) ;
902+
903+ public bool TryRemoveAnimation (
904+ AnimationSource animationSource ,
905+ bool dispose ,
906+ [ NotNullWhen ( true ) ] out Animation ? animation
907+ )
908+ {
909+ if ( ! _animationsBySource . Remove ( animationSource , out animation ) )
910+ {
911+ return false ;
912+ }
913+
914+ _animations . Remove ( animation ) ;
915+
916+ if ( dispose )
917+ {
918+ animation . Dispose ( ) ;
919+ }
920+
921+ return true ;
922+ }
923+
924+ public bool RemoveAnimationIfExists ( AnimationSource animationSource , bool dispose = false )
925+ {
926+ return ! _animationsBySource . ContainsKey ( animationSource ) ||
927+ TryRemoveAnimation ( animationSource : animationSource , dispose : dispose ) ;
928+ }
929+
930+ public bool TryRemoveAnimation ( Animation animation , bool dispose = false ) => TryRemoveAnimation (
931+ animation : animation ,
932+ animationSource : animation . Source ,
933+ dispose : dispose
934+ ) ;
935+
936+ public bool TryRemoveAnimation ( Animation animation , AnimationSource animationSource , bool dispose = false )
937+ {
938+ var removedFromSourceLookup = animationSource != default && _animationsBySource . Remove ( animationSource ) ;
939+ var removedFromList = _animations . Remove ( animation ) ;
940+
941+ if ( dispose )
942+ {
943+ animation . Dispose ( ) ;
944+ }
945+
946+ return removedFromList || removedFromSourceLookup ;
947+ }
948+
891949 public virtual int CalculateAttackTime ( )
892950 {
893951 //If this is an npc we don't know it's attack time. Luckily the server provided it!
0 commit comments