From ff16a6567b6137b1aafed3470406d5f5884a5bdc Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Tue, 19 Jan 2021 21:20:25 -0500 Subject: add multi-key binding API (#744) --- .../Framework/Serialization/KeybindConverter.cs | 89 ++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 src/SMAPI/Framework/Serialization/KeybindConverter.cs (limited to 'src/SMAPI/Framework/Serialization') diff --git a/src/SMAPI/Framework/Serialization/KeybindConverter.cs b/src/SMAPI/Framework/Serialization/KeybindConverter.cs new file mode 100644 index 00000000..1bc146f8 --- /dev/null +++ b/src/SMAPI/Framework/Serialization/KeybindConverter.cs @@ -0,0 +1,89 @@ +using System; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using StardewModdingAPI.Toolkit.Serialization; +using StardewModdingAPI.Utilities; + +namespace StardewModdingAPI.Framework.Serialization +{ + /// Handles deserialization of and models. + internal class KeybindConverter : JsonConverter + { + /********* + ** Accessors + *********/ + /// + public override bool CanRead { get; } = true; + + /// + public override bool CanWrite { get; } = true; + + + /********* + ** Public methods + *********/ + /// Get whether this instance can convert the specified object type. + /// The object type. + public override bool CanConvert(Type objectType) + { + return + typeof(Keybind).IsAssignableFrom(objectType) + || typeof(KeybindList).IsAssignableFrom(objectType); + } + + /// Reads the JSON representation of the object. + /// The JSON reader. + /// The object type. + /// The object being read. + /// The calling serializer. + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + string path = reader.Path; + + // validate JSON type + if (reader.TokenType != JsonToken.String) + throw new SParseException($"Can't parse {nameof(KeybindList)} from {reader.TokenType} node (path: {reader.Path})."); + + // parse raw value + string str = JToken.Load(reader).Value(); + if (objectType == typeof(Keybind)) + { + return Keybind.TryParse(str, out Keybind parsed, out string[] errors) + ? parsed + : throw new SParseException($"Can't parse {nameof(Keybind)} from invalid value '{str}' (path: {path}).\n{string.Join("\n", errors)}"); + } + + if (objectType == typeof(KeybindList)) + { + return KeybindList.TryParse(str, out KeybindList parsed, out string[] errors) + ? parsed + : throw new SParseException($"Can't parse {nameof(KeybindList)} from invalid value '{str}' (path: {path}).\n{string.Join("\n", errors)}"); + } + + throw new SParseException($"Can't parse unexpected type {objectType} from {reader.TokenType} node (path: {reader.Path})."); + } + + /// Writes the JSON representation of the object. + /// The JSON writer. + /// The value. + /// The calling serializer. + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + writer.WriteValue(value?.ToString()); + } + + + /********* + ** Private methods + *********/ + /// Read a JSON string. + /// The JSON string value. + /// The path to the current JSON node. + protected KeybindList ReadString(string str, string path) + { + return KeybindList.TryParse(str, out KeybindList parsed, out string[] errors) + ? parsed + : throw new SParseException($"Can't parse {nameof(KeybindList)} from invalid value '{str}' (path: {path}).\n{string.Join("\n", errors)}"); + } + } +} -- cgit From 48f6857892ee4e075422f27a7aa5b78bea6b04e0 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 20 Jan 2021 01:22:29 -0500 Subject: fix null handling in keybind list parsing (#744) --- .../Framework/Serialization/KeybindConverter.cs | 57 ++++++++++------------ 1 file changed, 25 insertions(+), 32 deletions(-) (limited to 'src/SMAPI/Framework/Serialization') diff --git a/src/SMAPI/Framework/Serialization/KeybindConverter.cs b/src/SMAPI/Framework/Serialization/KeybindConverter.cs index 1bc146f8..7c5db3ad 100644 --- a/src/SMAPI/Framework/Serialization/KeybindConverter.cs +++ b/src/SMAPI/Framework/Serialization/KeybindConverter.cs @@ -40,27 +40,34 @@ namespace StardewModdingAPI.Framework.Serialization { string path = reader.Path; - // validate JSON type - if (reader.TokenType != JsonToken.String) - throw new SParseException($"Can't parse {nameof(KeybindList)} from {reader.TokenType} node (path: {reader.Path})."); - - // parse raw value - string str = JToken.Load(reader).Value(); - if (objectType == typeof(Keybind)) + switch (reader.TokenType) { - return Keybind.TryParse(str, out Keybind parsed, out string[] errors) - ? parsed - : throw new SParseException($"Can't parse {nameof(Keybind)} from invalid value '{str}' (path: {path}).\n{string.Join("\n", errors)}"); - } + case JsonToken.Null: + return objectType == typeof(Keybind) + ? new Keybind() + : new KeybindList(); - if (objectType == typeof(KeybindList)) - { - return KeybindList.TryParse(str, out KeybindList parsed, out string[] errors) - ? parsed - : throw new SParseException($"Can't parse {nameof(KeybindList)} from invalid value '{str}' (path: {path}).\n{string.Join("\n", errors)}"); - } + case JsonToken.String: + { + string str = JToken.Load(reader).Value(); + + if (objectType == typeof(Keybind)) + { + return Keybind.TryParse(str, out Keybind parsed, out string[] errors) + ? parsed + : throw new SParseException($"Can't parse {nameof(Keybind)} from invalid value '{str}' (path: {path}).\n{string.Join("\n", errors)}"); + } + else + { + return KeybindList.TryParse(str, out KeybindList parsed, out string[] errors) + ? parsed + : throw new SParseException($"Can't parse {nameof(KeybindList)} from invalid value '{str}' (path: {path}).\n{string.Join("\n", errors)}"); + } + } - throw new SParseException($"Can't parse unexpected type {objectType} from {reader.TokenType} node (path: {reader.Path})."); + default: + throw new SParseException($"Can't parse {objectType} from unexpected {reader.TokenType} node (path: {reader.Path})."); + } } /// Writes the JSON representation of the object. @@ -71,19 +78,5 @@ namespace StardewModdingAPI.Framework.Serialization { writer.WriteValue(value?.ToString()); } - - - /********* - ** Private methods - *********/ - /// Read a JSON string. - /// The JSON string value. - /// The path to the current JSON node. - protected KeybindList ReadString(string str, string path) - { - return KeybindList.TryParse(str, out KeybindList parsed, out string[] errors) - ? parsed - : throw new SParseException($"Can't parse {nameof(KeybindList)} from invalid value '{str}' (path: {path}).\n{string.Join("\n", errors)}"); - } } } -- cgit From 342fc80394ac2d1bd67fb1b745b8ddec927fac49 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 20 Jan 2021 23:22:24 -0500 Subject: rewrite C# 9 code not supported in Linux build tools yet --- src/SMAPI.Toolkit/SemanticVersion.cs | 12 ++++++------ src/SMAPI/Framework/SCore.cs | 2 +- src/SMAPI/Framework/SMultiplayer.cs | 4 ++-- src/SMAPI/Framework/Serialization/KeybindConverter.cs | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src/SMAPI/Framework/Serialization') diff --git a/src/SMAPI.Toolkit/SemanticVersion.cs b/src/SMAPI.Toolkit/SemanticVersion.cs index d58dce0c..2f3e282b 100644 --- a/src/SMAPI.Toolkit/SemanticVersion.cs +++ b/src/SMAPI.Toolkit/SemanticVersion.cs @@ -293,12 +293,12 @@ namespace StardewModdingAPI.Toolkit return string.Compare(this.ToString(), new SemanticVersion(otherMajor, otherMinor, otherPatch, otherPlatformRelease, otherTag).ToString(), StringComparison.OrdinalIgnoreCase); } - return CompareToRaw() switch - { - (< 0) => curOlder, - (> 0) => curNewer, - _ => same - }; + int result = CompareToRaw(); + if (result < 0) + return curOlder; + if (result > 0) + return curNewer; + return same; } /// Assert that the current version is valid. diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs index 1ac361cd..cd094ff4 100644 --- a/src/SMAPI/Framework/SCore.cs +++ b/src/SMAPI/Framework/SCore.cs @@ -132,7 +132,7 @@ namespace StardewModdingAPI.Framework private readonly ConcurrentQueue RawCommandQueue = new ConcurrentQueue(); /// A list of commands to execute on each screen. - private readonly PerScreen>> ScreenCommandQueue = new(() => new()); + private readonly PerScreen>> ScreenCommandQueue = new PerScreen>>(() => new List>()); /********* diff --git a/src/SMAPI/Framework/SMultiplayer.cs b/src/SMAPI/Framework/SMultiplayer.cs index 8e18cc09..5956b63f 100644 --- a/src/SMAPI/Framework/SMultiplayer.cs +++ b/src/SMAPI/Framework/SMultiplayer.cs @@ -56,10 +56,10 @@ namespace StardewModdingAPI.Framework private readonly bool LogNetworkTraffic; /// The backing field for . - private readonly PerScreen> PeersImpl = new(() => new Dictionary()); + private readonly PerScreen> PeersImpl = new PerScreen>(() => new Dictionary()); /// The backing field for . - private readonly PerScreen HostPeerImpl = new(); + private readonly PerScreen HostPeerImpl = new PerScreen(); /********* diff --git a/src/SMAPI/Framework/Serialization/KeybindConverter.cs b/src/SMAPI/Framework/Serialization/KeybindConverter.cs index 7c5db3ad..93a274a8 100644 --- a/src/SMAPI/Framework/Serialization/KeybindConverter.cs +++ b/src/SMAPI/Framework/Serialization/KeybindConverter.cs @@ -44,7 +44,7 @@ namespace StardewModdingAPI.Framework.Serialization { case JsonToken.Null: return objectType == typeof(Keybind) - ? new Keybind() + ? (object)new Keybind() : new KeybindList(); case JsonToken.String: -- cgit