Validate that client prototypes are serializable (#18780)
This commit is contained in:
@@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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";
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user