Fix NPC shutdown crash (#2971)

Co-authored-by: Metal Gear Sloth <metalgearsloth@gmail.com>
This commit is contained in:
metalgearsloth
2021-01-11 01:24:03 +11:00
committed by GitHub
parent 7bfdf30268
commit d403a7fab4
10 changed files with 67 additions and 49 deletions

View File

@@ -5,38 +5,36 @@ namespace Content.Server.AI.Operators
{
public abstract class AiOperator
{
public bool HasStartup => _hasStartup;
private bool _hasStartup = false;
private bool _hasShutdown = false;
public bool HasStartup { get; private set; }
public bool HasShutdown { get; private set; }
/// <summary>
/// Called once when the AiLogicProcessor starts this action
/// </summary>
public virtual bool TryStartup()
/// <returns>true if it hasn't started up previously</returns>
public virtual bool Startup()
{
// If we've already startup then no point continuing
// This signals to the override that it's already startup
// Should probably throw but it made some code elsewhere marginally easier
if (_hasStartup)
{
if (HasStartup)
return false;
}
_hasStartup = true;
HasStartup = true;
return true;
}
/// <summary>
/// Called once when the AiLogicProcessor is done with this action if the outcome is successful or fails.
/// </summary>
public virtual void Shutdown(Outcome outcome)
public virtual bool Shutdown(Outcome outcome)
{
if (_hasShutdown)
{
throw new InvalidOperationException("AiOperator has already shutdown");
}
if (HasShutdown)
return false;
_hasShutdown = true;
HasShutdown = true;
return true;
}
/// <summary>

View File

@@ -22,9 +22,9 @@ namespace Content.Server.AI.Operators.Combat.Melee
_burstTime = burstTime;
}
public override bool TryStartup()
public override bool Startup()
{
if (!base.TryStartup())
if (!base.Startup())
{
return true;
}
@@ -42,13 +42,17 @@ namespace Content.Server.AI.Operators.Combat.Melee
return true;
}
public override void Shutdown(Outcome outcome)
public override bool Shutdown(Outcome outcome)
{
base.Shutdown(outcome);
if (!base.Shutdown(outcome))
return false;
if (_owner.TryGetComponent(out CombatModeComponent combatModeComponent))
{
combatModeComponent.IsInCombatMode = false;
}
return true;
}
public override Outcome Execute(float frameTime)

View File

@@ -22,9 +22,9 @@ namespace Content.Server.AI.Operators.Combat.Melee
_burstTime = burstTime;
}
public override bool TryStartup()
public override bool Startup()
{
if (!base.TryStartup())
if (!base.Startup())
{
return true;
}
@@ -51,13 +51,17 @@ namespace Content.Server.AI.Operators.Combat.Melee
return true;
}
public override void Shutdown(Outcome outcome)
public override bool Shutdown(Outcome outcome)
{
base.Shutdown(outcome);
if (!base.Shutdown(outcome))
return false;
if (_owner.TryGetComponent(out CombatModeComponent combatModeComponent))
{
combatModeComponent.IsInCombatMode = false;
}
return true;
}
public override Outcome Execute(float frameTime)

View File

@@ -21,9 +21,9 @@ namespace Content.Server.AI.Operators.Inventory
_owner = owner;
}
public override bool TryStartup()
public override bool Startup()
{
if (!base.TryStartup())
if (!base.Startup())
{
return true;
}
@@ -40,12 +40,15 @@ namespace Content.Server.AI.Operators.Inventory
return _target != null;
}
public override void Shutdown(Outcome outcome)
public override bool Shutdown(Outcome outcome)
{
base.Shutdown(outcome);
if (!base.Shutdown(outcome))
return false;
var blackboard = UtilityAiHelpers.GetBlackboard(_owner);
blackboard?.GetState<LastOpenedStorageState>().SetValue(null);
return true;
}
public override Outcome Execute(float frameTime)

View File

@@ -32,9 +32,9 @@ namespace Content.Server.AI.Operators.Movement
_requiresInRangeUnobstructed = requiresInRangeUnobstructed;
}
public override bool TryStartup()
public override bool Startup()
{
if (!base.TryStartup())
if (!base.Startup())
{
return true;
}
@@ -45,11 +45,14 @@ namespace Content.Server.AI.Operators.Movement
return true;
}
public override void Shutdown(Outcome outcome)
public override bool Shutdown(Outcome outcome)
{
base.Shutdown(outcome);
if (!base.Shutdown(outcome))
return false;
var steering = EntitySystem.Get<AiSteeringSystem>();
steering.Unregister(_owner);
return true;
}
public override Outcome Execute(float frameTime)

View File

@@ -21,9 +21,9 @@ namespace Content.Server.AI.Operators.Movement
DesiredRange = desiredRange;
}
public override bool TryStartup()
public override bool Startup()
{
if (!base.TryStartup())
if (!base.Startup())
{
return true;
}
@@ -34,11 +34,14 @@ namespace Content.Server.AI.Operators.Movement
return true;
}
public override void Shutdown(Outcome outcome)
public override bool Shutdown(Outcome outcome)
{
base.Shutdown(outcome);
if (!base.Shutdown(outcome))
return false;
var steering = EntitySystem.Get<AiSteeringSystem>();
steering.Unregister(_owner);
return true;
}
public override Outcome Execute(float frameTime)

View File

@@ -19,7 +19,7 @@ namespace Content.Server.AI.Operators.Sequences
}
var op = Sequence.Peek();
op.TryStartup();
op.Startup();
var outcome = op.Execute(frameTime);
switch (outcome)

View File

@@ -78,7 +78,7 @@ namespace Content.Server.AI.Utility.Actions
return Outcome.Success;
}
op.TryStartup();
op.Startup();
var outcome = op.Execute(frameTime);
switch (outcome)

View File

@@ -137,6 +137,8 @@ namespace Content.Server.AI.Utility.AiLogic
{
var currentOp = CurrentAction?.ActionOperators.Peek();
currentOp?.Shutdown(Outcome.Failed);
CurrentAction?.Shutdown();
CurrentAction = null;
}
public void MobStateChanged(MobStateChangedMessage message)

View File

@@ -110,17 +110,18 @@ namespace Content.Server.GameObjects.EntitySystems.AI
foreach (var processor in _awakeAi)
{
if (count >= maxUpdates)
{
break;
}
if (processor.SelfEntity.Deleted)
if (processor.SelfEntity.Deleted ||
!processor.SelfEntity.HasComponent<AiControllerComponent>())
{
toRemove.Add(processor);
continue;
}
if (count >= maxUpdates)
{
break;
}
processor.Update(frameTime);
count++;
}