finished TraitDictionary. Refactored permanent actor-removal.

This commit is contained in:
Bob
2010-08-15 01:14:06 +12:00
committed by Chris Forbes
parent c0d0636e08
commit 5561ac458b
14 changed files with 102 additions and 71 deletions

View File

@@ -142,7 +142,7 @@ namespace OpenRA
return new RectangleF(loc.X, loc.Y, size.X, size.Y); 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 ) public void QueueActivity( IActivity nextActivity )
{ {
@@ -209,7 +209,17 @@ namespace OpenRA
public void AddTrait( object trait ) 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 );
} }
} }
} }

View File

@@ -12,7 +12,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using OpenRA.FileFormats; using OpenRA.FileFormats;
using System.Diagnostics;
namespace OpenRA namespace OpenRA
{ {
@@ -31,7 +30,7 @@ namespace OpenRA
.GetConstructor( new Type[ 0 ] ).Invoke( new object[ 0 ] ); .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(); var t = val.GetType();
@@ -48,78 +47,107 @@ namespace OpenRA
public bool Contains<T>( Actor actor ) 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 ) 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 ) 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 ) 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 interface ITraitContainer
{ {
void Add( Actor actor, object trait ); void Add( Actor actor, object trait );
void RemoveActor( uint actor );
} }
class TraitContainer<T> : ITraitContainer class TraitContainer<T> : ITraitContainer
{ {
List<uint> actors = new List<uint>(); List<Actor> actors = new List<Actor>();
List<T> traits = new List<T>(); List<T> traits = new List<T>();
public void Add( Actor actor, object trait ) public void Add( Actor actor, object trait )
{ {
var insertIndex = actors.BinarySearchMany( actor.ActorID + 1 ); var insertIndex = actors.BinarySearchMany( actor.ActorID + 1 );
actors.Insert( insertIndex, actor.ActorID ); actors.Insert( insertIndex, actor );
traits.Insert( insertIndex, (T)trait ); traits.Insert( insertIndex, (T)trait );
} }
public T Get( Actor actor ) public T Get( uint actor )
{ {
var index = actors.BinarySearchMany( actor.ActorID ); var index = actors.BinarySearchMany( actor );
if( index >= actors.Count || actors[ index ] != actor.ActorID ) if( index >= actors.Count || actors[ index ].ActorID != actor )
throw new InvalidOperationException( string.Format( "TraitDictionary does not contain instance of type `{0}`", typeof( T ) ) ); 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 ) ) ); throw new InvalidOperationException( string.Format( "TraitDictionary contains multiple instance of type `{0}`", typeof( T ) ) );
else else
return traits[ index ]; return traits[ index ];
} }
public T GetOrDefault( Actor actor ) public T GetOrDefault( uint actor )
{ {
var index = actors.BinarySearchMany( actor.ActorID ); var index = actors.BinarySearchMany( actor );
if( index >= actors.Count || actors[ index ] != actor.ActorID ) if( index >= actors.Count || actors[ index ].ActorID != actor )
return default( T ); 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 ) ) ); throw new InvalidOperationException( string.Format( "TraitDictionary contains multiple instance of type `{0}`", typeof( T ) ) );
else return traits[ index ]; else return traits[ index ];
} }
public IEnumerable<T> GetMultiple( Actor actor ) public IEnumerable<T> GetMultiple( uint actor )
{ {
var index = actors.BinarySearchMany( actor.ActorID ); var index = actors.BinarySearchMany( actor );
while( index < actors.Count && actors[ index ] == actor.ActorID ) while( index < actors.Count && actors[ index ].ActorID == actor )
{ {
yield return traits[ index ]; yield return traits[ index ];
++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 static class ListExts
{ {
public static int BinarySearchMany<T>( this List<T> list, T searchFor ) public static int BinarySearchMany( this List<Actor> list, uint searchFor )
where T : IComparable<T>
{ {
int start = 0; int start = 0;
int end = list.Count; int end = list.Count;
@@ -127,7 +155,7 @@ namespace OpenRA
while( start != end ) while( start != end )
{ {
mid = ( start + end ) / 2; mid = ( start + end ) / 2;
var c = list[ mid ].CompareTo( searchFor ); var c = list[ mid ].ActorID.CompareTo( searchFor );
if( c < 0 ) if( c < 0 )
start = mid + 1; start = mid + 1;
else else

View File

@@ -18,7 +18,7 @@ namespace OpenRA.Traits.Activities
public IActivity Tick(Actor self) public IActivity Tick(Actor self)
{ {
if (isCanceled) return NextActivity; if (isCanceled) return NextActivity;
self.World.AddFrameEndTask(w => w.Remove(self)); self.Destroy();
return null; return null;
} }

View File

@@ -30,7 +30,7 @@ namespace OpenRA.Traits.Activities
foreach (var ns in self.TraitsImplementing<INotifySold>()) foreach (var ns in self.TraitsImplementing<INotifySold>())
ns.Sold(self); ns.Sold(self);
self.World.AddFrameEndTask( _ => self.World.Remove( self ) ); self.Destroy();
} }
public IActivity Tick(Actor self) public IActivity Tick(Actor self)

View File

@@ -173,8 +173,9 @@ namespace OpenRA
Game.viewport.Tick(); Game.viewport.Tick();
Timer.Time(" viewport: {0:0.000}"); Timer.Time(" viewport: {0:0.000}");
while( frameEndActions.Count != 0 ) while (frameEndActions.Count != 0)
frameEndActions.Dequeue()( this ); frameEndActions.Dequeue()(this);
Timer.Time(" frameEndActions: {0:0.000}"); Timer.Time(" frameEndActions: {0:0.000}");
WorldRenderer.Tick(); WorldRenderer.Tick();
@@ -215,9 +216,9 @@ namespace OpenRA
OwnedBy = new Cache<Player, OwnedByCachedView>(p => new OwnedByCachedView(world, world.actors, x => x.Owner == p)); 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 ) static CachedView<Actor, TraitPair<T>> WithTraitInner<T>( Set<Actor> set, TypeDictionary hasTrait )
@@ -233,28 +234,9 @@ namespace OpenRA
return ret; return ret;
} }
public CachedView<Actor, TraitPair<T>> WithTraitMultiple<T>() public IEnumerable<TraitPair<T>> WithTraitMultiple<T>()
{ {
var ret = hasTrait.GetOrDefault<CachedView<Actor, TraitPair<T>>>(); return world.traitDict.ActorsWithTraitMultiple<T>( world );
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 );
}
} }
public class OwnedByCachedView : CachedView<Actor, Actor> public class OwnedByCachedView : CachedView<Actor, Actor>
@@ -275,4 +257,15 @@ namespace OpenRA
public AllQueries Queries; 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 );
}
}
} }

View File

@@ -41,7 +41,7 @@ namespace OpenRA.Mods.Cnc
self.World.AddFrameEndTask( self.World.AddFrameEndTask(
w => w.Add( w => w.Add(
new DelayedAction(info.LingerTime, new DelayedAction(info.LingerTime,
() => w.Remove(self)))); () => self.Destroy())));
} }
} }
} }

View File

@@ -35,7 +35,7 @@ namespace OpenRA.Mods.RA.Activities
foreach (var t in target.TraitsImplementing<INotifyCapture>()) foreach (var t in target.TraitsImplementing<INotifyCapture>())
t.OnCapture(target, self, oldOwner, self.Owner); t.OnCapture(target, self, oldOwner, self.Owner);
w.Remove(self); self.Destroy();
}); });
return NextActivity; return NextActivity;
} }

View File

@@ -26,7 +26,7 @@ namespace OpenRA.Mods.RA.Activities
foreach (var t in target.TraitsImplementing<IAcceptSpy>()) foreach (var t in target.TraitsImplementing<IAcceptSpy>())
t.OnInfiltrate(target, self); t.OnInfiltrate(target, self);
self.World.AddFrameEndTask(w => w.Remove(self)); self.Destroy();
return NextActivity; return NextActivity;
} }

View File

@@ -28,7 +28,7 @@ namespace OpenRA.Mods.RA.Activities
return NextActivity; return NextActivity;
target.InflictDamage(self, -health.MaxHP, null); target.InflictDamage(self, -health.MaxHP, null);
self.World.AddFrameEndTask(w => w.Remove(self)); self.Destroy();
return NextActivity; return NextActivity;
} }

View File

@@ -49,7 +49,7 @@ namespace OpenRA.Mods.RA.Activities
{ {
var selected = w.Selection.Contains(self); var selected = w.Selection.Contains(self);
self.World.Remove(self); self.Destroy();
foreach (var s in sounds) foreach (var s in sounds)
Sound.PlayToPlayer(self.Owner, s, self.CenterLocation); Sound.PlayToPlayer(self.Owner, s, self.CenterLocation);

View File

@@ -62,7 +62,7 @@ namespace OpenRA.Mods.RA
var totalShares = shares.Sum(a => a.Second); var totalShares = shares.Sum(a => a.Second);
var n = self.World.SharedRandom.Next(totalShares); var n = self.World.SharedRandom.Next(totalShares);
self.World.AddFrameEndTask(w => w.Remove(self)); self.Destroy();
foreach (var s in shares) foreach (var s in shares)
if (n < s.Second) if (n < s.Second)
{ {
@@ -76,8 +76,8 @@ namespace OpenRA.Mods.RA
public void Tick(Actor self) public void Tick(Actor self)
{ {
if (++ticks >= self.Info.Traits.Get<CrateInfo>().Lifetime * 25) if( ++ticks >= self.Info.Traits.Get<CrateInfo>().Lifetime * 25 )
self.World.AddFrameEndTask(w => w.Remove(self)); self.Destroy();
} }
public int2 TopLeft { get { return Location; } } public int2 TopLeft { get { return Location; } }

View File

@@ -45,7 +45,7 @@ namespace OpenRA.Mods.RA
self.Kill(self); self.Kill(self);
detonatedBy.Owner.Kills++; detonatedBy.Owner.Kills++;
self.Owner.Deaths++; self.Owner.Deaths++;
w.Remove(self); self.Destroy();
} ); } );
} }
} }

View File

@@ -27,7 +27,7 @@ namespace OpenRA.Mods.RA
{ {
self.World.AddFrameEndTask(w => self.World.AddFrameEndTask(w =>
{ {
w.Remove(self); self.Destroy();
w.CreateActor(info.Actor, new TypeDictionary w.CreateActor(info.Actor, new TypeDictionary
{ {
new LocationInit( self.Location ), new LocationInit( self.Location ),

View File

@@ -65,7 +65,7 @@ namespace OpenRA.Mods.RA
a.QueueActivity(new Fly(order.TargetLocation)); a.QueueActivity(new Fly(order.TargetLocation));
if (flare != null) 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 FlyOffMap { Interruptible = false });
a.QueueActivity(new RemoveSelf()); a.QueueActivity(new RemoveSelf());