mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-01-02 03:18:23 -05:00
This commit imports the C# engine code and game files, excluding C++ source code. [Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
121 lines
2.8 KiB
C#
121 lines
2.8 KiB
C#
using System.Text;
|
|
using System.Text.Json;
|
|
using System.Text.Json.Serialization;
|
|
|
|
namespace Sandbox;
|
|
|
|
internal sealed class InterfaceConverterFactory : JsonConverterFactory
|
|
{
|
|
public override bool CanConvert( Type typeToConvert )
|
|
{
|
|
//
|
|
// Apply only to interfaces, no generic args
|
|
// Otherwise we pick up stuff like IList<T>
|
|
//
|
|
return typeToConvert.IsInterface && typeToConvert.GetGenericArguments().Length < 1;
|
|
}
|
|
|
|
public override JsonConverter CreateConverter( Type typeToConvert, JsonSerializerOptions options )
|
|
{
|
|
var converterType = typeof( InterfaceConverter<> ).MakeGenericType( typeToConvert );
|
|
return (JsonConverter)Activator.CreateInstance( converterType )!;
|
|
}
|
|
}
|
|
|
|
internal sealed class InterfaceConverter<T> : JsonConverter<T> where T : class
|
|
{
|
|
/// <summary>
|
|
/// A simple type value wrapper that indicates what type the value is.
|
|
/// </summary>
|
|
/// <param name="Type"></param>
|
|
/// <param name="Value"></param>
|
|
private record struct Wrapper( string Type, JsonElement Value );
|
|
|
|
public override T Read( ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options )
|
|
{
|
|
//
|
|
// No token to read
|
|
//
|
|
if ( reader.TokenType == JsonTokenType.Null )
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var data = JsonSerializer.Deserialize<Wrapper>( ref reader );
|
|
|
|
//
|
|
// Invalid data
|
|
//
|
|
if ( string.IsNullOrEmpty( data.Type ) || data.Value.ValueKind == JsonValueKind.Undefined )
|
|
{
|
|
return null;
|
|
}
|
|
|
|
//
|
|
// Component types
|
|
//
|
|
if ( data.Type == "Component" )
|
|
{
|
|
var rawText = data.Value.GetRawText();
|
|
var bytes = Encoding.UTF8.GetBytes( rawText );
|
|
var r = new Utf8JsonReader( bytes.AsSpan() );
|
|
r.Read(); // Advance to the first token
|
|
var obj = Component.JsonRead( ref r, null );
|
|
return (T)obj;
|
|
}
|
|
|
|
//
|
|
// Resource types
|
|
//
|
|
if ( data.Type == "Resource" )
|
|
{
|
|
if ( data.Value.ValueKind == JsonValueKind.String )
|
|
{
|
|
var path = data.Value.GetString();
|
|
var res = Resource.LoadFromPath( typeof( GameResource ), path );
|
|
return res as T;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public override void Write( Utf8JsonWriter writer, T value, JsonSerializerOptions options )
|
|
{
|
|
writer.WriteStartObject();
|
|
|
|
if ( value is null )
|
|
{
|
|
writer.WriteNull( "Type" );
|
|
writer.WriteNull( "Value" );
|
|
writer.WriteEndObject();
|
|
return;
|
|
}
|
|
|
|
if ( value is Resource resource )
|
|
{
|
|
writer.WriteString( "Type", "Resource" );
|
|
writer.WritePropertyName( "Value" );
|
|
writer.WriteStringValue( resource.ResourcePath );
|
|
writer.WriteEndObject();
|
|
return;
|
|
}
|
|
|
|
if ( value is Component component )
|
|
{
|
|
writer.WriteString( "Type", "Component" );
|
|
writer.WritePropertyName( "Value" );
|
|
Component.JsonWrite( component, writer );
|
|
writer.WriteEndObject();
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Unhandled type - write as null
|
|
//
|
|
writer.WriteNull( "Type" );
|
|
writer.WriteNull( "Value" );
|
|
writer.WriteEndObject();
|
|
}
|
|
}
|