diff --git a/Content.Server/Polymorph/Components/PolymorphedEntityComponent.cs b/Content.Server/Polymorph/Components/PolymorphedEntityComponent.cs index 817559d2bd..2a5d489727 100644 --- a/Content.Server/Polymorph/Components/PolymorphedEntityComponent.cs +++ b/Content.Server/Polymorph/Components/PolymorphedEntityComponent.cs @@ -10,7 +10,8 @@ namespace Content.Server.Polymorph.Components /// The polymorph prototype, used to track various information /// about the polymorph /// - public PolymorphPrototype Prototype = default!; + [DataField("prototype", required: true, customTypeSerializer:typeof(PrototypeIdSerializer))] + public string Prototype = string.Empty; /// /// The original entity that the player will revert back into diff --git a/Content.Server/Polymorph/Systems/PolymorphableSystem.cs b/Content.Server/Polymorph/Systems/PolymorphableSystem.cs index 1dc9dd7622..56324bfcb5 100644 --- a/Content.Server/Polymorph/Systems/PolymorphableSystem.cs +++ b/Content.Server/Polymorph/Systems/PolymorphableSystem.cs @@ -24,6 +24,7 @@ namespace Content.Server.Polymorph.Systems [Dependency] private readonly ActionsSystem _actions = default!; [Dependency] private readonly IPrototypeManager _proto = default!; + [Dependency] private readonly IComponentFactory _compFact = default!; [Dependency] private readonly ServerInventorySystem _inventory = default!; [Dependency] private readonly SharedHandsSystem _sharedHands = default!; [Dependency] private readonly DamageableSystem _damageable = default!; @@ -98,10 +99,11 @@ namespace Content.Server.Polymorph.Systems var child = Spawn(proto.Entity, targetTransformComp.Coordinates); MakeSentientCommand.MakeSentient(child, EntityManager); - var comp = EnsureComp(child); + var comp = _compFact.GetComponent(); + comp.Owner = child; comp.Parent = target; - comp.Prototype = proto; - RaiseLocalEvent(child, new PolymorphComponentSetupEvent(), true); + comp.Prototype = proto.ID; + EntityManager.AddComponent(child, comp); var childXform = Transform(child); childXform.LocalRotation = targetTransformComp.LocalRotation; @@ -212,11 +214,6 @@ namespace Content.Server.Polymorph.Systems } } - /// - /// Used after the polymorphedEntity component has it's data set up. - /// - public sealed class PolymorphComponentSetupEvent : InstantActionEvent { }; - public sealed class PolymorphActionEvent : InstantActionEvent { /// diff --git a/Content.Server/Polymorph/Systems/PolymorphedEntitySystem.cs b/Content.Server/Polymorph/Systems/PolymorphedEntitySystem.cs index 1469314cee..95b79c441b 100644 --- a/Content.Server/Polymorph/Systems/PolymorphedEntitySystem.cs +++ b/Content.Server/Polymorph/Systems/PolymorphedEntitySystem.cs @@ -13,11 +13,13 @@ using Content.Shared.Polymorph; using Robust.Server.Containers; using Robust.Shared.Containers; using Robust.Shared.Player; +using Robust.Shared.Prototypes; namespace Content.Server.Polymorph.Systems { public sealed class PolymorphedEntitySystem : EntitySystem { + [Dependency] private readonly IPrototypeManager _proto = default!; [Dependency] private readonly ActionsSystem _actions = default!; [Dependency] private readonly DamageableSystem _damageable = default!; [Dependency] private readonly PopupSystem _popup = default!; @@ -29,7 +31,7 @@ namespace Content.Server.Polymorph.Systems { base.Initialize(); - SubscribeLocalEvent(OnInit); + SubscribeLocalEvent(OnInit); SubscribeLocalEvent(OnRevertPolymorphActionEvent); } @@ -53,7 +55,11 @@ namespace Content.Server.Polymorph.Systems if (Deleted(component.Parent)) 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 parentXform = Transform(component.Parent); @@ -65,7 +71,7 @@ namespace Content.Server.Polymorph.Systems if (_container.TryGetContainingContainer(uid, out var cont)) cont.Insert(component.Parent); - if (component.Prototype.TransferDamage && + if (proto.TransferDamage && TryComp(component.Parent, out var damageParent) && _damageable.GetScaledDamage(uid, component.Parent, out var damage) && damage != null) @@ -89,6 +95,7 @@ namespace Content.Server.Polymorph.Systems slot.EmptyContainer(); foreach (var hand in _sharedHands.EnumerateHeld(uid)) + // This causes errors/bugs. Use hand related functions instead. hand.TryRemoveFromContainer(); } @@ -105,9 +112,17 @@ namespace Content.Server.Polymorph.Systems 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; var act = new InstantAction() @@ -116,7 +131,7 @@ namespace Content.Server.Polymorph.Systems EntityIcon = component.Parent, DisplayName = Loc.GetString("polymorph-revert-action-name"), Description = Loc.GetString("polymorph-revert-action-description"), - UseDelay = TimeSpan.FromSeconds(component.Prototype.Delay), + UseDelay = TimeSpan.FromSeconds(proto.Delay), }; _actions.AddAction(uid, act, null); @@ -126,19 +141,26 @@ namespace Content.Server.Polymorph.Systems { base.Update(frameTime); - foreach (var entity in EntityQuery()) + foreach (var comp in EntityQuery()) { - entity.Time += frameTime; + comp.Time += frameTime; - if(entity.Prototype.Duration != null && entity.Time >= entity.Prototype.Duration) - Revert(entity.Owner); + if (!_proto.TryIndex(comp.Prototype, out PolymorphPrototype? proto)) + { + 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(entity.Owner, out var mob)) + if(proto.Duration != null && comp.Time >= proto.Duration) + Revert(comp.Owner); + + if (!TryComp(comp.Owner, out var mob)) continue; - if ((entity.Prototype.RevertOnDeath && mob.IsDead()) || - (entity.Prototype.RevertOnCrit && mob.IsCritical())) - Revert(entity.Owner); + if ((proto.RevertOnDeath && mob.IsDead()) || + (proto.RevertOnCrit && mob.IsCritical())) + Revert(comp.Owner); } } }