mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 03:30:53 +01:00
Validate sprite specifier states (#3075)
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Serialization.Manager;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Serialization.Markdown.Mapping;
|
||||
using Robust.Shared.Serialization.Markdown.Validation;
|
||||
using Robust.Shared.Serialization.Markdown.Value;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations;
|
||||
|
||||
namespace Robust.Client.Serialization;
|
||||
|
||||
[TypeSerializer]
|
||||
public sealed class ClientSpriteSpecifierSerializer : SpriteSpecifierSerializer
|
||||
{
|
||||
public override ValidationNode ValidateRsi(ISerializationManager serializationManager,
|
||||
MappingDataNode node,
|
||||
IDependencyCollection dependencies,
|
||||
ISerializationContext? context)
|
||||
{
|
||||
if (!node.TryGet("sprite", out var pathNode) || pathNode is not ValueDataNode valuePathNode)
|
||||
{
|
||||
return new ErrorNode(node, "Sprite specifier has missing/invalid sprite node");
|
||||
}
|
||||
|
||||
if (!node.TryGet("state", out var stateNode) || stateNode is not ValueDataNode valueStateNode)
|
||||
{
|
||||
return new ErrorNode(node, "Sprite specifier has missing/invalid state node");
|
||||
}
|
||||
|
||||
var res = dependencies.Resolve<IResourceCache>();
|
||||
var rsiPath = SharedSpriteComponent.TextureRoot / valuePathNode.Value;
|
||||
if (!res.TryGetResource(rsiPath, out RSIResource? resource))
|
||||
{
|
||||
return new ErrorNode(node, "Failed to load RSI");
|
||||
}
|
||||
|
||||
if (!resource.RSI.TryGetState(valueStateNode.Value, out _))
|
||||
{
|
||||
return new ErrorNode(node, "Invalid RSI state");
|
||||
}
|
||||
|
||||
return new ValidatedValueNode(node);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Serialization.Manager;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Serialization.Markdown.Mapping;
|
||||
using Robust.Shared.Serialization.Markdown.Validation;
|
||||
using Robust.Shared.Serialization.Markdown.Value;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Server.Serialization;
|
||||
|
||||
[TypeSerializer]
|
||||
public sealed class ServerSpriteSpecifierSerializer : SpriteSpecifierSerializer
|
||||
{
|
||||
public override ValidationNode ValidateRsi(ISerializationManager serializationManager,
|
||||
MappingDataNode node,
|
||||
IDependencyCollection dependencies,
|
||||
ISerializationContext? context)
|
||||
{
|
||||
if (!node.TryGet("sprite", out var pathNode) || pathNode is not ValueDataNode valuePathNode)
|
||||
{
|
||||
return new ErrorNode(node, "Sprite specifier has missing/invalid sprite node");
|
||||
}
|
||||
|
||||
if (!valuePathNode.Value.EndsWith(".rsi")) // required so that resource path validation checks for the meta.json.
|
||||
{
|
||||
return new ErrorNode(node, "sprite node does not end in .rsi");
|
||||
}
|
||||
|
||||
if (!node.TryGet("state", out var stateNode) || stateNode is not ValueDataNode valueStateNode)
|
||||
{
|
||||
return new ErrorNode(node, "Sprite specifier has missing/invalid state node");
|
||||
}
|
||||
|
||||
var path = serializationManager.ValidateNode(typeof(ResourcePath),
|
||||
new ValueDataNode($"{SharedSpriteComponent.TextureRoot / valuePathNode.Value}"), context);
|
||||
|
||||
if (path is ErrorNode) return path;
|
||||
|
||||
// RSI meta-data & misc related functions are client only, so the server can't easily fully validate them.
|
||||
// However, as some sprites may be specified in server-exclusive prototypes, we should still try and check that
|
||||
// the state exists. So lets just check if the state .png exists, without properly validating the RSI's
|
||||
// meta.json
|
||||
|
||||
var statePath = serializationManager.ValidateNode(typeof(ResourcePath),
|
||||
new ValueDataNode($"{SharedSpriteComponent.TextureRoot / valuePathNode.Value / valueStateNode.Value}.png"), context);
|
||||
|
||||
if (statePath is ErrorNode) return statePath;
|
||||
|
||||
return new ValidatedValueNode(node);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using Robust.Shared.ContentPack;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Serialization.Manager;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Serialization.Markdown;
|
||||
@@ -13,8 +15,7 @@ using static Robust.Shared.Utility.SpriteSpecifier;
|
||||
|
||||
namespace Robust.Shared.Serialization.TypeSerializers.Implementations
|
||||
{
|
||||
[TypeSerializer]
|
||||
public sealed class SpriteSpecifierSerializer :
|
||||
public abstract class SpriteSpecifierSerializer :
|
||||
ITypeSerializer<Texture, ValueDataNode>,
|
||||
ITypeSerializer<EntityPrototype, ValueDataNode>,
|
||||
ITypeSerializer<Rsi, MappingDataNode>,
|
||||
@@ -123,24 +124,15 @@ namespace Robust.Shared.Serialization.TypeSerializers.Implementations
|
||||
IDependencyCollection dependencies,
|
||||
ISerializationContext? context)
|
||||
{
|
||||
if (!node.TryGet("sprite", out var pathNode) || pathNode is not ValueDataNode valuePathNode)
|
||||
{
|
||||
return new ErrorNode(node, "Sprite specifier has missing/invalid sprite node");
|
||||
}
|
||||
|
||||
if (!node.TryGet("state", out var stateNode) || stateNode is not ValueDataNode)
|
||||
{
|
||||
return new ErrorNode(node, "Sprite specifier has missing/invalid state node");
|
||||
}
|
||||
|
||||
var path = serializationManager.ValidateNode(typeof(ResourcePath),
|
||||
new ValueDataNode($"{SharedSpriteComponent.TextureRoot / valuePathNode.Value}"), context);
|
||||
|
||||
if (path is ErrorNode) return path;
|
||||
|
||||
return new ValidatedValueNode(node);
|
||||
// apparently explicit interface implementations can't be abstract.
|
||||
return ValidateRsi(serializationManager, node, dependencies, context);
|
||||
}
|
||||
|
||||
public abstract ValidationNode ValidateRsi(ISerializationManager serializationManager,
|
||||
MappingDataNode node,
|
||||
IDependencyCollection dependencies,
|
||||
ISerializationContext? context);
|
||||
|
||||
public DataNode Write(ISerializationManager serializationManager, Texture value, bool alwaysWrite = false,
|
||||
ISerializationContext? context = null)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user