Preparation fo Mystery rolling
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
namespace ALttPRandomizer.Serialization {
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ALttPRandomizer.Model;
|
||||
using YamlDotNet.Core;
|
||||
using YamlDotNet.Core.Events;
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
public class RandomizableWeightsYamlConverters : IYamlTypeConverter {
|
||||
private readonly Dictionary<Type, IYamlTypeConverter> converters = new();
|
||||
|
||||
public bool Accepts(Type type) {
|
||||
if (this.converters.ContainsKey(type)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!type.IsGenericType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type.GetGenericTypeDefinition() != typeof(RandomizableWeights<>)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Type itemType = type.GetGenericArguments()[0];
|
||||
Type innerType = typeof(RandomizableWeightsYamlConverter<>).MakeGenericType(itemType)!;
|
||||
|
||||
this.converters[type] = (IYamlTypeConverter) Activator.CreateInstance(innerType)!;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public object? ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer) {
|
||||
return this.converters[type].ReadYaml(parser, type, rootDeserializer);
|
||||
}
|
||||
|
||||
public void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer) {
|
||||
this.converters[type].WriteYaml(emitter, value, type, serializer);
|
||||
}
|
||||
}
|
||||
|
||||
internal class RandomizableWeightsYamlConverter<T> : IYamlTypeConverter where T : struct, Enum {
|
||||
private readonly Type valueType;
|
||||
private readonly Type dictionaryType;
|
||||
|
||||
public RandomizableWeightsYamlConverter() {
|
||||
this.valueType = typeof(T);
|
||||
this.dictionaryType = typeof(IDictionary<T, int>);
|
||||
}
|
||||
|
||||
public bool Accepts(Type type) {
|
||||
return type == typeof(RandomizableWeights<T>);
|
||||
}
|
||||
|
||||
public object? ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer) {
|
||||
if (parser.Accept<Scalar>(out var evt)) {
|
||||
if (evt.Value == "null") {
|
||||
parser.Consume<Scalar>();
|
||||
return RandomizableWeights<T>.EmptyWeights;
|
||||
}
|
||||
var value = rootDeserializer.Invoke(this.valueType);
|
||||
if (value is T t) {
|
||||
return RandomizableWeights<T>.ConstantWeights(t);
|
||||
} else {
|
||||
return RandomizableWeights<T>.EmptyWeights;
|
||||
}
|
||||
}
|
||||
|
||||
if (parser.Accept<MappingStart>(out _)) {
|
||||
var value = rootDeserializer.Invoke(this.dictionaryType);
|
||||
if (value is IDictionary<T, int> dict) {
|
||||
return RandomizableWeights<T>.FromDictionary(dict);
|
||||
} else {
|
||||
return RandomizableWeights<T>.EmptyWeights;
|
||||
}
|
||||
}
|
||||
|
||||
throw new YamlException($"Error reading type RandomizableWeights<{typeof(T).Name}>.");
|
||||
}
|
||||
|
||||
public void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer) {
|
||||
if (value is RandomizableWeights<T> weights) {
|
||||
switch (weights.Options.Count) {
|
||||
case 0:
|
||||
emitter.Emit(new Scalar("null"));
|
||||
break;
|
||||
case 1:
|
||||
serializer.Invoke(weights.Options[0].Item, valueType);
|
||||
break;
|
||||
default:
|
||||
emitter.Emit(new MappingStart());
|
||||
foreach (var (item, weight) in weights.Options) {
|
||||
serializer.Invoke(item, valueType);
|
||||
emitter.Emit(new Scalar(weight.ToString()));
|
||||
}
|
||||
emitter.Emit(new MappingEnd());
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
emitter.Emit(new MappingStart());
|
||||
emitter.Emit(new MappingEnd());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user