Fix polymorphed null error (#11571)

This commit is contained in:
Leon Friedrich
2022-10-02 07:16:55 +13:00
committed by GitHub
parent 8389bde2c0
commit d43ed3210c
3 changed files with 43 additions and 23 deletions

View File

@@ -10,7 +10,8 @@ namespace Content.Server.Polymorph.Components
/// The polymorph prototype, used to track various information /// The polymorph prototype, used to track various information
/// about the polymorph /// about the polymorph
/// </summary> /// </summary>
public PolymorphPrototype Prototype = default!; [DataField("prototype", required: true, customTypeSerializer:typeof(PrototypeIdSerializer<PolymorphPrototype>))]
public string Prototype = string.Empty;
/// <summary> /// <summary>
/// The original entity that the player will revert back into /// The original entity that the player will revert back into

View File

@@ -24,6 +24,7 @@ namespace Content.Server.Polymorph.Systems
[Dependency] private readonly ActionsSystem _actions = default!; [Dependency] private readonly ActionsSystem _actions = default!;
[Dependency] private readonly IPrototypeManager _proto = default!; [Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly IComponentFactory _compFact = default!;
[Dependency] private readonly ServerInventorySystem _inventory = default!; [Dependency] private readonly ServerInventorySystem _inventory = default!;
[Dependency] private readonly SharedHandsSystem _sharedHands = default!; [Dependency] private readonly SharedHandsSystem _sharedHands = default!;
[Dependency] private readonly DamageableSystem _damageable = default!; [Dependency] private readonly DamageableSystem _damageable = default!;
@@ -98,10 +99,11 @@ namespace Content.Server.Polymorph.Systems
var child = Spawn(proto.Entity, targetTransformComp.Coordinates); var child = Spawn(proto.Entity, targetTransformComp.Coordinates);
MakeSentientCommand.MakeSentient(child, EntityManager); MakeSentientCommand.MakeSentient(child, EntityManager);
var comp = EnsureComp<PolymorphedEntityComponent>(child); var comp = _compFact.GetComponent<PolymorphedEntityComponent>();
comp.Owner = child;
comp.Parent = target; comp.Parent = target;
comp.Prototype = proto; comp.Prototype = proto.ID;
RaiseLocalEvent(child, new PolymorphComponentSetupEvent(), true); EntityManager.AddComponent(child, comp);
var childXform = Transform(child); var childXform = Transform(child);
childXform.LocalRotation = targetTransformComp.LocalRotation; childXform.LocalRotation = targetTransformComp.LocalRotation;
@@ -212,11 +214,6 @@ namespace Content.Server.Polymorph.Systems
} }
} }
/// <summary>
/// Used after the polymorphedEntity component has it's data set up.
/// </summary>
public sealed class PolymorphComponentSetupEvent : InstantActionEvent { };
public sealed class PolymorphActionEvent : InstantActionEvent public sealed class PolymorphActionEvent : InstantActionEvent
{ {
/// <summary> /// <summary>

View File

@@ -13,11 +13,13 @@ using Content.Shared.Polymorph;
using Robust.Server.Containers; using Robust.Server.Containers;
using Robust.Shared.Containers; using Robust.Shared.Containers;
using Robust.Shared.Player; using Robust.Shared.Player;
using Robust.Shared.Prototypes;
namespace Content.Server.Polymorph.Systems namespace Content.Server.Polymorph.Systems
{ {
public sealed class PolymorphedEntitySystem : EntitySystem public sealed class PolymorphedEntitySystem : EntitySystem
{ {
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly ActionsSystem _actions = default!; [Dependency] private readonly ActionsSystem _actions = default!;
[Dependency] private readonly DamageableSystem _damageable = default!; [Dependency] private readonly DamageableSystem _damageable = default!;
[Dependency] private readonly PopupSystem _popup = default!; [Dependency] private readonly PopupSystem _popup = default!;
@@ -29,7 +31,7 @@ namespace Content.Server.Polymorph.Systems
{ {
base.Initialize(); base.Initialize();
SubscribeLocalEvent<PolymorphedEntityComponent, PolymorphComponentSetupEvent>(OnInit); SubscribeLocalEvent<PolymorphedEntityComponent, ComponentStartup>(OnInit);
SubscribeLocalEvent<PolymorphedEntityComponent, RevertPolymorphActionEvent>(OnRevertPolymorphActionEvent); SubscribeLocalEvent<PolymorphedEntityComponent, RevertPolymorphActionEvent>(OnRevertPolymorphActionEvent);
} }
@@ -53,7 +55,11 @@ namespace Content.Server.Polymorph.Systems
if (Deleted(component.Parent)) if (Deleted(component.Parent))
return; return;
var proto = component.Prototype; if (!_proto.TryIndex(component.Prototype, out PolymorphPrototype? proto))
{
Logger.Error($"{nameof(PolymorphedEntitySystem)} encountered an improperly initialized polymorph component while reverting. Entity {ToPrettyString(uid)}. Prototype: {component.Prototype}");
return;
}
var uidXform = Transform(uid); var uidXform = Transform(uid);
var parentXform = Transform(component.Parent); var parentXform = Transform(component.Parent);
@@ -65,7 +71,7 @@ namespace Content.Server.Polymorph.Systems
if (_container.TryGetContainingContainer(uid, out var cont)) if (_container.TryGetContainingContainer(uid, out var cont))
cont.Insert(component.Parent); cont.Insert(component.Parent);
if (component.Prototype.TransferDamage && if (proto.TransferDamage &&
TryComp<DamageableComponent>(component.Parent, out var damageParent) && TryComp<DamageableComponent>(component.Parent, out var damageParent) &&
_damageable.GetScaledDamage(uid, component.Parent, out var damage) && _damageable.GetScaledDamage(uid, component.Parent, out var damage) &&
damage != null) damage != null)
@@ -89,6 +95,7 @@ namespace Content.Server.Polymorph.Systems
slot.EmptyContainer(); slot.EmptyContainer();
foreach (var hand in _sharedHands.EnumerateHeld(uid)) foreach (var hand in _sharedHands.EnumerateHeld(uid))
// This causes errors/bugs. Use hand related functions instead.
hand.TryRemoveFromContainer(); hand.TryRemoveFromContainer();
} }
@@ -105,9 +112,17 @@ namespace Content.Server.Polymorph.Systems
QueueDel(uid); QueueDel(uid);
} }
private void OnInit(EntityUid uid, PolymorphedEntityComponent component, PolymorphComponentSetupEvent args) public void OnInit(EntityUid uid, PolymorphedEntityComponent component, ComponentStartup args)
{ {
if (component.Prototype.Forced) if (!_proto.TryIndex(component.Prototype, out PolymorphPrototype? proto))
{
// warning instead of error because of the all-comps one entity test.
Logger.Warning($"{nameof(PolymorphedEntitySystem)} encountered an improperly set up polymorph component while initializing. Entity {ToPrettyString(uid)}. Prototype: {component.Prototype}");
RemCompDeferred(uid, component);
return;
}
if (proto.Forced)
return; return;
var act = new InstantAction() var act = new InstantAction()
@@ -116,7 +131,7 @@ namespace Content.Server.Polymorph.Systems
EntityIcon = component.Parent, EntityIcon = component.Parent,
DisplayName = Loc.GetString("polymorph-revert-action-name"), DisplayName = Loc.GetString("polymorph-revert-action-name"),
Description = Loc.GetString("polymorph-revert-action-description"), Description = Loc.GetString("polymorph-revert-action-description"),
UseDelay = TimeSpan.FromSeconds(component.Prototype.Delay), UseDelay = TimeSpan.FromSeconds(proto.Delay),
}; };
_actions.AddAction(uid, act, null); _actions.AddAction(uid, act, null);
@@ -126,19 +141,26 @@ namespace Content.Server.Polymorph.Systems
{ {
base.Update(frameTime); base.Update(frameTime);
foreach (var entity in EntityQuery<PolymorphedEntityComponent>()) foreach (var comp in EntityQuery<PolymorphedEntityComponent>())
{ {
entity.Time += frameTime; comp.Time += frameTime;
if(entity.Prototype.Duration != null && entity.Time >= entity.Prototype.Duration) if (!_proto.TryIndex(comp.Prototype, out PolymorphPrototype? proto))
Revert(entity.Owner); {
Logger.Error($"{nameof(PolymorphedEntitySystem)} encountered an improperly initialized polymorph component while updating. Entity {ToPrettyString(comp.Owner)}. Prototype: {comp.Prototype}");
RemCompDeferred(comp.Owner, comp);
continue;
}
if (!TryComp<MobStateComponent>(entity.Owner, out var mob)) if(proto.Duration != null && comp.Time >= proto.Duration)
Revert(comp.Owner);
if (!TryComp<MobStateComponent>(comp.Owner, out var mob))
continue; continue;
if ((entity.Prototype.RevertOnDeath && mob.IsDead()) || if ((proto.RevertOnDeath && mob.IsDead()) ||
(entity.Prototype.RevertOnCrit && mob.IsCritical())) (proto.RevertOnCrit && mob.IsCritical()))
Revert(entity.Owner); Revert(comp.Owner);
} }
} }
} }