mirror of
https://github.com/Facepunch/sbox-public.git
synced 2025-12-23 22:48:07 -05:00
This commit imports the C# engine code and game files, excluding C++ source code. [Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
191 lines
3.7 KiB
C#
191 lines
3.7 KiB
C#
using System.Collections;
|
|
using System.Text.Json.Serialization;
|
|
|
|
namespace Sandbox;
|
|
|
|
/// <summary>
|
|
/// This isn't ideal, but it does what we want it to do. Kind of.
|
|
/// </summary>
|
|
internal static class Translation
|
|
{
|
|
internal static JsonSerializerOptions options;
|
|
|
|
static Translation()
|
|
{
|
|
options = new JsonSerializerOptions( JsonSerializerOptions.Default );
|
|
options.PropertyNameCaseInsensitive = true;
|
|
options.NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString | System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals;
|
|
options.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault;
|
|
|
|
options.Converters.Add( new JsonStringEnumConverter( null, true ) );
|
|
}
|
|
|
|
internal static bool TryConvert( ref object value, Type targetType )
|
|
{
|
|
if ( TryConvert( value, targetType, out var converted ) )
|
|
{
|
|
value = converted;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
internal static bool TryConvert( object from, System.Type targetType, out object convertedValue )
|
|
{
|
|
convertedValue = null;
|
|
|
|
//
|
|
// Old value is null
|
|
//
|
|
if ( from == null )
|
|
{
|
|
return true;
|
|
}
|
|
|
|
var fromT = from.GetType();
|
|
|
|
//
|
|
// Targetting Nullable? Work with the underlying type
|
|
//
|
|
if ( targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof( Nullable<> ) )
|
|
{
|
|
targetType = Nullable.GetUnderlyingType( targetType ) ?? targetType;
|
|
}
|
|
|
|
//
|
|
// Type compatible matches
|
|
//
|
|
if ( fromT == targetType || fromT.IsAssignableTo( targetType ) )
|
|
{
|
|
convertedValue = from;
|
|
return true;
|
|
}
|
|
|
|
//
|
|
// String
|
|
//
|
|
if ( targetType == typeof( string ) )
|
|
{
|
|
convertedValue = $"{from}";
|
|
return true;
|
|
}
|
|
|
|
//
|
|
// JsonElement
|
|
//
|
|
if ( from is JsonElement jse )
|
|
{
|
|
convertedValue = jse.Deserialize( targetType, options );
|
|
return true;
|
|
}
|
|
|
|
//
|
|
// Bool
|
|
//
|
|
if ( targetType == typeof( bool ) )
|
|
{
|
|
convertedValue = $"{from}".ToBool();
|
|
return true;
|
|
}
|
|
|
|
//
|
|
// Bool
|
|
//
|
|
if ( targetType.IsEnum )
|
|
{
|
|
convertedValue = System.Enum.Parse( targetType, from.ToString() );
|
|
return true;
|
|
}
|
|
|
|
//
|
|
// Float
|
|
//
|
|
if ( targetType == typeof( float ) )
|
|
{
|
|
if ( float.TryParse( from.ToString(), out var f ) )
|
|
{
|
|
convertedValue = f;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//
|
|
// Int
|
|
//
|
|
if ( targetType == typeof( int ) )
|
|
{
|
|
if ( from is string str )
|
|
{
|
|
convertedValue = str.ToInt();
|
|
return true;
|
|
}
|
|
|
|
convertedValue = Convert.ToInt32( from );
|
|
return true;
|
|
}
|
|
|
|
//
|
|
// List
|
|
//
|
|
if ( targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof( List<string> ).GetGenericTypeDefinition() )
|
|
{
|
|
if ( fromT.IsArray && fromT.GetElementType() == targetType.GenericTypeArguments[0] )
|
|
{
|
|
convertedValue = System.Activator.CreateInstance( targetType, new[] { from } );
|
|
return true;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Array
|
|
//
|
|
if ( targetType.IsArray )
|
|
{
|
|
if ( from is IList list )
|
|
{
|
|
var a = Array.CreateInstance( fromT.GenericTypeArguments[0], list.Count );
|
|
list.CopyTo( a, 0 );
|
|
convertedValue = a;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Implicit conversion
|
|
//
|
|
var op_Implicit = targetType.GetMethod( "op_Implicit", new[] { from.GetType() } );
|
|
if ( op_Implicit != null )
|
|
{
|
|
convertedValue = op_Implicit.Invoke( null, new[] { from } );
|
|
return true;
|
|
}
|
|
|
|
//
|
|
// convertable
|
|
//
|
|
if ( from is IConvertible )
|
|
{
|
|
try
|
|
{
|
|
var changedValue = System.Convert.ChangeType( from, targetType );
|
|
if ( changedValue is not null )
|
|
{
|
|
convertedValue = changedValue;
|
|
return true;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
Log.Trace( $"Couldn't convert {from} from its type to {targetType}" );
|
|
}
|
|
}
|
|
|
|
// TODO - serialize to json, deserialize from json
|
|
|
|
return false;
|
|
}
|
|
}
|