Move entity prototype reload logic to entity system.

Removes dependency of IPrototypeManager -> IEntityManager.
This commit is contained in:
Pieter-Jan Briers
2022-08-13 23:01:19 +02:00
parent e34935c9e2
commit 2017d943fb
4 changed files with 89 additions and 73 deletions

View File

@@ -70,6 +70,7 @@ Template for new versions:
* Word-wrapping logic has been split off from `RichTextEntry`, into a new helper struct `WordWrap`.
* Some internal logic in `LineEdit` has been shared with `TextEdit` by moving it to a new `TextEditShared` file.
* SDL2 backend now uses `[UnmanagedCallersOnly]` instead of `GetFunctionPointerForDelegate`-style P/Invoke marshalling.
* Entity prototype reloading logic has been moved out of `PrototypeManager` and into a new `PrototypeReloadSystem`.
## 0.62.1.0

View File

@@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Robust.Shared.IoC;
using Robust.Shared.Prototypes;
namespace Robust.Shared.GameObjects;
/// <summary>
/// Responsible for applying relevant changes to active entities when prototypes are reloaded.
/// </summary>
internal sealed class PrototypeReloadSystem : EntitySystem
{
[Dependency] private readonly IPrototypeManager _prototypes = default!;
[Dependency] private readonly IComponentFactory _componentFactory = default!;
public override void Initialize()
{
_prototypes.PrototypesReloaded += OnPrototypesReloaded;
}
public override void Shutdown()
{
base.Shutdown();
_prototypes.PrototypesReloaded -= OnPrototypesReloaded;
}
private void OnPrototypesReloaded(PrototypesReloadedEventArgs eventArgs)
{
if (!eventArgs.ByType.TryGetValue(typeof(EntityPrototype), out var set))
return;
foreach (var metadata in EntityQuery<MetaDataComponent>())
{
var id = metadata.EntityPrototype?.ID;
if (id == null || !set.Modified.ContainsKey(id))
continue;
var proto = _prototypes.Index<EntityPrototype>(id);
UpdateEntity(metadata.Owner, metadata, proto);
}
}
private void UpdateEntity(EntityUid entity, MetaDataComponent metaData, EntityPrototype newPrototype)
{
var oldPrototype = metaData.EntityPrototype;
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)>();
var newPrototypeComponents = newPrototype.Components.Keys
.Where(n => n != "Transform" && n != "MetaData")
.Select(name => (name, _componentFactory.GetRegistration(name).Type))
.ToList();
var ignoredComponents = new List<string>();
// Find components to be removed, and remove them
foreach (var (name, type) in oldPrototypeComponents.Except(newPrototypeComponents))
{
if (newPrototype.Components.ContainsKey(name))
{
ignoredComponents.Add(name);
continue;
}
RemComp(entity, type);
}
EntityManager.CullRemovedComponents();
// Add new components
foreach (var (name, _) in newPrototypeComponents.Where(t => !ignoredComponents.Contains(t.name))
.Except(oldPrototypeComponents))
{
var data = newPrototype.Components[name];
var component = (Component)_componentFactory.GetComponent(name);
component.Owner = entity;
EntityManager.AddComponent(entity, component);
}
// Update entity metadata
metaData.EntityPrototype = newPrototype;
}
}

View File

@@ -190,60 +190,6 @@ namespace Robust.Shared.Prototypes
return true;
}
public void UpdateEntity(EntityUid entity)
{
var entityManager = IoCManager.Resolve<IEntityManager>();
var metaData = entityManager.GetComponent<MetaDataComponent>(entity);
if (ID != metaData.EntityPrototype?.ID)
{
Logger.Error(
$"Reloaded prototype used to update entity did not match entity's existing prototype: Expected '{ID}', got '{entityManager.GetComponent<MetaDataComponent>(entity).EntityPrototype?.ID}'");
return;
}
var factory = IoCManager.Resolve<IComponentFactory>();
var oldPrototype = metaData.EntityPrototype;
var oldPrototypeComponents = oldPrototype?.Components.Keys
.Where(n => n != "Transform" && n != "MetaData")
.Select(name => (name, factory.GetRegistration(name).Type))
.ToList() ?? new List<(string name, Type Type)>();
var newPrototypeComponents = Components.Keys
.Where(n => n != "Transform" && n != "MetaData")
.Select(name => (name, factory.GetRegistration(name).Type))
.ToList();
var ignoredComponents = new List<string>();
// Find components to be removed, and remove them
foreach (var (name, type) in oldPrototypeComponents.Except(newPrototypeComponents))
{
if (Components.Keys.Contains(name))
{
ignoredComponents.Add(name);
continue;
}
entityManager.RemoveComponent(entity, type);
}
entityManager.CullRemovedComponents();
// Add new components
foreach (var (name, type) in newPrototypeComponents.Where(t => !ignoredComponents.Contains(t.name))
.Except(oldPrototypeComponents))
{
var data = Components[name];
var component = (Component) factory.GetComponent(name);
component.Owner = entity;
entityManager.AddComponent(entity, component);
}
// Update entity metadata
metaData.EntityPrototype = this;
}
internal static void LoadEntity(
EntityPrototype? prototype,
EntityUid entity,

View File

@@ -8,7 +8,6 @@ using System.Threading;
using JetBrains.Annotations;
using Robust.Shared.Asynchronous;
using Robust.Shared.ContentPack;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.IoC.Exceptions;
using Robust.Shared.Log;
@@ -237,7 +236,6 @@ namespace Robust.Shared.Prototypes
{
[Dependency] private readonly IReflectionManager _reflectionManager = default!;
[Dependency] protected readonly IResourceManager Resources = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] protected readonly ITaskManager TaskManager = default!;
[Dependency] private readonly ISerializationManager _serializationManager = default!;
@@ -480,23 +478,6 @@ namespace Robust.Shared.Prototypes
g => g.Key,
g => new PrototypesReloadedEventArgs.PrototypeChangeSet(
g.Value.Where(x => _prototypes[g.Key].ContainsKey(x)).ToDictionary(a => a, a => _prototypes[g.Key][a])))));
// TODO filter by entity prototypes changed
if (!pushed.ContainsKey(typeof(EntityPrototype))) return;
var entityPrototypes = _prototypes[typeof(EntityPrototype)];
foreach (var prototype in pushed[typeof(EntityPrototype)])
{
foreach (var entity in _entityManager.GetEntities())
{
var metaData = _entityManager.GetComponent<MetaDataComponent>(entity);
if (metaData.EntityPrototype != null && metaData.EntityPrototype.ID == prototype)
{
((EntityPrototype) entityPrototypes[prototype]).UpdateEntity(entity);
}
}
}
#endif
}