diff --git a/OpenRa.DataStructures/OpenRa.DataStructures.csproj b/OpenRa.DataStructures/OpenRa.DataStructures.csproj index 8da1f21edd..b0d2c9ca21 100644 --- a/OpenRa.DataStructures/OpenRa.DataStructures.csproj +++ b/OpenRa.DataStructures/OpenRa.DataStructures.csproj @@ -33,6 +33,10 @@ prompt + + False + ..\Ijw.DirectX\Release\IjwFramework.dll + 3.5 diff --git a/OpenRa.DataStructures/TypeDictionary.cs b/OpenRa.DataStructures/TypeDictionary.cs index 574e624cbe..e4309999bd 100755 --- a/OpenRa.DataStructures/TypeDictionary.cs +++ b/OpenRa.DataStructures/TypeDictionary.cs @@ -1,50 +1,56 @@ using System; using System.Collections.Generic; -using System.Text; +using System.Linq; +using System.Reflection; +using IjwFramework.Collections; namespace OpenRa { public class TypeDictionary { - Dictionary inner = new Dictionary(); - - public void Add( Type t, object val ) - { - inner.Add( t, val ); - } + Cache> innerInherit = new Cache>( _ => new List() ); public void Add( object val ) { - Add( val.GetType(), val ); - } + var t = val.GetType(); - public void Remove() - { - inner.Remove( typeof( T ) ); + foreach( var i in t.GetInterfaces() ) + innerInherit[ i ].Add( val ); + foreach( var tt in t.BaseTypes() ) + innerInherit[ tt ].Add( val ); } public bool Contains() { - return inner.ContainsKey( typeof( T ) ); + return innerInherit.Keys.Contains( typeof( T ) ); } public T Get() { - return (T)inner[ typeof( T ) ]; + var l = innerInherit[ typeof( T ) ]; + if( l.Count == 1 ) + return (T)l[ 0 ]; + else if( l.Count == 0 ) + throw new InvalidOperationException( string.Format( "TypeDictionary does not contain instance of type `{0}`", typeof( T ) ) ); + else + throw new InvalidOperationException( string.Format( "TypeDictionary contains multiple instance of type `{0}`", typeof( T ) ) ); } public T GetOrDefault() { - object o = null; - inner.TryGetValue(typeof(T), out o); - return (T)o; + var l = innerInherit[ typeof( T ) ]; + if( l.Count == 1 ) + return (T)l[ 0 ]; + else if( l.Count == 0 ) + return default( T ); + else + throw new InvalidOperationException( string.Format( "TypeDictionary contains multiple instance of type `{0}`", typeof( T ) ) ); } public IEnumerable WithInterface() { - foreach( var i in inner ) - if( i.Value is T ) - yield return (T)i.Value; + foreach( var i in innerInherit[ typeof( T ) ] ) + yield return (T)i; } public IEnumerator GetEnumerator() @@ -52,4 +58,16 @@ namespace OpenRa return WithInterface().GetEnumerator(); } } + + static class TypeExts + { + public static IEnumerable BaseTypes( this Type t ) + { + while( t != null ) + { + yield return t; + t = t.BaseType; + } + } + } } diff --git a/OpenRa.Game/Combat.cs b/OpenRa.Game/Combat.cs index 241f6c9852..2147aaceb3 100644 --- a/OpenRa.Game/Combat.cs +++ b/OpenRa.Game/Combat.cs @@ -49,7 +49,7 @@ namespace OpenRa.Game var distance = (target.CenterLocation - loc).Length*1/24f; var rawDamage = weapon.Damage * (float)Math.Exp(-distance / warhead.Spread); - var multiplier = warhead.EffectivenessAgainst(target.Info.Traits.WithInterface().First().Armor); + var multiplier = warhead.EffectivenessAgainst(target.Info.Traits.Get().Armor); return rawDamage * multiplier; } @@ -59,7 +59,7 @@ namespace OpenRa.Game var warhead = Rules.WarheadInfo[weapon.Warhead]; var unit = target.traits.GetOrDefault(); - if (warhead.EffectivenessAgainst(target.Info.Traits.WithInterface().First().Armor) <= 0) + if (warhead.EffectivenessAgainst(target.Info.Traits.Get().Armor) <= 0) return false; if (target.traits.Contains()) @@ -76,7 +76,7 @@ namespace OpenRa.Game public static bool HasAnyValidWeapons(Actor self, Actor target) { - var info = self.Info.Traits.WithInterface().First(); + var info = self.Info.Traits.Get(); if (info.PrimaryWeapon != null && WeaponValidForTarget(self.GetPrimaryWeapon(), target)) return true; if (info.SecondaryWeapon != null && diff --git a/OpenRa.Game/Effects/Corpse.cs b/OpenRa.Game/Effects/Corpse.cs index 2c4570d46c..2e89a40d7b 100755 --- a/OpenRa.Game/Effects/Corpse.cs +++ b/OpenRa.Game/Effects/Corpse.cs @@ -15,7 +15,7 @@ namespace OpenRa.Game.Effects public Corpse(Actor fromActor, int death) { - anim = new Animation(fromActor.traits.WithInterface().FirstOrDefault().GetImage(fromActor)); + anim = new Animation(fromActor.traits.GetOrDefault().GetImage(fromActor)); anim.PlayThen("die{0}".F(death + 1), () => Game.world.AddFrameEndTask(w => w.Remove(this))); diff --git a/OpenRa.Game/Exts.cs b/OpenRa.Game/Exts.cs index ae908bedc1..804f99b970 100644 --- a/OpenRa.Game/Exts.cs +++ b/OpenRa.Game/Exts.cs @@ -32,7 +32,7 @@ namespace OpenRa.Game public static WeaponInfo GetPrimaryWeapon(this Actor self) { - var info = self.Info.Traits.WithInterface().FirstOrDefault(); + var info = self.Info.Traits.GetOrDefault(); if (info == null) return null; var weapon = info.PrimaryWeapon; @@ -43,7 +43,7 @@ namespace OpenRa.Game public static WeaponInfo GetSecondaryWeapon(this Actor self) { - var info = self.Info.Traits.WithInterface().FirstOrDefault(); + var info = self.Info.Traits.GetOrDefault(); if (info == null) return null; var weapon = info.SecondaryWeapon; diff --git a/OpenRa.Game/Game.cs b/OpenRa.Game/Game.cs index c3237a5470..4ee33460d3 100644 --- a/OpenRa.Game/Game.cs +++ b/OpenRa.Game/Game.cs @@ -244,7 +244,7 @@ namespace OpenRa.Game public static bool IsActorCrushableByActor(Actor a, Actor b) { - return IsActorCrushableByMovementType(a, b.traits.WithInterface().FirstOrDefault().GetMovementType()); + return IsActorCrushableByMovementType(a, b.traits.GetOrDefault().GetMovementType()); } public static bool IsActorPathableToCrush(Actor a, UnitMovementType umt) diff --git a/OpenRa.Game/GameRules/TechTree.cs b/OpenRa.Game/GameRules/TechTree.cs index 6f70cf883a..d403192261 100755 --- a/OpenRa.Game/GameRules/TechTree.cs +++ b/OpenRa.Game/GameRules/TechTree.cs @@ -14,7 +14,7 @@ namespace OpenRa.Game.GameRules foreach( var b in Rules.Categories[ "Building" ] ) { var info = Rules.NewUnitInfo[ b ]; - var pi = info.Traits.WithInterface().FirstOrDefault(); + var pi = info.Traits.GetOrDefault(); if (pi != null) foreach( var p in pi.Produces ) producesIndex[ p ].Add( info ); diff --git a/OpenRa.Game/Graphics/WorldRenderer.cs b/OpenRa.Game/Graphics/WorldRenderer.cs index 44b1d197ab..a3c82c409c 100644 --- a/OpenRa.Game/Graphics/WorldRenderer.cs +++ b/OpenRa.Game/Graphics/WorldRenderer.cs @@ -169,7 +169,7 @@ namespace OpenRa.Game.Graphics lineRenderer.DrawLine(xy + new float2(0, -2), xy + new float2(0, -4), c, c); lineRenderer.DrawLine(Xy + new float2(0, -2), Xy + new float2(0, -4), c, c); - var healthAmount = (float)selectedUnit.Health / selectedUnit.Info.Traits.WithInterface().First().HP; + var healthAmount = (float)selectedUnit.Health / selectedUnit.Info.Traits.Get().HP; var healthColor = (healthAmount < Rules.General.ConditionRed) ? Color.Red : (healthAmount < Rules.General.ConditionYellow) ? Color.Yellow : Color.LimeGreen; diff --git a/OpenRa.Game/Orders/ChronoshiftDestinationOrderGenerator.cs b/OpenRa.Game/Orders/ChronoshiftDestinationOrderGenerator.cs index a32d0ca117..2babfc2232 100644 --- a/OpenRa.Game/Orders/ChronoshiftDestinationOrderGenerator.cs +++ b/OpenRa.Game/Orders/ChronoshiftDestinationOrderGenerator.cs @@ -40,7 +40,7 @@ namespace OpenRa.Game.Orders if (!Game.LocalPlayer.Shroud.IsExplored(xy)) return Cursor.MoveBlocked; - var movement = self.traits.WithInterface().FirstOrDefault(); + var movement = self.traits.GetOrDefault(); return (movement.CanEnterCell(xy)) ? Cursor.Chronoshift : Cursor.MoveBlocked; } } diff --git a/OpenRa.Game/Orders/ChronoshiftSelfDestinationOrderGenerator.cs b/OpenRa.Game/Orders/ChronoshiftSelfDestinationOrderGenerator.cs index 5c949c1c51..d44ccbd88a 100644 --- a/OpenRa.Game/Orders/ChronoshiftSelfDestinationOrderGenerator.cs +++ b/OpenRa.Game/Orders/ChronoshiftSelfDestinationOrderGenerator.cs @@ -38,7 +38,7 @@ namespace OpenRa.Game.Orders if (!Game.LocalPlayer.Shroud.IsExplored(xy)) return Cursor.MoveBlocked; - var movement = self.traits.WithInterface().FirstOrDefault(); + var movement = self.traits.GetOrDefault(); return (movement.CanEnterCell(xy)) ? Cursor.Chronoshift : Cursor.MoveBlocked; } } diff --git a/OpenRa.Game/Orders/UnitOrderGenerator.cs b/OpenRa.Game/Orders/UnitOrderGenerator.cs index c578db1f34..a3455ae861 100644 --- a/OpenRa.Game/Orders/UnitOrderGenerator.cs +++ b/OpenRa.Game/Orders/UnitOrderGenerator.cs @@ -57,7 +57,7 @@ namespace OpenRa.Game.Orders Cursor CursorForOrderString(string s, Actor a, int2 location) { - var movement = a.traits.WithInterface().FirstOrDefault(); + var movement = a.traits.GetOrDefault(); switch (s) { case "Attack": return Cursor.Attack; diff --git a/OpenRa.Game/Shroud.cs b/OpenRa.Game/Shroud.cs index 1b0cdfae55..c1cddc65ff 100644 --- a/OpenRa.Game/Shroud.cs +++ b/OpenRa.Game/Shroud.cs @@ -35,7 +35,7 @@ namespace OpenRa.Game { foreach (var t in Game.FindTilesInCircle( (1f / Game.CellSize * a.CenterLocation).ToInt2(), - a.Info.Traits.WithInterface().First().Sight)) + a.Info.Traits.Get().Sight)) explored[t.X, t.Y] = true; dirty = true; diff --git a/OpenRa.Game/Traits/Activities/Attack.cs b/OpenRa.Game/Traits/Activities/Attack.cs index edb64ea905..3a13213597 100644 --- a/OpenRa.Game/Traits/Activities/Attack.cs +++ b/OpenRa.Game/Traits/Activities/Attack.cs @@ -27,7 +27,7 @@ namespace OpenRa.Game.Traits.Activities return new Move( Target, Range ) { NextActivity = this }; var desiredFacing = Util.GetFacing((Target.Location - self.Location).ToFloat2(), 0); - var renderUnit = self.traits.WithInterface().FirstOrDefault(); + var renderUnit = self.traits.GetOrDefault(); var numDirs = (renderUnit != null) ? renderUnit.anim.CurrentSequence.Length : 8; @@ -37,7 +37,7 @@ namespace OpenRa.Game.Traits.Activities return new Turn( desiredFacing ) { NextActivity = this }; } - var attack = self.traits.WithInterface().First(); + var attack = self.traits.Get(); attack.target = Target; attack.DoAttack(self); return this; diff --git a/OpenRa.Game/Traits/Activities/CaptureBuilding.cs b/OpenRa.Game/Traits/Activities/CaptureBuilding.cs index 69b7bc91d7..ca304c8505 100644 --- a/OpenRa.Game/Traits/Activities/CaptureBuilding.cs +++ b/OpenRa.Game/Traits/Activities/CaptureBuilding.cs @@ -19,7 +19,7 @@ namespace OpenRa.Game.Traits.Activities if (target.Owner == self.Owner) { - if (target.Health == target.Info.Traits.WithInterface().First().HP) + if (target.Health == target.Info.Traits.Get().HP) return NextActivity; target.InflictDamage(self, -EngineerCapture.EngineerDamage, Rules.WarheadInfo["Super"]); } diff --git a/OpenRa.Game/Traits/Activities/DeliverOre.cs b/OpenRa.Game/Traits/Activities/DeliverOre.cs index c41c69c6c5..edc5b25f3d 100644 --- a/OpenRa.Game/Traits/Activities/DeliverOre.cs +++ b/OpenRa.Game/Traits/Activities/DeliverOre.cs @@ -64,7 +64,7 @@ namespace OpenRa.Game.Traits.Activities else if( unit.Facing != 64 ) return new Turn( 64 ) { NextActivity = this }; - var renderUnit = self.traits.WithInterface().First(); + var renderUnit = self.traits.Get(); if( renderUnit.anim.CurrentSequence.Name != "empty" ) renderUnit.PlayCustomAnimation( self, "empty", () => isDone = true ); diff --git a/OpenRa.Game/Traits/Activities/Harvest.cs b/OpenRa.Game/Traits/Activities/Harvest.cs index 677c34e953..0de6440655 100644 --- a/OpenRa.Game/Traits/Activities/Harvest.cs +++ b/OpenRa.Game/Traits/Activities/Harvest.cs @@ -33,7 +33,7 @@ namespace OpenRa.Game.Traits.Activities { var unit = self.traits.Get(); var harv = self.traits.Get(); - var renderUnit = self.traits.WithInterface().First(); /* better have one of these! */ + var renderUnit = self.traits.Get(); /* better have one of these! */ var isGem = false; if (!Rules.Map.ContainsResource(self.Location) || diff --git a/OpenRa.Game/Traits/Activities/HeliReturn.cs b/OpenRa.Game/Traits/Activities/HeliReturn.cs index 3595f7dd6f..425f8cb997 100644 --- a/OpenRa.Game/Traits/Activities/HeliReturn.cs +++ b/OpenRa.Game/Traits/Activities/HeliReturn.cs @@ -24,7 +24,7 @@ namespace OpenRa.Game.Traits.Activities if (isCanceled) return NextActivity; var dest = ChooseHelipad(self); - var initialFacing = self.Info.Traits.WithInterface().First().InitialFacing; + var initialFacing = self.Info.Traits.Get().InitialFacing; if (dest == null) return Util.SequenceActivities( diff --git a/OpenRa.Game/Traits/Activities/Repair.cs b/OpenRa.Game/Traits/Activities/Repair.cs index b343b3f506..1edf56ae36 100644 --- a/OpenRa.Game/Traits/Activities/Repair.cs +++ b/OpenRa.Game/Traits/Activities/Repair.cs @@ -17,7 +17,7 @@ namespace OpenRa.Game.Traits.Activities if (remainingTicks == 0) { var unitCost = self.Info.Traits.Get().Cost; - var hp = self.Info.Traits.WithInterface().First().HP; + var hp = self.Info.Traits.Get().HP; var costPerHp = (Rules.General.URepairPercent * unitCost) / hp; var hpToRepair = Math.Min(Rules.General.URepairStep, hp - self.Health); diff --git a/OpenRa.Game/Traits/Activities/Sell.cs b/OpenRa.Game/Traits/Activities/Sell.cs index b8c784faec..a185d47a7c 100644 --- a/OpenRa.Game/Traits/Activities/Sell.cs +++ b/OpenRa.Game/Traits/Activities/Sell.cs @@ -14,7 +14,7 @@ namespace OpenRa.Game.Traits.Activities void DoSell(Actor self) { var cost = self.Info.Traits.Get().Cost; - var hp = self.Info.Traits.WithInterface().First().HP; + var hp = self.Info.Traits.Get().HP; var refund = Rules.General.RefundPercent * self.Health * cost / hp; self.Owner.GiveCash((int)refund); @@ -30,7 +30,7 @@ namespace OpenRa.Game.Traits.Activities { if (!started) { - var rb = self.traits.WithInterface().First(); + var rb = self.traits.Get(); //var rb = self.traits.Get(); rb.PlayCustomAnimBackwards(self, "make", () => Game.world.AddFrameEndTask(w => DoSell(self))); diff --git a/OpenRa.Game/Traits/Activities/UnloadCargo.cs b/OpenRa.Game/Traits/Activities/UnloadCargo.cs index 32b9da09ca..3b5a1fe3a7 100644 --- a/OpenRa.Game/Traits/Activities/UnloadCargo.cs +++ b/OpenRa.Game/Traits/Activities/UnloadCargo.cs @@ -44,7 +44,7 @@ namespace OpenRa.Game.Traits.Activities if (cargo.IsEmpty(self)) return NextActivity; - var ru = self.traits.WithInterface().FirstOrDefault(); + var ru = self.traits.GetOrDefault(); if (ru != null) ru.PlayCustomAnimation(self, "unload", null); diff --git a/OpenRa.Game/Traits/AttackBase.cs b/OpenRa.Game/Traits/AttackBase.cs index 366d3902c6..b5f5bb66dd 100644 --- a/OpenRa.Game/Traits/AttackBase.cs +++ b/OpenRa.Game/Traits/AttackBase.cs @@ -88,7 +88,7 @@ namespace OpenRa.Game.Traits public void DoAttack(Actor self) { var unit = self.traits.GetOrDefault(); - var info = self.Info.Traits.WithInterface().First(); + var info = self.Info.Traits.Get(); if (info.PrimaryWeapon != null && CheckFire(self, unit, info.PrimaryWeapon, ref primaryFireDelay, info.PrimaryOffset, ref primaryBurst, info.PrimaryLocalOffset)) @@ -142,7 +142,7 @@ namespace OpenRa.Game.Traits var firePos = self.CenterLocation.ToInt2() + Util.GetTurretPosition(self, unit, fireOffset, 0f).ToInt2(); var thisTarget = target; // closure. var destUnit = thisTarget.traits.GetOrDefault(); - var info = self.Info.Traits.WithInterface().First(); + var info = self.Info.Traits.Get(); ScheduleDelayedAction(info.FireDelay, () => { diff --git a/OpenRa.Game/Traits/AutoHeal.cs b/OpenRa.Game/Traits/AutoHeal.cs index d31041939a..c9918aee83 100644 --- a/OpenRa.Game/Traits/AutoHeal.cs +++ b/OpenRa.Game/Traits/AutoHeal.cs @@ -9,7 +9,7 @@ namespace OpenRa.Game.Traits { void AttackTarget(Actor self, Actor target) { - var attack = self.traits.WithInterface().First(); + var attack = self.traits.Get(); if (target != null) attack.ResolveOrder(self, new Order("Attack", self, target, int2.Zero, null)); else @@ -19,14 +19,14 @@ namespace OpenRa.Game.Traits bool NeedsNewTarget(Actor self) { - var attack = self.traits.WithInterface().First(); + var attack = self.traits.Get(); var range = Util.GetMaximumRange(self); if (attack.target == null) return true; // he's dead. if ((attack.target.Location - self.Location).LengthSquared > range * range + 2) return true; // wandered off faster than we could follow - if (attack.target.Health == attack.target.Info.Traits.WithInterface().First().HP) + if (attack.target.Health == attack.target.Info.Traits.Get().HP) return true; // fully healed return false; @@ -34,7 +34,7 @@ namespace OpenRa.Game.Traits public void Tick(Actor self) { - var attack = self.traits.WithInterface().First(); + var attack = self.traits.Get(); var range = Util.GetMaximumRange(self); if (NeedsNewTarget(self)) @@ -48,7 +48,7 @@ namespace OpenRa.Game.Traits return inRange .Where(a => a.Owner == self.Owner && a != self) /* todo: one day deal with friendly players */ .Where(a => Combat.HasAnyValidWeapons(self, a)) - .Where(a => a.Health < a.Info.Traits.WithInterface().First().HP) + .Where(a => a.Health < a.Info.Traits.Get().HP) .OrderBy(a => (a.Location - self.Location).LengthSquared) .FirstOrDefault(); } diff --git a/OpenRa.Game/Traits/AutoTarget.cs b/OpenRa.Game/Traits/AutoTarget.cs index 33fc5002c5..a6721b6cfb 100644 --- a/OpenRa.Game/Traits/AutoTarget.cs +++ b/OpenRa.Game/Traits/AutoTarget.cs @@ -8,7 +8,7 @@ namespace OpenRa.Game.Traits { void AttackTarget(Actor self, Actor target) { - var attack = self.traits.WithInterface().First(); + var attack = self.traits.Get(); if (target != null) attack.ResolveOrder(self, new Order("Attack", self, target, int2.Zero, null)); } @@ -17,7 +17,7 @@ namespace OpenRa.Game.Traits { if (!self.IsIdle) return; - var attack = self.traits.WithInterface().First(); + var attack = self.traits.Get(); var range = Util.GetMaximumRange(self); if (attack.target == null || @@ -48,7 +48,7 @@ namespace OpenRa.Game.Traits if (e.Damage < 0) return; // don't retaliate against healers - var attack = self.traits.WithInterface().First(); + var attack = self.traits.Get(); if (attack.target != null) return; AttackTarget(self, e.Attacker); diff --git a/OpenRa.Game/Traits/ChronoshiftDeploy.cs b/OpenRa.Game/Traits/ChronoshiftDeploy.cs index 08c24000ba..5b814d1038 100644 --- a/OpenRa.Game/Traits/ChronoshiftDeploy.cs +++ b/OpenRa.Game/Traits/ChronoshiftDeploy.cs @@ -40,7 +40,7 @@ namespace OpenRa.Game.Traits return; } - var movement = self.traits.WithInterface().FirstOrDefault(); + var movement = self.traits.GetOrDefault(); if (order.OrderString == "ChronoshiftSelf" && movement.CanEnterCell(order.TargetLocation)) { // Cannot chronoshift into unexplored location diff --git a/OpenRa.Game/Traits/Chronoshiftable.cs b/OpenRa.Game/Traits/Chronoshiftable.cs index 4450d036ce..067c43716e 100644 --- a/OpenRa.Game/Traits/Chronoshiftable.cs +++ b/OpenRa.Game/Traits/Chronoshiftable.cs @@ -45,7 +45,7 @@ namespace OpenRa.Game.Traits Game.controller.orderGenerator = new ChronoshiftDestinationOrderGenerator(self, power); } - var movement = self.traits.WithInterface().FirstOrDefault(); + var movement = self.traits.GetOrDefault(); if (order.OrderString == "Chronoshift" && movement.CanEnterCell(order.TargetLocation)) { // Cannot chronoshift into unexplored location diff --git a/OpenRa.Game/Traits/DemoTruck.cs b/OpenRa.Game/Traits/DemoTruck.cs index c8ff6c5f73..2816729f98 100644 --- a/OpenRa.Game/Traits/DemoTruck.cs +++ b/OpenRa.Game/Traits/DemoTruck.cs @@ -18,7 +18,7 @@ namespace OpenRa.Game.Traits public new void ResolveOrder(Actor self, Order order) { // Override chronoshifting action to detonate vehicle - var movement = self.traits.WithInterface().FirstOrDefault(); + var movement = self.traits.GetOrDefault(); var chronosphere = Game.world.Actors.Where(a => a.Owner == order.Subject.Owner && a.traits.Contains()).FirstOrDefault(); if (order.OrderString == "Chronoshift" && movement.CanEnterCell(order.TargetLocation)) { @@ -44,7 +44,7 @@ namespace OpenRa.Game.Traits int2 detonateLocation = self.CenterLocation.ToInt2(); Game.world.AddFrameEndTask( - w => w.Add(new Bullet(self.Info.Traits.WithInterface().First().PrimaryWeapon, detonatedBy.Owner, detonatedBy, + w => w.Add( new Bullet( self.Info.Traits.Get().PrimaryWeapon, detonatedBy.Owner, detonatedBy, detonateLocation, detonateLocation, altitude, altitude))); } } diff --git a/OpenRa.Game/Traits/Helicopter.cs b/OpenRa.Game/Traits/Helicopter.cs index 6c8114c764..58e570fe2f 100644 --- a/OpenRa.Game/Traits/Helicopter.cs +++ b/OpenRa.Game/Traits/Helicopter.cs @@ -52,7 +52,7 @@ namespace OpenRa.Game.Traits { self.CancelActivity(); self.QueueActivity(new HeliFly(Util.CenterOfCell(order.TargetLocation))); - self.QueueActivity(new Turn(self.Info.Traits.WithInterface().FirstOrDefault().InitialFacing)); + self.QueueActivity( new Turn( self.Info.Traits.GetOrDefault().InitialFacing ) ); self.QueueActivity(new HeliLand(true)); } @@ -69,7 +69,7 @@ namespace OpenRa.Game.Traits self.CancelActivity(); self.QueueActivity(new HeliFly(order.TargetActor.CenterLocation + offsetVec)); - self.QueueActivity(new Turn(self.Info.Traits.WithInterface().FirstOrDefault().InitialFacing)); + self.QueueActivity( new Turn( self.Info.Traits.GetOrDefault().InitialFacing ) ); self.QueueActivity(new HeliLand(false)); self.QueueActivity(order.TargetActor.Info.Name == "hpad" ? (IActivity)new Rearm() : new Repair()); diff --git a/OpenRa.Game/Traits/Passenger.cs b/OpenRa.Game/Traits/Passenger.cs index 33b17b2b8d..2339b37325 100644 --- a/OpenRa.Game/Traits/Passenger.cs +++ b/OpenRa.Game/Traits/Passenger.cs @@ -19,7 +19,7 @@ namespace OpenRa.Game.Traits if (cargo == null || cargo.IsFull(underCursor)) return null; - var umt = self.traits.WithInterface().First().GetMovementType(); + var umt = self.traits.Get().GetMovementType(); if (!underCursor.Info.Traits.Get().PassengerTypes.Contains(umt)) return null; diff --git a/OpenRa.Game/Traits/Production.cs b/OpenRa.Game/Traits/Production.cs index ade7b28856..a35beeb11e 100755 --- a/OpenRa.Game/Traits/Production.cs +++ b/OpenRa.Game/Traits/Production.cs @@ -26,7 +26,7 @@ namespace OpenRa.Game.Traits public virtual int CreationFacing( Actor self, Actor newUnit ) { - return newUnit.Info.Traits.WithInterface().FirstOrDefault().InitialFacing; + return newUnit.Info.Traits.GetOrDefault().InitialFacing; } public bool Produce( Actor self, LegacyUnitInfo producee ) diff --git a/OpenRa.Game/Traits/RenderBuildingWarFactory.cs b/OpenRa.Game/Traits/RenderBuildingWarFactory.cs index 2990363d0d..6386120fa5 100644 --- a/OpenRa.Game/Traits/RenderBuildingWarFactory.cs +++ b/OpenRa.Game/Traits/RenderBuildingWarFactory.cs @@ -26,7 +26,7 @@ namespace OpenRa.Game.Traits public RenderWarFactory(Actor self) { this.self = self; - roof = new Animation(self.traits.WithInterface().First().GetImage(self)); + roof = new Animation(self.traits.Get().GetImage(self)); } public void BuildingComplete( Actor self ) diff --git a/OpenRa.Game/Traits/RenderSimple.cs b/OpenRa.Game/Traits/RenderSimple.cs index 30cc447c8f..b27d49f887 100644 --- a/OpenRa.Game/Traits/RenderSimple.cs +++ b/OpenRa.Game/Traits/RenderSimple.cs @@ -19,7 +19,7 @@ namespace OpenRa.Game.Traits public string GetImage(Actor self) { - return self.Info.Traits.WithInterface().First().Image ?? self.Info.Name; + return self.Info.Traits.Get().Image ?? self.Info.Name; } public RenderSimple(Actor self) diff --git a/OpenRa.Game/Traits/RenderUnitMuzzleFlash.cs b/OpenRa.Game/Traits/RenderUnitMuzzleFlash.cs index fa8f569bbc..9e18c5830a 100644 --- a/OpenRa.Game/Traits/RenderUnitMuzzleFlash.cs +++ b/OpenRa.Game/Traits/RenderUnitMuzzleFlash.cs @@ -16,8 +16,8 @@ namespace OpenRa.Game.Traits : base(self) { var unit = self.traits.Get(); - var attack = self.traits.WithInterface().First(); - var attackInfo = self.Info.Traits.WithInterface().First(); + var attack = self.traits.Get(); + var attackInfo = self.Info.Traits.Get(); var muzzleFlash = new Animation(GetImage(self)); muzzleFlash.PlayFetchIndex("muzzle", diff --git a/OpenRa.Game/Traits/RenderUnitReload.cs b/OpenRa.Game/Traits/RenderUnitReload.cs index f1b67973e9..ea966477c4 100644 --- a/OpenRa.Game/Traits/RenderUnitReload.cs +++ b/OpenRa.Game/Traits/RenderUnitReload.cs @@ -16,7 +16,7 @@ namespace OpenRa.Game.Traits { var isAttacking = self.GetCurrentActivity() is Activities.Attack; - var attack = self.traits.WithInterface().FirstOrDefault(); + var attack = self.traits.GetOrDefault(); if (attack != null) anim.ReplaceAnim((attack.IsReloading() ? "empty-" : "") diff --git a/OpenRa.Game/Traits/RenderUnitTurreted.cs b/OpenRa.Game/Traits/RenderUnitTurreted.cs index c6222bd0b8..30a204f6a0 100644 --- a/OpenRa.Game/Traits/RenderUnitTurreted.cs +++ b/OpenRa.Game/Traits/RenderUnitTurreted.cs @@ -16,8 +16,8 @@ namespace OpenRa.Game.Traits { var unit = self.traits.Get(); var turreted = self.traits.Get(); - var attack = self.traits.WithInterface().FirstOrDefault(); - var attackInfo = self.Info.Traits.WithInterface().First(); + var attack = self.traits.GetOrDefault(); + var attackInfo = self.Info.Traits.Get(); var turretAnim = new Animation(GetImage(self)); turretAnim.PlayFacing( "turret", () => turreted.turretFacing ); diff --git a/OpenRa.Game/Traits/Util.cs b/OpenRa.Game/Traits/Util.cs index 9b8345796c..246a19721b 100755 --- a/OpenRa.Game/Traits/Util.cs +++ b/OpenRa.Game/Traits/Util.cs @@ -83,7 +83,7 @@ namespace OpenRa.Game.Traits static float2 GetRecoil(Actor self, float recoil) { if (self.LegacyInfo.Recoil == 0) return float2.Zero; - var rut = self.traits.WithInterface().FirstOrDefault(); + var rut = self.traits.GetOrDefault(); if (rut == null) return float2.Zero; var facing = self.traits.Get().turretFacing; @@ -106,7 +106,7 @@ namespace OpenRa.Game.Traits { if( unit == null ) return int2.Zero; /* things that don't have a rotating base don't need the turrets repositioned */ - var ru = self.traits.WithInterface().FirstOrDefault(); + var ru = self.traits.GetOrDefault(); var numDirs = (ru != null) ? ru.anim.CurrentSequence.Length : 8; var bodyFacing = unit.Facing; var quantizedFacing = QuantizeFacing(bodyFacing, numDirs) * (256 / numDirs); @@ -145,7 +145,7 @@ namespace OpenRa.Game.Traits public static float GetMaximumRange(Actor self) { - var info = self.Info.Traits.WithInterface().First(); + var info = self.Info.Traits.Get(); return new[] { self.GetPrimaryWeapon(), self.GetSecondaryWeapon() } .Where(w => w != null).Max(w => w.Range); } diff --git a/OpenRa.Game/UnitInfluenceMap.cs b/OpenRa.Game/UnitInfluenceMap.cs index 6f50bf1dad..4d93aa7e3c 100644 --- a/OpenRa.Game/UnitInfluenceMap.cs +++ b/OpenRa.Game/UnitInfluenceMap.cs @@ -16,8 +16,8 @@ namespace OpenRa.Game for (int i = 0; i < 128; i++) for (int j = 0; j < 128; j++) influence[ i, j ] = new List(); - - Game.world.ActorRemoved += a => Remove(a, a.traits.WithInterface().FirstOrDefault()); + + Game.world.ActorRemoved += a => Remove( a, a.traits.GetOrDefault() ); } public void Tick() @@ -53,7 +53,7 @@ namespace OpenRa.Game for( int x = 0 ; x < 128 ; x++ ) if( influence[ x, y ] != null ) foreach (var a in influence[ x, y ]) - if (!a.traits.WithInterface().First().OccupiedCells().Contains( new int2( x, y ) ) ) + if (!a.traits.Get().OccupiedCells().Contains( new int2( x, y ) ) ) throw new InvalidOperationException( "UIM: Sanity check failed A" ); foreach( Actor a in Game.world.Actors )