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);
}
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 );
}
}
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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)

View File

@@ -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 );
}
}
}

View File

@@ -41,7 +41,7 @@ namespace OpenRA.Mods.Cnc
self.World.AddFrameEndTask(
w => w.Add(
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>())
t.OnCapture(target, self, oldOwner, self.Owner);
w.Remove(self);
self.Destroy();
});
return NextActivity;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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; } }

View File

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

View File

@@ -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 ),

View File

@@ -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());