Add an ICreationActivity interface

This commit is contained in:
abcdefg30
2019-09-22 14:45:33 +02:00
committed by Paul Chote
parent 39f8d34494
commit 56726a0533
6 changed files with 54 additions and 9 deletions

View File

@@ -82,6 +82,7 @@ namespace OpenRA
readonly INotifyIdle[] tickIdles; readonly INotifyIdle[] tickIdles;
readonly ITargetablePositions[] targetablePositions; readonly ITargetablePositions[] targetablePositions;
WPos[] staticTargetablePositions; WPos[] staticTargetablePositions;
bool created;
internal Actor(World world, string name, TypeDictionary initDict) internal Actor(World world, string name, TypeDictionary initDict)
{ {
@@ -138,6 +139,35 @@ namespace OpenRA
SyncHashes = TraitsImplementing<ISync>().Select(sync => new SyncHash(sync)).ToArray(); SyncHashes = TraitsImplementing<ISync>().Select(sync => new SyncHash(sync)).ToArray();
} }
internal void Created()
{
created = true;
foreach (var t in TraitsImplementing<INotifyCreated>())
t.Created(this);
// The initial activity should run before any activities queued by INotifyCreated.Created
// However, we need to know which traits are enabled (via conditions), so wait for after the calls and insert the activity as the first
ICreationActivity creationActivity = null;
foreach (var ica in TraitsImplementing<ICreationActivity>())
{
if (!ica.IsTraitEnabled())
continue;
if (creationActivity != null)
throw new InvalidOperationException("More than one enabled ICreationActivity trait: {0} and {1}".F(creationActivity.GetType().Name, ica.GetType().Name));
var activity = ica.GetCreationActivity();
if (activity == null)
continue;
creationActivity = ica;
activity.Queue(CurrentActivity);
CurrentActivity = activity;
}
}
public void Tick() public void Tick()
{ {
var wasIdle = IsIdle; var wasIdle = IsIdle;
@@ -214,11 +244,15 @@ namespace OpenRA
{ {
if (!queued) if (!queued)
CancelActivity(); CancelActivity();
QueueActivity(nextActivity); QueueActivity(nextActivity);
} }
public void QueueActivity(Activity nextActivity) public void QueueActivity(Activity nextActivity)
{ {
if (!created)
throw new InvalidOperationException("An activity was queued before the actor was created. Queue it inside the INotifyCreated.Created callback instead.");
if (CurrentActivity == null) if (CurrentActivity == null)
CurrentActivity = nextActivity; CurrentActivity = nextActivity;
else else

View File

@@ -12,6 +12,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using OpenRA.Activities;
using OpenRA.FileSystem; using OpenRA.FileSystem;
using OpenRA.Graphics; using OpenRA.Graphics;
using OpenRA.Network; using OpenRA.Network;
@@ -538,4 +539,7 @@ namespace OpenRA.Traits
[RequireExplicitImplementation] [RequireExplicitImplementation]
public interface IUnlocksRenderPlayer { bool RenderPlayerUnlocked { get; } } public interface IUnlocksRenderPlayer { bool RenderPlayerUnlocked { get; } }
[RequireExplicitImplementation]
public interface ICreationActivity { Activity GetCreationActivity(); }
} }

View File

@@ -330,10 +330,10 @@ namespace OpenRA
public Actor CreateActor(bool addToWorld, string name, TypeDictionary initDict) public Actor CreateActor(bool addToWorld, string name, TypeDictionary initDict)
{ {
var a = new Actor(this, name, initDict); var a = new Actor(this, name, initDict);
foreach (var t in a.TraitsImplementing<INotifyCreated>()) a.Created();
t.Created(a);
if (addToWorld) if (addToWorld)
Add(a); Add(a);
return a; return a;
} }

View File

@@ -190,7 +190,7 @@ namespace OpenRA.Mods.Common.Traits
public class Aircraft : ITick, ISync, IFacing, IPositionable, IMove, IIssueOrder, IResolveOrder, IOrderVoice, IDeathActorInitModifier, public class Aircraft : ITick, ISync, IFacing, IPositionable, IMove, IIssueOrder, IResolveOrder, IOrderVoice, IDeathActorInitModifier,
INotifyCreated, INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyActorDisposing, INotifyBecomingIdle, INotifyCreated, INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyActorDisposing, INotifyBecomingIdle,
IActorPreviewInitModifier, IIssueDeployOrder, IObservesVariables IActorPreviewInitModifier, IIssueDeployOrder, IObservesVariables, ICreationActivity
{ {
static readonly Pair<CPos, SubCell>[] NoCells = { }; static readonly Pair<CPos, SubCell>[] NoCells = { };
@@ -309,8 +309,6 @@ namespace OpenRA.Mods.Common.Traits
notifyMoving = self.TraitsImplementing<INotifyMoving>().ToArray(); notifyMoving = self.TraitsImplementing<INotifyMoving>().ToArray();
positionOffsets = self.TraitsImplementing<IAircraftCenterPositionOffset>().ToArray(); positionOffsets = self.TraitsImplementing<IAircraftCenterPositionOffset>().ToArray();
overrideAircraftLanding = self.TraitOrDefault<IOverrideAircraftLanding>(); overrideAircraftLanding = self.TraitOrDefault<IOverrideAircraftLanding>();
self.QueueActivity(MoveIntoWorld(self, moveIntoWorldDelay));
} }
void INotifyAddedToWorld.AddedToWorld(Actor self) void INotifyAddedToWorld.AddedToWorld(Actor self)
@@ -1164,6 +1162,11 @@ namespace OpenRA.Mods.Common.Traits
inits.Add(new DynamicFacingInit(() => Facing)); inits.Add(new DynamicFacingInit(() => Facing));
} }
Activity ICreationActivity.GetCreationActivity()
{
return MoveIntoWorld(self, moveIntoWorldDelay);
}
public class AircraftMoveOrderTargeter : IOrderTargeter public class AircraftMoveOrderTargeter : IOrderTargeter
{ {
readonly Aircraft aircraft; readonly Aircraft aircraft;

View File

@@ -130,8 +130,6 @@ namespace OpenRA.Mods.Common.Traits
mobile = self.Trait<Mobile>(); mobile = self.Trait<Mobile>();
resLayer = self.World.WorldActor.Trait<ResourceLayer>(); resLayer = self.World.WorldActor.Trait<ResourceLayer>();
claimLayer = self.World.WorldActor.Trait<ResourceClaimLayer>(); claimLayer = self.World.WorldActor.Trait<ResourceClaimLayer>();
self.QueueActivity(new CallFunc(() => ChooseNewProc(self, null)));
} }
void INotifyCreated.Created(Actor self) void INotifyCreated.Created(Actor self)
@@ -141,6 +139,8 @@ namespace OpenRA.Mods.Common.Traits
conditionManager = self.TraitOrDefault<ConditionManager>(); conditionManager = self.TraitOrDefault<ConditionManager>();
UpdateCondition(self); UpdateCondition(self);
self.QueueActivity(new CallFunc(() => ChooseNewProc(self, null)));
// Note: This is queued in a FrameEndTask because otherwise the activity is dropped/overridden while moving out of a factory. // Note: This is queued in a FrameEndTask because otherwise the activity is dropped/overridden while moving out of a factory.
if (Info.SearchOnCreation) if (Info.SearchOnCreation)
self.World.AddFrameEndTask(w => self.QueueActivity(new FindAndDeliverResources(self))); self.World.AddFrameEndTask(w => self.QueueActivity(new FindAndDeliverResources(self)));

View File

@@ -138,7 +138,7 @@ namespace OpenRA.Mods.Common.Traits
} }
} }
public class Mobile : PausableConditionalTrait<MobileInfo>, IIssueOrder, IResolveOrder, IOrderVoice, IPositionable, IMove, ITick, public class Mobile : PausableConditionalTrait<MobileInfo>, IIssueOrder, IResolveOrder, IOrderVoice, IPositionable, IMove, ITick, ICreationActivity,
IFacing, IDeathActorInitModifier, INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyBlockingMove, IActorPreviewInitModifier, INotifyBecomingIdle IFacing, IDeathActorInitModifier, INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyBlockingMove, IActorPreviewInitModifier, INotifyBecomingIdle
{ {
readonly Actor self; readonly Actor self;
@@ -256,7 +256,6 @@ namespace OpenRA.Mods.Common.Traits
Locomotor = self.World.WorldActor.TraitsImplementing<Locomotor>() Locomotor = self.World.WorldActor.TraitsImplementing<Locomotor>()
.Single(l => l.Info.Name == Info.Locomotor); .Single(l => l.Info.Name == Info.Locomotor);
self.QueueActivity(MoveIntoWorld(self, moveIntoWorldDelay));
base.Created(self); base.Created(self);
} }
@@ -897,6 +896,11 @@ namespace OpenRA.Mods.Common.Traits
} }
} }
Activity ICreationActivity.GetCreationActivity()
{
return MoveIntoWorld(self, moveIntoWorldDelay);
}
class MoveOrderTargeter : IOrderTargeter class MoveOrderTargeter : IOrderTargeter
{ {
readonly Mobile mobile; readonly Mobile mobile;