Validate that client prototypes are serializable (#18780)

This commit is contained in:
Leon Friedrich
2023-08-07 15:44:53 +12:00
committed by GitHub
parent 5c6013ab07
commit 5cc5a8c82e
5 changed files with 34 additions and 28 deletions

View File

@@ -28,19 +28,12 @@ public sealed class AtmosPipeAppearanceSystem : EntitySystem
if (!TryComp(uid, out SpriteComponent? sprite)) if (!TryComp(uid, out SpriteComponent? sprite))
return; return;
if (!_resCache.TryGetResource(SpriteSpecifierSerializer.TextureRoot / component.RsiPath, out RSIResource? rsi))
{
Logger.Error($"{nameof(AtmosPipeAppearanceSystem)} could not load to load RSI {component.RsiPath}.");
return;
}
foreach (PipeConnectionLayer layerKey in Enum.GetValues(typeof(PipeConnectionLayer))) foreach (PipeConnectionLayer layerKey in Enum.GetValues(typeof(PipeConnectionLayer)))
{ {
sprite.LayerMapReserveBlank(layerKey); sprite.LayerMapReserveBlank(layerKey);
var layer = sprite.LayerMapGet(layerKey); var layer = sprite.LayerMapGet(layerKey);
sprite.LayerSetRSI(layer, rsi.RSI); sprite.LayerSetRSI(layer, component.Sprite.RsiPath);
var layerState = component.State; sprite.LayerSetState(layer, component.Sprite.RsiState);
sprite.LayerSetState(layer, layerState);
sprite.LayerSetDirOffset(layer, ToOffset(layerKey)); sprite.LayerSetDirOffset(layer, ToOffset(layerKey));
} }
} }

View File

@@ -32,7 +32,7 @@ namespace Content.Client.Chemistry.Visualizers
[DataField("metamorphic")] [DataField("metamorphic")]
public bool Metamorphic = false; public bool Metamorphic = false;
[DataField("metamorphicDefaultSprite")] [DataField("metamorphicDefaultSprite")]
public SpriteSpecifier MetamorphicDefaultSprite = SpriteSpecifier.Invalid; public SpriteSpecifier? MetamorphicDefaultSprite;
[DataField("metamorphicNameFull")] [DataField("metamorphicNameFull")]
public string MetamorphicNameFull = "transformable-container-component-glass"; public string MetamorphicNameFull = "transformable-container-component-glass";
@@ -41,9 +41,12 @@ namespace Content.Client.Chemistry.Visualizers
/// If not set, will work as default. /// If not set, will work as default.
/// </summary> /// </summary>
[DataField("solutionName")] [DataField("solutionName")]
public string SolutionName = ""; public string? SolutionName;
[DataField("initialName")]
public string InitialName = string.Empty; public string InitialName = string.Empty;
[DataField("initialDescription")]
public string InitialDescription = string.Empty; public string InitialDescription = string.Empty;
} }
} }

View File

@@ -76,6 +76,7 @@ public sealed class SolutionContainerVisualsSystem : VisualizerSystem<SolutionCo
{ {
if (hasOverlay) if (hasOverlay)
args.Sprite.LayerSetVisible(overlayLayer, true); args.Sprite.LayerSetVisible(overlayLayer, true);
if (component.MetamorphicDefaultSprite != null)
args.Sprite.LayerSetSprite(baseLayer, component.MetamorphicDefaultSprite); args.Sprite.LayerSetSprite(baseLayer, component.MetamorphicDefaultSprite);
} }
} }

View File

@@ -1,4 +1,6 @@
using System.Collections.Generic;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.Markdown.Validation;
using Robust.UnitTesting; using Robust.UnitTesting;
namespace Content.IntegrationTests.Tests.PrototypeTests; namespace Content.IntegrationTests.Tests.PrototypeTests;
@@ -6,29 +8,37 @@ namespace Content.IntegrationTests.Tests.PrototypeTests;
public sealed class PrototypeTests public sealed class PrototypeTests
{ {
/// <summary> /// <summary>
/// This test writes all known prototypes as yaml files, then validates that the result is valid yaml. /// This test writes all known server prototypes as yaml files, then validates that the result is valid yaml.
/// Can help prevent instances where prototypes have bad C# default values. /// Can help prevent instances where prototypes have bad C# default values.
/// </summary> /// </summary>
[Test] [Test]
public async Task TestAllPrototypesAreSerializable() public async Task TestAllServerPrototypesAreSerializable()
{ {
await using var pairTracker = await PoolManager.GetServerClient(); await using var pairTracker = await PoolManager.GetServerClient();
var context = new PrototypeSaveTest.TestEntityUidContext(); var context = new PrototypeSaveTest.TestEntityUidContext();
Assert.Multiple(() => await SaveThenValidatePrototype(pairTracker.Pair.Server, "server", context);
{
Validate(pairTracker.Pair.Server, "server", context);
// TODO fix client serialization
//Validate(pairTracker.Pair.Client, "client", context);
});
await pairTracker.CleanReturnAsync(); await pairTracker.CleanReturnAsync();
} }
public void Validate(RobustIntegrationTest.IntegrationInstance instance, string instanceId, /// <summary>
/// This test writes all known client prototypes as yaml files, then validates that the result is valid yaml.
/// Can help prevent instances where prototypes have bad C# default values.
/// </summary>
[Test]
public async Task TestAllClientPrototypesAreSerializable()
{
await using var pairTracker = await PoolManager.GetServerClient();
var context = new PrototypeSaveTest.TestEntityUidContext();
await SaveThenValidatePrototype(pairTracker.Pair.Client, "client", context);
await pairTracker.CleanReturnAsync();
}
public async Task SaveThenValidatePrototype(RobustIntegrationTest.IntegrationInstance instance, string instanceId,
PrototypeSaveTest.TestEntityUidContext ctx) PrototypeSaveTest.TestEntityUidContext ctx)
{ {
var protoMan = instance.ResolveDependency<IPrototypeManager>(); var protoMan = instance.ResolveDependency<IPrototypeManager>();
var errors = protoMan.ValidateAllPrototypesSerializable(ctx); Dictionary<Type, Dictionary<string, HashSet<ErrorNode>>> errors = default!;
await instance.WaitPost(() => errors = protoMan.ValidateAllPrototypesSerializable(ctx));
if (errors.Count == 0) if (errors.Count == 0)
return; return;

View File

@@ -1,11 +1,10 @@
using Robust.Shared.Utility;
namespace Content.Shared.Atmos.Components; namespace Content.Shared.Atmos.Components;
[RegisterComponent] [RegisterComponent]
public sealed class PipeAppearanceComponent : Component public sealed class PipeAppearanceComponent : Component
{ {
[DataField("rsi")] [DataField("sprite")]
public string RsiPath = "Structures/Piping/Atmospherics/pipe.rsi"; public SpriteSpecifier.Rsi Sprite = new(new("Structures/Piping/Atmospherics/pipe.rsi"), "pipeConnector");
[DataField("baseState")]
public string State = "pipeConnector";
} }