From ed55f3b4e12121d973779ded6ebb2a65826d3e97 Mon Sep 17 00:00:00 2001 From: metalgearsloth Date: Mon, 19 Aug 2024 20:36:49 +1000 Subject: [PATCH] wehj --- .../GameObjects/ServerComponentFactory.cs | 3 +- Robust.Shared/GameObjects/ComponentFactory.cs | 10 +++ .../GameObjects/EntityManager.Components.cs | 10 +++ .../GameObjects/IComponentFactory.cs | 2 + .../Systems/PrototypeReloadSystem.cs | 68 ++++++++++++------- .../EntityEventBusTests.ComponentEvent.cs | 3 +- 6 files changed, 69 insertions(+), 27 deletions(-) diff --git a/Robust.Server/GameObjects/ServerComponentFactory.cs b/Robust.Server/GameObjects/ServerComponentFactory.cs index 3d22330f7fa..9e718fbb079 100644 --- a/Robust.Server/GameObjects/ServerComponentFactory.cs +++ b/Robust.Server/GameObjects/ServerComponentFactory.cs @@ -2,12 +2,13 @@ using Robust.Shared.IoC; using Robust.Shared.Log; using Robust.Shared.Reflection; +using Robust.Shared.Serialization.Manager; namespace Robust.Server.GameObjects; internal sealed class ServerComponentFactory : ComponentFactory { - public ServerComponentFactory(IDynamicTypeFactoryInternal typeFactory, IReflectionManager reflectionManager, ILogManager logManager) : base(typeFactory, reflectionManager, logManager) + public ServerComponentFactory(IDynamicTypeFactoryInternal typeFactory, IReflectionManager reflectionManager, ISerializationManager serManager, ILogManager logManager) : base(typeFactory, reflectionManager, serManager, logManager) { RegisterIgnore("Input"); RegisterIgnore("AnimationPlayer"); diff --git a/Robust.Shared/GameObjects/ComponentFactory.cs b/Robust.Shared/GameObjects/ComponentFactory.cs index d0161db08e5..b95c7a1668d 100644 --- a/Robust.Shared/GameObjects/ComponentFactory.cs +++ b/Robust.Shared/GameObjects/ComponentFactory.cs @@ -8,7 +8,9 @@ using Robust.Shared.GameStates; using Robust.Shared.IoC; using Robust.Shared.Log; +using Robust.Shared.Prototypes; using Robust.Shared.Reflection; +using Robust.Shared.Serialization.Manager; using Robust.Shared.Timing; using Robust.Shared.Utility; @@ -18,6 +20,7 @@ namespace Robust.Shared.GameObjects internal class ComponentFactory( IDynamicTypeFactoryInternal _typeFactory, IReflectionManager _reflectionManager, + ISerializationManager _serManager, ILogManager logManager) : IComponentFactory { private readonly ISawmill _sawmill = logManager.GetSawmill("ent.componentFactory"); @@ -181,6 +184,13 @@ public void IgnoreMissingComponents(string postfix = "") _ignoreMissingComponentPostfix = postfix ?? throw new ArgumentNullException(nameof(postfix)); } + public IComponent GetComponent(EntityPrototype.ComponentRegistryEntry entry) + { + var copy = GetComponent(entry.Component.GetType()); + _serManager.CopyTo(entry.Component, ref copy, notNullableOverride: true); + return copy; + } + public void RegisterIgnore(params string[] names) { foreach (var name in names) diff --git a/Robust.Shared/GameObjects/EntityManager.Components.cs b/Robust.Shared/GameObjects/EntityManager.Components.cs index 35d911c0c43..adb2a3ee2ec 100644 --- a/Robust.Shared/GameObjects/EntityManager.Components.cs +++ b/Robust.Shared/GameObjects/EntityManager.Components.cs @@ -297,6 +297,16 @@ public static implicit operator T(CompInitializeHandle handle) return new CompInitializeHandle(this, uid, newComponent, reg.Idx); } + public void AddComponent( + EntityUid uid, + EntityPrototype.ComponentRegistryEntry entry, + bool overwrite = false, + MetaDataComponent? metadata = null) + { + var copy = _componentFactory.GetComponent(entry); + AddComponent(uid, copy, overwrite, metadata); + } + /// public void AddComponent(EntityUid uid, T component, bool overwrite = false, MetaDataComponent? metadata = null) where T : IComponent { diff --git a/Robust.Shared/GameObjects/IComponentFactory.cs b/Robust.Shared/GameObjects/IComponentFactory.cs index 8f22cb4c374..e060c94d955 100644 --- a/Robust.Shared/GameObjects/IComponentFactory.cs +++ b/Robust.Shared/GameObjects/IComponentFactory.cs @@ -112,6 +112,8 @@ public interface IComponentFactory /// If provided, will only ignore components ending with the postfix. void IgnoreMissingComponents(string postfix = ""); + IComponent GetComponent(EntityPrototype.ComponentRegistryEntry entry); + /// /// Gets a new component instantiated of the specified type. /// diff --git a/Robust.Shared/GameObjects/Systems/PrototypeReloadSystem.cs b/Robust.Shared/GameObjects/Systems/PrototypeReloadSystem.cs index 2a240e03fa2..f0a73252b94 100644 --- a/Robust.Shared/GameObjects/Systems/PrototypeReloadSystem.cs +++ b/Robust.Shared/GameObjects/Systems/PrototypeReloadSystem.cs @@ -12,7 +12,6 @@ namespace Robust.Shared.GameObjects; internal sealed class PrototypeReloadSystem : EntitySystem { [Dependency] private readonly IPrototypeManager _prototypes = default!; - [Dependency] private readonly IComponentFactory _componentFactory = default!; public override void Initialize() { @@ -36,43 +35,62 @@ private void OnPrototypesReloaded(PrototypesReloadedEventArgs eventArgs) } } + private bool IsIgnored(EntityPrototype.ComponentRegistryEntry entry) + { + var compType = entry.Component.GetType(); + + if (compType == typeof(TransformComponent) || compType == typeof(MetaDataComponent)) + return true; + + return false; + } + private void UpdateEntity(EntityUid entity, MetaDataComponent metaData, EntityPrototype newPrototype) { var oldPrototype = metaData.EntityPrototype; + var modified = false; - var oldPrototypeComponents = oldPrototype?.Components.Keys - .Where(n => n != "Transform" && n != "MetaData") - .Select(name => (name, _componentFactory.GetRegistration(name).Type)) - .ToList() ?? new List<(string name, Type Type)>(); + if (oldPrototype != null) + { + foreach (var oldComp in oldPrototype.Components) + { + if (IsIgnored(oldComp.Value)) + continue; - var newPrototypeComponents = newPrototype.Components.Keys - .Where(n => n != "Transform" && n != "MetaData") - .Select(name => (name, _componentFactory.GetRegistration(name).Type)) - .ToList(); + // Removed + if (!newPrototype.Components.TryGetValue(oldComp.Key, out var newComp)) + { + modified = true; + RemComp(entity, oldComp.Value.Component.GetType()); + continue; + } - var ignoredComponents = new List(); + // Modified + if (!newComp.Mapping.Equals(oldComp.Value.Mapping)) + { + modified = true; + EntityManager.AddComponent(entity, newComp, overwrite: true, metaData); + } + } + } - // Find components to be removed, and remove them - foreach (var (name, type) in oldPrototypeComponents.Except(newPrototypeComponents)) + foreach (var newComp in newPrototype.Components) { - if (newPrototype.Components.ContainsKey(name)) - { - ignoredComponents.Add(name); + if (IsIgnored(newComp.Value)) continue; - } - RemComp(entity, type); - } + // Existing component, handled above + if (oldPrototype?.Components.ContainsKey(newComp.Key) == true) + continue; - EntityManager.CullRemovedComponents(); + // Added + modified = true; + EntityManager.AddComponent(entity, newComp.Value, overwrite: true, metadata: metaData); + } - // Add new components - foreach (var (name, _) in newPrototypeComponents.Where(t => !ignoredComponents.Contains(t.name)) - .Except(oldPrototypeComponents)) + if (modified) { - var data = newPrototype.Components[name]; - var component = _componentFactory.GetComponent(name); - EntityManager.AddComponent(entity, component); + EntityManager.CullRemovedComponents(); } // Update entity metadata diff --git a/Robust.UnitTesting/Shared/GameObjects/EntityEventBusTests.ComponentEvent.cs b/Robust.UnitTesting/Shared/GameObjects/EntityEventBusTests.ComponentEvent.cs index acd2f0a3d81..8a190e0b17f 100644 --- a/Robust.UnitTesting/Shared/GameObjects/EntityEventBusTests.ComponentEvent.cs +++ b/Robust.UnitTesting/Shared/GameObjects/EntityEventBusTests.ComponentEvent.cs @@ -5,6 +5,7 @@ using Robust.Shared.IoC; using Robust.Shared.Log; using Robust.Shared.Reflection; +using Robust.Shared.Serialization.Manager; using Robust.UnitTesting.Shared.Reflection; namespace Robust.UnitTesting.Shared.GameObjects @@ -14,7 +15,7 @@ public sealed partial class EntityEventBusTests [Test] public void SubscribeCompEvent() { - var compFactory = new ComponentFactory(new DynamicTypeFactory(), new ReflectionManagerTest(), new LogManager()); + var compFactory = new ComponentFactory(new DynamicTypeFactory(), new ReflectionManagerTest(), new SerializationManager(), new LogManager()); // Arrange var entUid = new EntityUid(7);