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 Newtonsoft.Json.Linq;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace IPA.JsonConverters 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) if (reader.TokenType == JsonToken.StartArray)
{ {
@ -20,10 +29,24 @@ namespace IPA.JsonConverters
return existingValue; 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); 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 Newtonsoft.Json.Linq;
using System; using System;
using System.IO; using System.IO;
@ -18,7 +19,7 @@ namespace IPA.Loader.Features
DataModel data; DataModel data;
try try
{ {
data = featureData.ToObject<DataModel>();
data = featureData.ToObject<DataModel>() ?? throw new InvalidOperationException("Feature data is null");
} }
catch (Exception e) catch (Exception e)
{ {
@ -36,7 +37,7 @@ namespace IPA.Loader.Features
InvalidMessage = $"Invalid type name {data.TypeName}"; InvalidMessage = $"Invalid type name {data.TypeName}";
return false; 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; 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;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using System; using System;
@ -15,12 +16,12 @@ namespace IPA.Loader.Features
[JsonProperty("type", Required = Required.Always)] [JsonProperty("type", Required = Required.Always)]
public string TypeName = ""; public string TypeName = "";
[JsonProperty("name", Required = Required.DisallowNull)] [JsonProperty("name", Required = Required.DisallowNull)]
public string ActualName = null;
public string? ActualName = null;
public string Name => ActualName ?? TypeName; public string Name => ActualName ?? TypeName;
} }
private DataModel data;
private DataModel data = null!;
protected override bool Initialize(PluginMetadata meta, JObject featureData) protected override bool Initialize(PluginMetadata meta, JObject featureData)
{ {
@ -28,7 +29,7 @@ namespace IPA.Loader.Features
try try
{ {
data = featureData.ToObject<DataModel>();
data = featureData.ToObject<DataModel>() ?? throw new InvalidOperationException("Feature data is null");
} }
catch (Exception e) catch (Exception e)
{ {
@ -54,7 +55,7 @@ namespace IPA.Loader.Features
Logger.features.Error($"Invalid type name {data.TypeName}"); Logger.features.Error($"Invalid type name {data.TypeName}");
return; 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 = ""; 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 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) if (feature.TryGetDefiningPlugin(out var plugin) && plugin == null)
{ // this is a DefineFeature, so we want to initialize it early { // 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(); public Dictionary<string, VersionRange> Conflicts = new();
[JsonProperty("features", Required = Required.DisallowNull), JsonConverter(typeof(FeaturesFieldConverter))] [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)] [JsonProperty("loadBefore", Required = Required.DisallowNull)]
public string[] LoadBefore = Array.Empty<string>(); public string[] LoadBefore = Array.Empty<string>();


Loading…
Cancel
Save