From d24854d94ff7cfd942364ae3be7de1f67b389932 Mon Sep 17 00:00:00 2001 From: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com> Date: Sat, 10 May 2025 21:37:42 +1000 Subject: [PATCH] Improve yaml validation errors for ignored prototypes (#5886) * Improve yaml validation errors for ignored prototypes * release notes * Comments --- RELEASE-NOTES.md | 4 ++-- Robust.Shared/Prototypes/IPrototypeManager.cs | 5 +++++ Robust.Shared/Prototypes/PrototypeManager.cs | 13 +++++++++++++ .../Custom/Prototype/PrototypeIdSerializer.cs | 6 ++---- .../Implementations/Generic/ProtoIdSerializer.cs | 15 +++++++++++++-- 5 files changed, 35 insertions(+), 8 deletions(-) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index af782d718..ced4fd771 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -39,7 +39,7 @@ END TEMPLATE--> ### New features -*None yet* +* Added `IPrototypeManager.IsIgnored()` for checking whether a given prototype kind has been marked as ignored via `RegisterIgnore()`. ### Bugfixes @@ -47,7 +47,7 @@ END TEMPLATE--> ### Other -*None yet* +* The yaml prototype id serialiser now provides better feedback when trying to validate an id for a prototype kind that has been ignored via `IPrototypeManager.RegisterIgnore()` ### Internal diff --git a/Robust.Shared/Prototypes/IPrototypeManager.cs b/Robust.Shared/Prototypes/IPrototypeManager.cs index 0b7b67e24..30950068c 100644 --- a/Robust.Shared/Prototypes/IPrototypeManager.cs +++ b/Robust.Shared/Prototypes/IPrototypeManager.cs @@ -306,6 +306,11 @@ public interface IPrototypeManager /// void RegisterIgnore(string name); + /// + /// Checks whether the given gind name has been marked as ignored via + /// + bool IsIgnored(string name); + /// /// Loads several prototype kinds into the manager. Note that this will re-build a frozen dictionary and should be avoided if possible. /// diff --git a/Robust.Shared/Prototypes/PrototypeManager.cs b/Robust.Shared/Prototypes/PrototypeManager.cs index 044c8d6ee..8efe3f258 100644 --- a/Robust.Shared/Prototypes/PrototypeManager.cs +++ b/Robust.Shared/Prototypes/PrototypeManager.cs @@ -920,6 +920,8 @@ namespace Robust.Shared.Prototypes return TryGetKindFrom(typeof(T), out kind); } + public bool IsIgnored(string name) => _ignoredPrototypeTypes.Contains(name); + /// public void RegisterIgnore(string name) { @@ -973,6 +975,17 @@ namespace Robust.Shared.Prototypes var name = attribute.Type ?? CalculatePrototypeName(kind); + if (_ignoredPrototypeTypes.Contains(name)) + { + // For whatever reason, we are registering a prototype despite it having been marked as ignored. + // This often happens when someone is moving a server or client prototype to shared. Maybe this should + // log an error, but I want to avoid breaking changes and maaaaybe there some weird instance where you + // want the client to know that a prototype kind exists, without having the client load information + // about the individual prototypes? So for now lets just log a warning instead of introducing breaking + // changes. + Sawmill.Warning($"Registering an ignored prototype {kind}"); + } + if (_kindNames.TryGetValue(name, out var existing)) { throw new InvalidImplementationException(kind, diff --git a/Robust.Shared/Serialization/TypeSerializers/Implementations/Custom/Prototype/PrototypeIdSerializer.cs b/Robust.Shared/Serialization/TypeSerializers/Implementations/Custom/Prototype/PrototypeIdSerializer.cs index 17ca71d3b..9a075f80f 100644 --- a/Robust.Shared/Serialization/TypeSerializers/Implementations/Custom/Prototype/PrototypeIdSerializer.cs +++ b/Robust.Shared/Serialization/TypeSerializers/Implementations/Custom/Prototype/PrototypeIdSerializer.cs @@ -3,6 +3,7 @@ using Robust.Shared.Prototypes; using Robust.Shared.Serialization.Manager; using Robust.Shared.Serialization.Markdown.Validation; using Robust.Shared.Serialization.Markdown.Value; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Generic; using Robust.Shared.Serialization.TypeSerializers.Interfaces; namespace Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype @@ -30,10 +31,7 @@ namespace Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Pro public virtual ValidationNode Validate(ISerializationManager serializationManager, ValueDataNode node, IDependencyCollection dependencies, ISerializationContext? context = null) { - var protoMan = dependencies.Resolve(); - return protoMan.TryGetKindFrom(out _) && protoMan.HasIndex(node.Value) - ? new ValidatedValueNode(node) - : new ErrorNode(node, $"PrototypeID {node.Value} for type {typeof(TPrototype)} at {node.Start} not found"); + return ProtoIdSerializer.Validate(dependencies, node); } } } diff --git a/Robust.Shared/Serialization/TypeSerializers/Implementations/Generic/ProtoIdSerializer.cs b/Robust.Shared/Serialization/TypeSerializers/Implementations/Generic/ProtoIdSerializer.cs index d04537c2a..cf383bb35 100644 --- a/Robust.Shared/Serialization/TypeSerializers/Implementations/Generic/ProtoIdSerializer.cs +++ b/Robust.Shared/Serialization/TypeSerializers/Implementations/Generic/ProtoIdSerializer.cs @@ -19,8 +19,19 @@ public sealed class ProtoIdSerializer : ITypeSerializer, ValueData { public ValidationNode Validate(ISerializationManager serialization, ValueDataNode node, IDependencyCollection dependencies, ISerializationContext? context = null) { - var prototypes = dependencies.Resolve(); - if (prototypes.TryGetKindFrom(out _) && prototypes.HasMapping(node.Value)) + return Validate(dependencies, node); + } + + public static ValidationNode Validate(IDependencyCollection deps, ValueDataNode node) + { + var proto = deps.Resolve(); + if (!proto.TryGetKindFrom(out var kind)) + return new ErrorNode(node, $"Unknown prototype kind: {typeof(T)}"); + + if (proto.IsIgnored(kind)) + return new ErrorNode(node,$"Attempting to validate an ignored prototype: {typeof(T)}.\nDid you forget to remove the IPrototypeManager.RegisterIgnore(\"{kind}\") call when moving a prototype to Shared?"); + + if (proto.HasMapping(node.Value)) return new ValidatedValueNode(node); return new ErrorNode(node, $"No {typeof(T)} found with id {node.Value}");