From 9330f0123459ec3f88694b3d1da58f792a026670 Mon Sep 17 00:00:00 2001 From: SmusiJarviss Date: Sun, 25 May 2025 20:13:54 +0200 Subject: [PATCH] Support nullable Vector2, Vector3, and Vector4 in YAML converter - Added handling of null scalars for nullable vector types. - Prevents errors when YAML contains 'null' for vector properties. - Maintains previous behavior for non-nullable vectors. --- .../CustomConverters/VectorsConverter.cs | 41 +++++++++++++++---- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/EXILED/Exiled.Loader/Features/Configs/CustomConverters/VectorsConverter.cs b/EXILED/Exiled.Loader/Features/Configs/CustomConverters/VectorsConverter.cs index 944e2f2784..f780234d93 100644 --- a/EXILED/Exiled.Loader/Features/Configs/CustomConverters/VectorsConverter.cs +++ b/EXILED/Exiled.Loader/Features/Configs/CustomConverters/VectorsConverter.cs @@ -12,6 +12,7 @@ namespace Exiled.Loader.Features.Configs.CustomConverters using System.Globalization; using System.IO; + using Exiled.API.Features; using Exiled.API.Features.Pools; using UnityEngine; @@ -21,18 +22,37 @@ namespace Exiled.Loader.Features.Configs.CustomConverters using YamlDotNet.Serialization; /// - /// Converts a Vector2, Vector3 or Vector4 to Yaml configs and vice versa. + /// Converts a Vector2, Vector3 or Vector4 (including nullable) to Yaml configs and vice versa. /// public sealed class VectorsConverter : IYamlTypeConverter { /// - public bool Accepts(Type type) => type == typeof(Vector2) || type == typeof(Vector3) || type == typeof(Vector4); + public bool Accepts(Type type) + { + Type baseType = Nullable.GetUnderlyingType(type) ?? type; + return baseType == typeof(Vector2) || baseType == typeof(Vector3) || baseType == typeof(Vector4); + } /// public object ReadYaml(IParser parser, Type type) { + Type baseType = Nullable.GetUnderlyingType(type) ?? type; + + if (parser.TryConsume(out Scalar scalar)) + { + if (string.IsNullOrEmpty(scalar.Value) || scalar.Value.Equals("null", StringComparison.OrdinalIgnoreCase)) + { + if (Nullable.GetUnderlyingType(type) != null) + return null; + + Log.Error($"Cannot assign null to non-nullable type {baseType.FullName}."); + } + + Log.Error($"Expected mapping, but got scalar: {scalar.Value}"); + } + if (!parser.TryConsume(out _)) - throw new InvalidDataException($"Cannot deserialize object of type {type.FullName}."); + Log.Error($"Cannot deserialize object of type {type.FullName}."); List coordinates = ListPool.Pool.Get(4); int i = 0; @@ -45,16 +65,17 @@ public object ReadYaml(IParser parser, Type type) continue; } - if (!parser.TryConsume(out Scalar scalar) || !float.TryParse(scalar.Value, NumberStyles.Float, CultureInfo.GetCultureInfo("en-US"), out float coordinate)) + if (!parser.TryConsume(out Scalar coordScalar) || + !float.TryParse(coordScalar.Value, NumberStyles.Float, CultureInfo.GetCultureInfo("en-US"), out float coordinate)) { ListPool.Pool.Return(coordinates); - throw new InvalidDataException($"Invalid float value."); + throw new InvalidDataException("Invalid float value."); } coordinates.Add(coordinate); } - object vector = Activator.CreateInstance(type, coordinates.ToArray()); + object vector = Activator.CreateInstance(baseType, coordinates.ToArray()); ListPool.Pool.Return(coordinates); @@ -64,6 +85,12 @@ public object ReadYaml(IParser parser, Type type) /// public void WriteYaml(IEmitter emitter, object value, Type type) { + if (value is null) + { + emitter.Emit(new Scalar("null")); + return; + } + Dictionary coordinates = DictionaryPool.Pool.Get(); if (value is Vector2 vector2) @@ -97,4 +124,4 @@ public void WriteYaml(IEmitter emitter, object value, Type type) emitter.Emit(new MappingEnd()); } } -} \ No newline at end of file +}