Browse Source

Features can now have multiple definitions of each by way of an array of objects

pull/73/head
Anairkoen Schno 3 years ago
parent
commit
c3515aabf4
Signed by: DaNike GPG Key ID: BEFB74D5F3FC4387
5 changed files with 41 additions and 14 deletions
  1. +27
    -4
      IPA.Loader/JsonConverters/FeaturesFieldConverter.cs
  2. +4
    -3
      IPA.Loader/Loader/Features/ConfigProviderFeature.cs
  3. +6
    -5
      IPA.Loader/Loader/Features/DefineFeature.cs
  4. +3
    -1
      IPA.Loader/Loader/PluginLoader.cs
  5. +1
    -1
      IPA.Loader/Loader/PluginManifest.cs

+ 27
- 4
IPA.Loader/JsonConverters/FeaturesFieldConverter.cs View File

@ -3,15 +3,24 @@ using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace IPA.JsonConverters
{
internal class FeaturesFieldConverter : JsonConverter<Dictionary<string, JObject>>
internal class FeaturesFieldConverter : JsonConverter<Dictionary<string, List<JObject>>>
{
public override Dictionary<string, JObject> ReadJson(JsonReader reader, Type objectType, Dictionary<string, JObject> existingValue, bool hasExistingValue, JsonSerializer serializer)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void Assert([DoesNotReturnIf(false)] bool condition)
{
if (!condition)
throw new InvalidOperationException();
}
public override Dictionary<string, List<JObject>> ReadJson(JsonReader reader, Type objectType, Dictionary<string, List<JObject>> existingValue, bool hasExistingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.StartArray)
{
@ -20,10 +29,24 @@ namespace IPA.JsonConverters
return existingValue;
}
return serializer.Deserialize<Dictionary<string, JObject>>(reader);
var dict = new Dictionary<string, List<JObject>>();
Assert(reader.TokenType == JsonToken.StartObject && reader.Read());
while (reader.TokenType == JsonToken.PropertyName)
{
var name = reader.ReadAsString();
var list = reader.TokenType == JsonToken.StartObject
? (new() { serializer.Deserialize<JObject>(reader) })
: serializer.Deserialize<List<JObject>>(reader);
dict.Add(name, list);
}
Assert(reader.TokenType == JsonToken.EndObject && reader.Read());
return dict;
}
public override void WriteJson(JsonWriter writer, Dictionary<string, JObject> value, JsonSerializer serializer)
public override void WriteJson(JsonWriter writer, Dictionary<string, List<JObject>> value, JsonSerializer serializer)
{
serializer.Serialize(writer, value);
}


+ 4
- 3
IPA.Loader/Loader/Features/ConfigProviderFeature.cs View File

@ -1,4 +1,5 @@
using Newtonsoft.Json;
#nullable enable
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.IO;
@ -18,7 +19,7 @@ namespace IPA.Loader.Features
DataModel data;
try
{
data = featureData.ToObject<DataModel>();
data = featureData.ToObject<DataModel>() ?? throw new InvalidOperationException("Feature data is null");
}
catch (Exception e)
{
@ -36,7 +37,7 @@ namespace IPA.Loader.Features
InvalidMessage = $"Invalid type name {data.TypeName}";
return false;
}
catch (Exception e) when (e is FileNotFoundException || e is FileLoadException || e is BadImageFormatException)
catch (Exception e) when (e is FileNotFoundException or FileLoadException or BadImageFormatException)
{
string filename;


+ 6
- 5
IPA.Loader/Loader/Features/DefineFeature.cs View File

@ -1,4 +1,5 @@
using IPA.Logging;
#nullable enable
using IPA.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
@ -15,12 +16,12 @@ namespace IPA.Loader.Features
[JsonProperty("type", Required = Required.Always)]
public string TypeName = "";
[JsonProperty("name", Required = Required.DisallowNull)]
public string ActualName = null;
public string? ActualName = null;
public string Name => ActualName ?? TypeName;
}
private DataModel data;
private DataModel data = null!;
protected override bool Initialize(PluginMetadata meta, JObject featureData)
{
@ -28,7 +29,7 @@ namespace IPA.Loader.Features
try
{
data = featureData.ToObject<DataModel>();
data = featureData.ToObject<DataModel>() ?? throw new InvalidOperationException("Feature data is null");
}
catch (Exception e)
{
@ -54,7 +55,7 @@ namespace IPA.Loader.Features
Logger.features.Error($"Invalid type name {data.TypeName}");
return;
}
catch (Exception e) when (e is FileNotFoundException || e is FileLoadException || e is BadImageFormatException)
catch (Exception e) when (e is FileNotFoundException or FileLoadException or BadImageFormatException)
{
var filename = "";


+ 3
- 1
IPA.Loader/Loader/PluginLoader.cs View File

@ -809,7 +809,9 @@ namespace IPA.Loader
{
foreach (var meta in PluginsMetadata)
{
foreach (var feature in meta.Manifest.Features.Select(f => new Feature.Instance(meta, f.Key, f.Value)))
foreach (var feature in meta.Manifest.Features
.SelectMany(f => f.Value.Select(o => (f.Key, o)))
.Select(t => new Feature.Instance(meta, t.Key, t.o)))
{
if (feature.TryGetDefiningPlugin(out var plugin) && plugin == null)
{ // this is a DefineFeature, so we want to initialize it early


+ 1
- 1
IPA.Loader/Loader/PluginManifest.cs View File

@ -43,7 +43,7 @@ namespace IPA.Loader
public Dictionary<string, VersionRange> Conflicts = new();
[JsonProperty("features", Required = Required.DisallowNull), JsonConverter(typeof(FeaturesFieldConverter))]
public Dictionary<string, JObject> Features = new();
public Dictionary<string, List<JObject>> Features = new();
[JsonProperty("loadBefore", Required = Required.DisallowNull)]
public string[] LoadBefore = Array.Empty<string>();


Loading…
Cancel
Save