finished TraitDictionary. Refactored permanent actor-removal.
This commit is contained in:
@@ -142,7 +142,7 @@ namespace OpenRA
|
||||
return new RectangleF(loc.X, loc.Y, size.X, size.Y);
|
||||
}
|
||||
|
||||
public bool IsInWorld { get; set; }
|
||||
public bool IsInWorld { get; internal set; }
|
||||
|
||||
public void QueueActivity( IActivity nextActivity )
|
||||
{
|
||||
@@ -209,7 +209,17 @@ namespace OpenRA
|
||||
|
||||
public void AddTrait( object trait )
|
||||
{
|
||||
World.traitDict.Add( this, trait );
|
||||
World.traitDict.AddTrait( this, trait );
|
||||
}
|
||||
|
||||
public void Destroy()
|
||||
{
|
||||
World.AddFrameEndTask( w => World.Remove( this ) );
|
||||
}
|
||||
|
||||
~Actor()
|
||||
{
|
||||
World.traitDict.RemoveActor( this );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
@@ -31,7 +30,7 @@ namespace OpenRA
|
||||
.GetConstructor( new Type[ 0 ] ).Invoke( new object[ 0 ] );
|
||||
}
|
||||
|
||||
public void Add( Actor actor, object val )
|
||||
public void AddTrait( Actor actor, object val )
|
||||
{
|
||||
var t = val.GetType();
|
||||
|
||||
@@ -48,78 +47,107 @@ namespace OpenRA
|
||||
|
||||
public bool Contains<T>( Actor actor )
|
||||
{
|
||||
return ( (TraitContainer<T>)InnerGet( typeof( T ) ) ).GetMultiple( actor ).Count() != 0;
|
||||
return ( (TraitContainer<T>)InnerGet( typeof( T ) ) ).GetMultiple( actor.ActorID ).Count() != 0;
|
||||
}
|
||||
|
||||
public T Get<T>( Actor actor )
|
||||
{
|
||||
return ( (TraitContainer<T>)InnerGet( typeof( T ) ) ).Get( actor );
|
||||
return ( (TraitContainer<T>)InnerGet( typeof( T ) ) ).Get( actor.ActorID );
|
||||
}
|
||||
|
||||
public T GetOrDefault<T>( Actor actor )
|
||||
{
|
||||
return ( (TraitContainer<T>)InnerGet( typeof( T ) ) ).GetOrDefault( actor );
|
||||
return ( (TraitContainer<T>)InnerGet( typeof( T ) ) ).GetOrDefault( actor.ActorID );
|
||||
}
|
||||
|
||||
public IEnumerable<T> WithInterface<T>( Actor actor )
|
||||
{
|
||||
return ( (TraitContainer<T>)InnerGet( typeof( T ) ) ).GetMultiple( actor );
|
||||
return ( (TraitContainer<T>)InnerGet( typeof( T ) ) ).GetMultiple( actor.ActorID );
|
||||
}
|
||||
|
||||
public IEnumerable<TraitPair<T>> ActorsWithTraitMultiple<T>( World world )
|
||||
{
|
||||
return ( (TraitContainer<T>)InnerGet( typeof( T ) ) ).All().Where( x => x.Actor.IsInWorld );
|
||||
}
|
||||
|
||||
public void RemoveActor( Actor a )
|
||||
{
|
||||
foreach( var t in traits )
|
||||
t.Value.RemoveActor( a.ActorID );
|
||||
}
|
||||
|
||||
interface ITraitContainer
|
||||
{
|
||||
void Add( Actor actor, object trait );
|
||||
void RemoveActor( uint actor );
|
||||
}
|
||||
|
||||
class TraitContainer<T> : ITraitContainer
|
||||
{
|
||||
List<uint> actors = new List<uint>();
|
||||
List<Actor> actors = new List<Actor>();
|
||||
List<T> traits = new List<T>();
|
||||
|
||||
public void Add( Actor actor, object trait )
|
||||
{
|
||||
var insertIndex = actors.BinarySearchMany( actor.ActorID + 1 );
|
||||
actors.Insert( insertIndex, actor.ActorID );
|
||||
actors.Insert( insertIndex, actor );
|
||||
traits.Insert( insertIndex, (T)trait );
|
||||
}
|
||||
|
||||
public T Get( Actor actor )
|
||||
public T Get( uint actor )
|
||||
{
|
||||
var index = actors.BinarySearchMany( actor.ActorID );
|
||||
if( index >= actors.Count || actors[ index ] != actor.ActorID )
|
||||
var index = actors.BinarySearchMany( actor );
|
||||
if( index >= actors.Count || actors[ index ].ActorID != actor )
|
||||
throw new InvalidOperationException( string.Format( "TraitDictionary does not contain instance of type `{0}`", typeof( T ) ) );
|
||||
else if( index + 1 < actors.Count && actors[ index + 1 ] == actor.ActorID )
|
||||
else if( index + 1 < actors.Count && actors[ index + 1 ].ActorID == actor )
|
||||
throw new InvalidOperationException( string.Format( "TraitDictionary contains multiple instance of type `{0}`", typeof( T ) ) );
|
||||
else
|
||||
return traits[ index ];
|
||||
}
|
||||
|
||||
public T GetOrDefault( Actor actor )
|
||||
public T GetOrDefault( uint actor )
|
||||
{
|
||||
var index = actors.BinarySearchMany( actor.ActorID );
|
||||
if( index >= actors.Count || actors[ index ] != actor.ActorID )
|
||||
var index = actors.BinarySearchMany( actor );
|
||||
if( index >= actors.Count || actors[ index ].ActorID != actor )
|
||||
return default( T );
|
||||
else if( index + 1 < actors.Count && actors[ index + 1 ] == actor.ActorID )
|
||||
else if( index + 1 < actors.Count && actors[ index + 1 ].ActorID == actor )
|
||||
throw new InvalidOperationException( string.Format( "TraitDictionary contains multiple instance of type `{0}`", typeof( T ) ) );
|
||||
else return traits[ index ];
|
||||
}
|
||||
|
||||
public IEnumerable<T> GetMultiple( Actor actor )
|
||||
public IEnumerable<T> GetMultiple( uint actor )
|
||||
{
|
||||
var index = actors.BinarySearchMany( actor.ActorID );
|
||||
while( index < actors.Count && actors[ index ] == actor.ActorID )
|
||||
var index = actors.BinarySearchMany( actor );
|
||||
while( index < actors.Count && actors[ index ].ActorID == actor )
|
||||
{
|
||||
yield return traits[ index ];
|
||||
++index;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<TraitPair<T>> All()
|
||||
{
|
||||
for( int i = 0 ; i < actors.Count ; i++ )
|
||||
yield return new TraitPair<T> { Actor = actors[ i ], Trait = traits[ i ] };
|
||||
}
|
||||
|
||||
public void RemoveActor( uint actor )
|
||||
{
|
||||
for( int i = actors.Count - 1 ; i >= 0 ; i-- )
|
||||
{
|
||||
if( actors[ i ].ActorID == actor )
|
||||
{
|
||||
actors.RemoveAt( i );
|
||||
traits.RemoveAt( i );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class ListExts
|
||||
{
|
||||
public static int BinarySearchMany<T>( this List<T> list, T searchFor )
|
||||
where T : IComparable<T>
|
||||
public static int BinarySearchMany( this List<Actor> list, uint searchFor )
|
||||
{
|
||||
int start = 0;
|
||||
int end = list.Count;
|
||||
@@ -127,7 +155,7 @@ namespace OpenRA
|
||||
while( start != end )
|
||||
{
|
||||
mid = ( start + end ) / 2;
|
||||
var c = list[ mid ].CompareTo( searchFor );
|
||||
var c = list[ mid ].ActorID.CompareTo( searchFor );
|
||||
if( c < 0 )
|
||||
start = mid + 1;
|
||||
else
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace OpenRA.Traits.Activities
|
||||
public IActivity Tick(Actor self)
|
||||
{
|
||||
if (isCanceled) return NextActivity;
|
||||
self.World.AddFrameEndTask(w => w.Remove(self));
|
||||
self.Destroy();
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace OpenRA.Traits.Activities
|
||||
|
||||
foreach (var ns in self.TraitsImplementing<INotifySold>())
|
||||
ns.Sold(self);
|
||||
self.World.AddFrameEndTask( _ => self.World.Remove( self ) );
|
||||
self.Destroy();
|
||||
}
|
||||
|
||||
public IActivity Tick(Actor self)
|
||||
|
||||
@@ -173,8 +173,9 @@ namespace OpenRA
|
||||
Game.viewport.Tick();
|
||||
Timer.Time(" viewport: {0:0.000}");
|
||||
|
||||
while( frameEndActions.Count != 0 )
|
||||
frameEndActions.Dequeue()( this );
|
||||
while (frameEndActions.Count != 0)
|
||||
frameEndActions.Dequeue()(this);
|
||||
|
||||
Timer.Time(" frameEndActions: {0:0.000}");
|
||||
|
||||
WorldRenderer.Tick();
|
||||
@@ -215,9 +216,9 @@ namespace OpenRA
|
||||
OwnedBy = new Cache<Player, OwnedByCachedView>(p => new OwnedByCachedView(world, world.actors, x => x.Owner == p));
|
||||
}
|
||||
|
||||
public CachedView<Actor, TraitPair<T>> WithTrait<T>()
|
||||
public IEnumerable<TraitPair<T>> WithTrait<T>()
|
||||
{
|
||||
return WithTraitInner<T>( world.actors, hasTrait );
|
||||
return world.traitDict.ActorsWithTraitMultiple<T>( world );
|
||||
}
|
||||
|
||||
static CachedView<Actor, TraitPair<T>> WithTraitInner<T>( Set<Actor> set, TypeDictionary hasTrait )
|
||||
@@ -233,28 +234,9 @@ namespace OpenRA
|
||||
return ret;
|
||||
}
|
||||
|
||||
public CachedView<Actor, TraitPair<T>> WithTraitMultiple<T>()
|
||||
public IEnumerable<TraitPair<T>> WithTraitMultiple<T>()
|
||||
{
|
||||
var ret = hasTrait.GetOrDefault<CachedView<Actor, TraitPair<T>>>();
|
||||
if( ret != null )
|
||||
return ret;
|
||||
ret = new CachedView<Actor, TraitPair<T>>(
|
||||
world.actors,
|
||||
x => x.HasTrait<T>(),
|
||||
x => x.TraitsImplementing<T>().Select( t => new TraitPair<T> { Actor = x, Trait = t } ) );
|
||||
hasTrait.Add( ret );
|
||||
return ret;
|
||||
}
|
||||
|
||||
public struct TraitPair<T>
|
||||
{
|
||||
public Actor Actor;
|
||||
public T Trait;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "{0}->{1}".F( Actor.Info.Name, Trait.GetType().Name );
|
||||
}
|
||||
return world.traitDict.ActorsWithTraitMultiple<T>( world );
|
||||
}
|
||||
|
||||
public class OwnedByCachedView : CachedView<Actor, Actor>
|
||||
@@ -275,4 +257,15 @@ namespace OpenRA
|
||||
|
||||
public AllQueries Queries;
|
||||
}
|
||||
|
||||
public struct TraitPair<T>
|
||||
{
|
||||
public Actor Actor;
|
||||
public T Trait;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "{0}->{1}".F( Actor.Info.Name, Trait.GetType().Name );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace OpenRA.Mods.Cnc
|
||||
self.World.AddFrameEndTask(
|
||||
w => w.Add(
|
||||
new DelayedAction(info.LingerTime,
|
||||
() => w.Remove(self))));
|
||||
() => self.Destroy())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
foreach (var t in target.TraitsImplementing<INotifyCapture>())
|
||||
t.OnCapture(target, self, oldOwner, self.Owner);
|
||||
|
||||
w.Remove(self);
|
||||
self.Destroy();
|
||||
});
|
||||
return NextActivity;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
foreach (var t in target.TraitsImplementing<IAcceptSpy>())
|
||||
t.OnInfiltrate(target, self);
|
||||
|
||||
self.World.AddFrameEndTask(w => w.Remove(self));
|
||||
self.Destroy();
|
||||
|
||||
return NextActivity;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
return NextActivity;
|
||||
|
||||
target.InflictDamage(self, -health.MaxHP, null);
|
||||
self.World.AddFrameEndTask(w => w.Remove(self));
|
||||
self.Destroy();
|
||||
|
||||
return NextActivity;
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
{
|
||||
var selected = w.Selection.Contains(self);
|
||||
|
||||
self.World.Remove(self);
|
||||
self.Destroy();
|
||||
foreach (var s in sounds)
|
||||
Sound.PlayToPlayer(self.Owner, s, self.CenterLocation);
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace OpenRA.Mods.RA
|
||||
var totalShares = shares.Sum(a => a.Second);
|
||||
var n = self.World.SharedRandom.Next(totalShares);
|
||||
|
||||
self.World.AddFrameEndTask(w => w.Remove(self));
|
||||
self.Destroy();
|
||||
foreach (var s in shares)
|
||||
if (n < s.Second)
|
||||
{
|
||||
@@ -76,8 +76,8 @@ namespace OpenRA.Mods.RA
|
||||
public void Tick(Actor self)
|
||||
{
|
||||
|
||||
if (++ticks >= self.Info.Traits.Get<CrateInfo>().Lifetime * 25)
|
||||
self.World.AddFrameEndTask(w => w.Remove(self));
|
||||
if( ++ticks >= self.Info.Traits.Get<CrateInfo>().Lifetime * 25 )
|
||||
self.Destroy();
|
||||
}
|
||||
|
||||
public int2 TopLeft { get { return Location; } }
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace OpenRA.Mods.RA
|
||||
self.Kill(self);
|
||||
detonatedBy.Owner.Kills++;
|
||||
self.Owner.Deaths++;
|
||||
w.Remove(self);
|
||||
self.Destroy();
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace OpenRA.Mods.RA
|
||||
{
|
||||
self.World.AddFrameEndTask(w =>
|
||||
{
|
||||
w.Remove(self);
|
||||
self.Destroy();
|
||||
w.CreateActor(info.Actor, new TypeDictionary
|
||||
{
|
||||
new LocationInit( self.Location ),
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace OpenRA.Mods.RA
|
||||
a.QueueActivity(new Fly(order.TargetLocation));
|
||||
|
||||
if (flare != null)
|
||||
a.QueueActivity(new CallFunc(() => Owner.World.AddFrameEndTask(_w => _w.Remove(flare))));
|
||||
a.QueueActivity(new CallFunc(() => flare.Destroy()));
|
||||
|
||||
a.QueueActivity(new FlyOffMap { Interruptible = false });
|
||||
a.QueueActivity(new RemoveSelf());
|
||||
|
||||
Reference in New Issue
Block a user