From 0825deef18c58bf8330ee14b6ba86d318ffefd3f Mon Sep 17 00:00:00 2001 From: AlexejheroYTB Date: Tue, 4 Oct 2022 13:20:32 +0300 Subject: [PATCH 01/22] Localization API --- Reactor/Localization/CustomStringName.cs | 53 ----------- .../Extensions/TranslationExtensions.cs | 49 +++++++++++ Reactor/Localization/LocalizationManager.cs | 69 +++++++++++++++ Reactor/Localization/LocalizationProvider.cs | 63 +++++++++++++ .../Localization/Patches/GetStringPatch.cs | 88 +++++++++++++++++++ .../HardCodedLocalizationProvider.cs | 24 +++++ .../Utilities/CustomStringName.cs | 31 +++++++ Reactor/ReactorPlugin.cs | 3 + Reactor/Utilities/ReactorPriority.cs | 14 +++ 9 files changed, 341 insertions(+), 53 deletions(-) delete mode 100644 Reactor/Localization/CustomStringName.cs create mode 100644 Reactor/Localization/Extensions/TranslationExtensions.cs create mode 100644 Reactor/Localization/LocalizationManager.cs create mode 100644 Reactor/Localization/LocalizationProvider.cs create mode 100644 Reactor/Localization/Patches/GetStringPatch.cs create mode 100644 Reactor/Localization/Providers/HardCodedLocalizationProvider.cs create mode 100644 Reactor/Localization/Utilities/CustomStringName.cs create mode 100644 Reactor/Utilities/ReactorPriority.cs diff --git a/Reactor/Localization/CustomStringName.cs b/Reactor/Localization/CustomStringName.cs deleted file mode 100644 index 404f5f5..0000000 --- a/Reactor/Localization/CustomStringName.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using HarmonyLib; -using Il2CppInterop.Runtime.InteropTypes.Arrays; - -namespace Reactor.Localization; - -public class CustomStringName -{ - private static int _lastId = -1; - - private static readonly List _list = new(); - - public static IReadOnlyList List => _list.AsReadOnly(); - - public static CustomStringName Register(string value) - { - var customStringName = new CustomStringName(_lastId--, value); - _list.Add(customStringName); - - return customStringName; - } - - public int Id { get; } - - public string Value { get; } - - private CustomStringName(int id, string value) - { - Id = id; - Value = value; - } - - public static implicit operator StringNames(CustomStringName name) => (StringNames) name.Id; - public static explicit operator CustomStringName?(StringNames name) => List.SingleOrDefault(x => x.Id == (int) name); - - [HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetString), typeof(StringNames), typeof(Il2CppReferenceArray))] - private static class GetStringPatch - { - public static bool Prefix(StringNames id, Il2CppReferenceArray parts, ref string __result) - { - var customStringName = (CustomStringName?) id; - - if (customStringName != null) - { - __result = string.Format(customStringName.Value, parts); - return false; - } - - return true; - } - } -} diff --git a/Reactor/Localization/Extensions/TranslationExtensions.cs b/Reactor/Localization/Extensions/TranslationExtensions.cs new file mode 100644 index 0000000..abbb871 --- /dev/null +++ b/Reactor/Localization/Extensions/TranslationExtensions.cs @@ -0,0 +1,49 @@ +using System.Linq; +using Il2CppInterop.Runtime.InteropTypes.Arrays; +using Double = Il2CppSystem.Double; +using Int16 = Il2CppSystem.Int16; +using Int32 = Il2CppSystem.Int32; +using Int64 = Il2CppSystem.Int64; +using Object = Il2CppSystem.Object; +using Single = Il2CppSystem.Single; +using UInt16 = Il2CppSystem.UInt16; +using UInt32 = Il2CppSystem.UInt32; +using UInt64 = Il2CppSystem.UInt64; + +namespace Reactor.Localization.Extensions; + +public static class TranslationExtensions +{ + public readonly struct Il2CppObjectParsable + { + public readonly Object Object; + + public Il2CppObjectParsable(Object obj) => Object = obj; + + public static implicit operator Object(Il2CppObjectParsable parsable) => parsable.Object; + + public static implicit operator Il2CppObjectParsable(short value) => new(new Int16 {m_value = value}.BoxIl2CppObject()); + public static implicit operator Il2CppObjectParsable(int value) => new(new Int32 {m_value = value}.BoxIl2CppObject()); + public static implicit operator Il2CppObjectParsable(long value) => new(new Int64 {m_value = value}.BoxIl2CppObject()); + + public static implicit operator Il2CppObjectParsable(ushort value) => new(new UInt16 {m_value = value}.BoxIl2CppObject()); + public static implicit operator Il2CppObjectParsable(uint value) => new(new UInt32 {m_value = value}.BoxIl2CppObject()); + public static implicit operator Il2CppObjectParsable(ulong value) => new(new UInt64 {m_value = value}.BoxIl2CppObject()); + + public static implicit operator Il2CppObjectParsable(float value) => new(new Single {m_value = value}.BoxIl2CppObject()); + public static implicit operator Il2CppObjectParsable(double value) => new(new Double {m_value = value}.BoxIl2CppObject()); + + public static implicit operator Il2CppObjectParsable(string value) => new(value); + } + + /// + /// Invoking + /// directly will generally cause exceptions, this version makes it easier for the developer to invoke this method without worrying about IL2CPP boxing bs. + /// + /// + /// + /// + /// + public static string GetStringFixed(this TranslationController self, StringNames name, params Il2CppObjectParsable[] args) + => self.GetString(name, new Il2CppReferenceArray(args.Select(o => o.Object).ToArray())); +} diff --git a/Reactor/Localization/LocalizationManager.cs b/Reactor/Localization/LocalizationManager.cs new file mode 100644 index 0000000..3a5b20c --- /dev/null +++ b/Reactor/Localization/LocalizationManager.cs @@ -0,0 +1,69 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Reactor.Localization; + +public static class LocalizationManager +{ + internal static List Providers = new(); + + public static void Register(LocalizationProvider provider) + { + if (!Providers.Contains(provider)) Providers.Add(provider); + } + + public static void Unregister(LocalizationProvider provider) + { + Providers.Remove(provider); + } + + public static void UnregisterAllByType() where T : LocalizationProvider + { + Providers.RemoveAll(x => x is T); + } + + internal static bool TryGetText(StringNames stringName, out string text) + { + foreach (var provider in Providers.OrderByDescending(p => p.Priority)) + { + if (provider.CanHandle(stringName)) + { + text = provider.GetText(stringName); + return true; + } + } + + text = string.Empty; + return false; + } + + internal static bool TryGetStringName(SystemTypes systemType, out StringNames stringName) + { + foreach (var provider in Providers.OrderByDescending(p => p.Priority)) + { + if (provider.CanHandle(systemType)) + { + stringName = provider.GetStringName(systemType); + return true; + } + } + + stringName = StringNames.NoTranslation; + return false; + } + + internal static bool TryGetStringName(TaskTypes taskTypes, out StringNames stringName) + { + foreach (var provider in Providers.OrderByDescending(p => p.Priority)) + { + if (provider.CanHandle(taskTypes)) + { + stringName = provider.GetStringName(taskTypes); + return true; + } + } + + stringName = StringNames.NoTranslation; + return false; + } +} diff --git a/Reactor/Localization/LocalizationProvider.cs b/Reactor/Localization/LocalizationProvider.cs new file mode 100644 index 0000000..403e943 --- /dev/null +++ b/Reactor/Localization/LocalizationProvider.cs @@ -0,0 +1,63 @@ +namespace Reactor.Localization; + +/// +/// The required implementation of a localization provider class +/// +public abstract class LocalizationProvider +{ + /// + /// The priority of this . + /// The higher the priority is, the earlier it will be invoked in relation to other providers. + ///
+ /// You can use the class for this value if you want to make this easier. + ///
+ public virtual int Priority => 0; + + /// + /// Whether or not this can handle this + ///
+ /// Returning true here will subsequently call with the same + ///
+ /// + /// + public virtual bool CanHandle(StringNames stringName) => false; + + /// + /// Returns the localized text for the given + /// + /// + /// + public virtual string GetText(StringNames stringName) => "STRMISS"; + + /// + /// Whether or not this can handle this + ///
+ /// Returning true here will subsequently call with the same + ///
+ /// + /// + public virtual bool CanHandle(SystemTypes systemType) => false; + + /// + /// Returns the matching for the given + /// + /// + /// + public virtual StringNames GetStringName(SystemTypes systemType) => StringNames.ExitButton; + + /// + /// Whether or not this can handle this + ///
+ /// Returning true here will subsequently call with the same + ///
+ /// + /// + public virtual bool CanHandle(TaskTypes taskType) => false; + + /// + /// Returns the matching for the given + /// + /// + /// + public virtual StringNames GetStringName(TaskTypes taskType) => StringNames.ExitButton; +} diff --git a/Reactor/Localization/Patches/GetStringPatch.cs b/Reactor/Localization/Patches/GetStringPatch.cs new file mode 100644 index 0000000..5491b5a --- /dev/null +++ b/Reactor/Localization/Patches/GetStringPatch.cs @@ -0,0 +1,88 @@ +using HarmonyLib; +using Il2CppInterop.Runtime.InteropTypes.Arrays; +using Reactor.Localization.Extensions; + +namespace Reactor.Localization.Patches; + +[HarmonyPatch] +internal static class GetStringPatch +{ + [HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetString), + typeof(StringNames), typeof(Il2CppReferenceArray))] + [HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetStringWithDefault))] + [HarmonyPrefix] + public static bool StringNamesPatch(StringNames id, Il2CppReferenceArray parts, ref string __result) + { + if (LocalizationManager.TryGetText(id, out var text)) + { + __result = string.Format(text, parts); + return false; + } + + return true; + } + + [HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetString), typeof(SystemTypes))] + [HarmonyPrefix] + public static bool SystemTypesStringPatch(TranslationController __instance, SystemTypes room, ref string __result) + { + if (LocalizationManager.TryGetStringName(room, out var stringName)) + { + if (LocalizationManager.TryGetText(stringName, out var text)) + { + __result = text; + return false; + } + + __result = __instance.GetStringFixed(stringName); + return false; + } + + return true; + } + + [HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetSystemName))] + [HarmonyPrefix] + public static bool SystemTypesStringNamesPatch(SystemTypes room, ref StringNames __result) + { + if (LocalizationManager.TryGetStringName(room, out var stringName)) + { + __result = stringName; + return false; + } + + return true; + } + + [HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetString), typeof(TaskTypes))] + [HarmonyPrefix] + public static bool TaskTypesStringPatch(TranslationController __instance, TaskTypes task, ref string __result) + { + if (LocalizationManager.TryGetStringName(task, out var stringName)) + { + if (LocalizationManager.TryGetText(stringName, out var text)) + { + __result = text; + return false; + } + + __result = __instance.GetStringFixed(stringName); + return false; + } + + return true; + } + + [HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetTaskName))] + [HarmonyPrefix] + public static bool TaskTypesStringNamesPatch(TaskTypes task, ref StringNames __result) + { + if (LocalizationManager.TryGetStringName(task, out var stringName)) + { + __result = stringName; + return false; + } + + return true; + } +} diff --git a/Reactor/Localization/Providers/HardCodedLocalizationProvider.cs b/Reactor/Localization/Providers/HardCodedLocalizationProvider.cs new file mode 100644 index 0000000..2afcdb8 --- /dev/null +++ b/Reactor/Localization/Providers/HardCodedLocalizationProvider.cs @@ -0,0 +1,24 @@ +using System; +using Il2CppSystem.Collections.Generic; +using Reactor.Localization.Utilities; +using Reactor.Utilities; + +namespace Reactor.Localization.Providers; + +public sealed class HardCodedLocalizationProvider : LocalizationProvider +{ + internal static Dictionary Strings = new(); + + public override int Priority => ReactorPriority.Low; + + public override bool CanHandle(StringNames stringName) + { + return Strings.ContainsKey(stringName); + } + + public override string GetText(StringNames stringName) + { + if (!Strings.ContainsKey(stringName)) throw new InvalidOperationException("StringName not found: " + stringName); + return Strings[stringName].Value; + } +} diff --git a/Reactor/Localization/Utilities/CustomStringName.cs b/Reactor/Localization/Utilities/CustomStringName.cs new file mode 100644 index 0000000..a8456e0 --- /dev/null +++ b/Reactor/Localization/Utilities/CustomStringName.cs @@ -0,0 +1,31 @@ +using Reactor.Localization.Providers; + +namespace Reactor.Localization.Utilities; + +public class CustomStringName +{ + private static int _lastId = int.MinValue + 1; + + public int Id { get; } + + public string Value { get; } + + private CustomStringName(int id, string value) + { + Id = id; + Value = value; + } + + public static CustomStringName Register(string value) + { + var id = _lastId++; + var customStringName = new CustomStringName(id, value); + + HardCodedLocalizationProvider.Strings[(StringNames) id] = customStringName; + + return customStringName; + } + + public static implicit operator StringNames(CustomStringName name) => (StringNames) name.Id; + public static implicit operator string(CustomStringName name) => name.Value; +} diff --git a/Reactor/ReactorPlugin.cs b/Reactor/ReactorPlugin.cs index b9f1f0e..f4a3176 100644 --- a/Reactor/ReactorPlugin.cs +++ b/Reactor/ReactorPlugin.cs @@ -7,6 +7,8 @@ using HarmonyLib; using Reactor.Networking; using Il2CppInterop.Runtime.Attributes; +using Reactor.Localization; +using Reactor.Localization.Providers; using Reactor.Networking.Attributes; using Reactor.Networking.Rpc; using Reactor.Patches; @@ -38,6 +40,7 @@ public ReactorPlugin() RegisterCustomRpcAttribute.Initialize(); MessageConverterAttribute.Initialize(); MethodRpcAttribute.Initialize(); + LocalizationManager.Register(new HardCodedLocalizationProvider()); } public override void Load() diff --git a/Reactor/Utilities/ReactorPriority.cs b/Reactor/Utilities/ReactorPriority.cs new file mode 100644 index 0000000..06d8257 --- /dev/null +++ b/Reactor/Utilities/ReactorPriority.cs @@ -0,0 +1,14 @@ +namespace Reactor.Utilities; + +public static class ReactorPriority +{ + public const int Last = -800; + public const int VeryLow = -600; + public const int Low = -400; + public const int LowerThanNormal = -200; + public const int Normal = 0; + public const int HigherThanNormal = 200; + public const int High = 400; + public const int VeryHigh = 600; + public const int First = 800; +} From bc43a4ab6afdc01c68b02d6d5826430b6707cfcc Mon Sep 17 00:00:00 2001 From: AlexejheroYTB Date: Mon, 10 Oct 2022 18:04:20 +0300 Subject: [PATCH 02/22] Fix CustomStringName --- Reactor/Localization/CustomStringName.cs | 82 ------------------- .../Utilities/CustomStringName.cs | 31 ++++++- 2 files changed, 28 insertions(+), 85 deletions(-) delete mode 100644 Reactor/Localization/CustomStringName.cs diff --git a/Reactor/Localization/CustomStringName.cs b/Reactor/Localization/CustomStringName.cs deleted file mode 100644 index 7034dd4..0000000 --- a/Reactor/Localization/CustomStringName.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using HarmonyLib; -using Il2CppInterop.Runtime.InteropTypes.Arrays; - -namespace Reactor.Localization; - -/// -/// Provides a way to use custom static StringNames. -/// -public class CustomStringName -{ - private static int _lastId = -1; - - private static readonly List _list = new(); - - /// - /// Gets a list of all s. - /// - public static IReadOnlyList List => _list.AsReadOnly(); - - /// - /// Registers a with specified . - /// - /// The value. - /// A . - public static CustomStringName Register(string value) - { - var customStringName = new CustomStringName(_lastId--, value); - _list.Add(customStringName); - - return customStringName; - } - - /// - /// Gets the id. - /// - public int Id { get; } - - /// - /// Gets the value. - /// - public string Value { get; } - - private CustomStringName(int id, string value) - { - Id = id; - Value = value; - } - - /// - /// Defines an implicit conversion of a to a . - /// - /// The . - /// A . - public static implicit operator StringNames(CustomStringName name) => (StringNames) name.Id; - - /// - /// Defines an explicit conversion of a to a . - /// - /// The . - /// A . - public static explicit operator CustomStringName?(StringNames name) => List.SingleOrDefault(x => x.Id == (int) name); - - [HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetString), typeof(StringNames), typeof(Il2CppReferenceArray))] - private static class GetStringPatch - { - public static bool Prefix(StringNames id, Il2CppReferenceArray parts, ref string __result) - { - var customStringName = (CustomStringName?) id; - - if (customStringName != null) - { - __result = string.Format(CultureInfo.InvariantCulture, customStringName.Value, parts); - return false; - } - - return true; - } - } -} diff --git a/Reactor/Localization/Utilities/CustomStringName.cs b/Reactor/Localization/Utilities/CustomStringName.cs index a8456e0..c8f7308 100644 --- a/Reactor/Localization/Utilities/CustomStringName.cs +++ b/Reactor/Localization/Utilities/CustomStringName.cs @@ -2,30 +2,55 @@ namespace Reactor.Localization.Utilities; +/// +/// Provides a way to use custom static StringNames. +/// public class CustomStringName { private static int _lastId = int.MinValue + 1; + /// + /// Gets the id. + /// public int Id { get; } + /// + /// Gets the value. + /// public string Value { get; } - + private CustomStringName(int id, string value) { Id = id; Value = value; } - + + /// + /// Registers a with specified . + /// + /// The value. + /// A . public static CustomStringName Register(string value) { var id = _lastId++; var customStringName = new CustomStringName(id, value); - + HardCodedLocalizationProvider.Strings[(StringNames) id] = customStringName; return customStringName; } + /// + /// Defines an implicit conversion of a to a . + /// + /// The . + /// A . public static implicit operator StringNames(CustomStringName name) => (StringNames) name.Id; + + /// + /// Defines an implicit conversion of a to a . + /// + /// The . + /// A . public static implicit operator string(CustomStringName name) => name.Value; } From 5439f62eb5cd15ce495e545028122b2feedc64ac Mon Sep 17 00:00:00 2001 From: AlexejheroYTB Date: Mon, 10 Oct 2022 18:35:41 +0300 Subject: [PATCH 03/22] Add examples and fix some issues a --- Reactor.Example/ExampleLocalization.cs | 6 ++++++ Reactor.Example/ExamplePlugin.cs | 9 +++++++++ Reactor/Localization/Patches/GetStringPatch.cs | 9 ++++----- .../Providers/HardCodedLocalizationProvider.cs | 2 +- 4 files changed, 20 insertions(+), 6 deletions(-) create mode 100644 Reactor.Example/ExampleLocalization.cs diff --git a/Reactor.Example/ExampleLocalization.cs b/Reactor.Example/ExampleLocalization.cs new file mode 100644 index 0000000..a01157e --- /dev/null +++ b/Reactor.Example/ExampleLocalization.cs @@ -0,0 +1,6 @@ +namespace Reactor.Example; + +public class ExampleLocalization +{ + +} diff --git a/Reactor.Example/ExamplePlugin.cs b/Reactor.Example/ExamplePlugin.cs index fc1922d..031bd63 100644 --- a/Reactor.Example/ExamplePlugin.cs +++ b/Reactor.Example/ExamplePlugin.cs @@ -2,6 +2,7 @@ using BepInEx; using BepInEx.Unity.IL2CPP; using Il2CppInterop.Runtime.Attributes; +using Reactor.Localization.Utilities; using Reactor.Networking; using Reactor.Networking.Attributes; using Reactor.Networking.Rpc; @@ -19,9 +20,12 @@ namespace Reactor.Example; [ReactorModFlags(ModFlags.RequireOnAllClients)] public partial class ExamplePlugin : BasePlugin { + private static CustomStringName? _helloStringName; + public override void Load() { this.AddComponent(); + _helloStringName = CustomStringName.Register("Hello!"); } [RegisterInIl2Cpp] @@ -54,6 +58,11 @@ public ExampleComponent(IntPtr ptr) : base(ptr) { RpcSay(PlayerControl.LocalPlayer, "Hello from method rpc", Random.value, PlayerControl.LocalPlayer); } + + if (GUILayout.Button("Debug.Log CustomStringName")) + { + Logger.Info(TranslationController.Instance.GetString(_helloStringName)); + } } }) { diff --git a/Reactor/Localization/Patches/GetStringPatch.cs b/Reactor/Localization/Patches/GetStringPatch.cs index 5491b5a..41092f2 100644 --- a/Reactor/Localization/Patches/GetStringPatch.cs +++ b/Reactor/Localization/Patches/GetStringPatch.cs @@ -7,9 +7,8 @@ namespace Reactor.Localization.Patches; [HarmonyPatch] internal static class GetStringPatch { - [HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetString), - typeof(StringNames), typeof(Il2CppReferenceArray))] - [HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetStringWithDefault))] + [HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetString), typeof(StringNames), typeof(Il2CppReferenceArray))] + [HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetStringWithDefault), typeof(StringNames), typeof(string), typeof(Il2CppReferenceArray))] [HarmonyPrefix] public static bool StringNamesPatch(StringNames id, Il2CppReferenceArray parts, ref string __result) { @@ -53,7 +52,7 @@ public static bool SystemTypesStringNamesPatch(SystemTypes room, ref StringNames return true; } - + [HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetString), typeof(TaskTypes))] [HarmonyPrefix] public static bool TaskTypesStringPatch(TranslationController __instance, TaskTypes task, ref string __result) @@ -72,7 +71,7 @@ public static bool TaskTypesStringPatch(TranslationController __instance, TaskTy return true; } - + [HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetTaskName))] [HarmonyPrefix] public static bool TaskTypesStringNamesPatch(TaskTypes task, ref StringNames __result) diff --git a/Reactor/Localization/Providers/HardCodedLocalizationProvider.cs b/Reactor/Localization/Providers/HardCodedLocalizationProvider.cs index 2afcdb8..620bf55 100644 --- a/Reactor/Localization/Providers/HardCodedLocalizationProvider.cs +++ b/Reactor/Localization/Providers/HardCodedLocalizationProvider.cs @@ -1,5 +1,5 @@ using System; -using Il2CppSystem.Collections.Generic; +using System.Collections.Generic; using Reactor.Localization.Utilities; using Reactor.Utilities; From 1cdce8b5413d0d577ce85ad725e0d893a9e8acb1 Mon Sep 17 00:00:00 2001 From: AlexejheroYTB Date: Mon, 10 Oct 2022 18:51:07 +0300 Subject: [PATCH 04/22] Add SupportLangs to GetText callback --- Reactor.Example/ExampleLocalization.cs | 6 ----- .../ExampleLocalizationProvider.cs | 23 +++++++++++++++++++ Reactor.Example/ExamplePlugin.cs | 12 ++++++++-- Reactor/Localization/LocalizationManager.cs | 4 ++-- Reactor/Localization/LocalizationProvider.cs | 2 +- .../Localization/Patches/GetStringPatch.cs | 14 +++++++---- .../HardCodedLocalizationProvider.cs | 2 +- 7 files changed, 47 insertions(+), 16 deletions(-) delete mode 100644 Reactor.Example/ExampleLocalization.cs create mode 100644 Reactor.Example/ExampleLocalizationProvider.cs diff --git a/Reactor.Example/ExampleLocalization.cs b/Reactor.Example/ExampleLocalization.cs deleted file mode 100644 index a01157e..0000000 --- a/Reactor.Example/ExampleLocalization.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Reactor.Example; - -public class ExampleLocalization -{ - -} diff --git a/Reactor.Example/ExampleLocalizationProvider.cs b/Reactor.Example/ExampleLocalizationProvider.cs new file mode 100644 index 0000000..cfd1c35 --- /dev/null +++ b/Reactor.Example/ExampleLocalizationProvider.cs @@ -0,0 +1,23 @@ +using Reactor.Localization; + +namespace Reactor.Example; + +public class ExampleLocalizationProvider : LocalizationProvider +{ + public override bool CanHandle(StringNames stringName) + { + return stringName == (StringNames) 1337; + } + + public override string GetText(StringNames stringName, SupportedLangs language) + { + switch (language) + { + case SupportedLangs.English: + return "Cringe English"; + + default: + return "Based " + language; + } + } +} diff --git a/Reactor.Example/ExamplePlugin.cs b/Reactor.Example/ExamplePlugin.cs index 031bd63..cdf7779 100644 --- a/Reactor.Example/ExamplePlugin.cs +++ b/Reactor.Example/ExamplePlugin.cs @@ -2,6 +2,7 @@ using BepInEx; using BepInEx.Unity.IL2CPP; using Il2CppInterop.Runtime.Attributes; +using Reactor.Localization; using Reactor.Localization.Utilities; using Reactor.Networking; using Reactor.Networking.Attributes; @@ -25,7 +26,9 @@ public partial class ExamplePlugin : BasePlugin public override void Load() { this.AddComponent(); + _helloStringName = CustomStringName.Register("Hello!"); + LocalizationManager.Register(new ExampleLocalizationProvider()); } [RegisterInIl2Cpp] @@ -59,9 +62,14 @@ public ExampleComponent(IntPtr ptr) : base(ptr) RpcSay(PlayerControl.LocalPlayer, "Hello from method rpc", Random.value, PlayerControl.LocalPlayer); } - if (GUILayout.Button("Debug.Log CustomStringName")) + if (GUILayout.Button("Log CustomStringName")) + { + Logger.Info(TranslationController.Instance.GetString(_helloStringName!)); + } + + if (GUILayout.Button("Log localized string")) { - Logger.Info(TranslationController.Instance.GetString(_helloStringName)); + Logger.Info(TranslationController.Instance.GetString((StringNames) 1337)); } } }) diff --git a/Reactor/Localization/LocalizationManager.cs b/Reactor/Localization/LocalizationManager.cs index 3a5b20c..2fc76d9 100644 --- a/Reactor/Localization/LocalizationManager.cs +++ b/Reactor/Localization/LocalizationManager.cs @@ -22,13 +22,13 @@ public static void UnregisterAllByType() where T : LocalizationProvider Providers.RemoveAll(x => x is T); } - internal static bool TryGetText(StringNames stringName, out string text) + internal static bool TryGetText(StringNames stringName, SupportedLangs language, out string text) { foreach (var provider in Providers.OrderByDescending(p => p.Priority)) { if (provider.CanHandle(stringName)) { - text = provider.GetText(stringName); + text = provider.GetText(stringName, language); return true; } } diff --git a/Reactor/Localization/LocalizationProvider.cs b/Reactor/Localization/LocalizationProvider.cs index 403e943..3d5cd43 100644 --- a/Reactor/Localization/LocalizationProvider.cs +++ b/Reactor/Localization/LocalizationProvider.cs @@ -27,7 +27,7 @@ public abstract class LocalizationProvider /// /// /// - public virtual string GetText(StringNames stringName) => "STRMISS"; + public virtual string GetText(StringNames stringName, SupportedLangs language) => "STRMISS"; /// /// Whether or not this can handle this diff --git a/Reactor/Localization/Patches/GetStringPatch.cs b/Reactor/Localization/Patches/GetStringPatch.cs index 41092f2..1e0f369 100644 --- a/Reactor/Localization/Patches/GetStringPatch.cs +++ b/Reactor/Localization/Patches/GetStringPatch.cs @@ -10,9 +10,11 @@ internal static class GetStringPatch [HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetString), typeof(StringNames), typeof(Il2CppReferenceArray))] [HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetStringWithDefault), typeof(StringNames), typeof(string), typeof(Il2CppReferenceArray))] [HarmonyPrefix] - public static bool StringNamesPatch(StringNames id, Il2CppReferenceArray parts, ref string __result) + public static bool StringNamesPatch(TranslationController __instance, StringNames id, Il2CppReferenceArray parts, ref string __result) { - if (LocalizationManager.TryGetText(id, out var text)) + var currentLanguage = __instance.currentLanguage.languageID; + + if (LocalizationManager.TryGetText(id, currentLanguage, out var text)) { __result = string.Format(text, parts); return false; @@ -25,9 +27,11 @@ public static bool StringNamesPatch(StringNames id, Il2CppReferenceArray Date: Mon, 10 Oct 2022 18:54:03 +0300 Subject: [PATCH 05/22] Move Il2CppBoxedPrimitive into extensions --- .../Extensions/TranslationExtensions.cs | 33 ++----------------- .../Extensions/Il2CppInteropExtensions.cs | 31 +++++++++++++++++ 2 files changed, 33 insertions(+), 31 deletions(-) diff --git a/Reactor/Localization/Extensions/TranslationExtensions.cs b/Reactor/Localization/Extensions/TranslationExtensions.cs index abbb871..dcd6275 100644 --- a/Reactor/Localization/Extensions/TranslationExtensions.cs +++ b/Reactor/Localization/Extensions/TranslationExtensions.cs @@ -1,41 +1,12 @@ using System.Linq; using Il2CppInterop.Runtime.InteropTypes.Arrays; -using Double = Il2CppSystem.Double; -using Int16 = Il2CppSystem.Int16; -using Int32 = Il2CppSystem.Int32; -using Int64 = Il2CppSystem.Int64; +using Reactor.Utilities.Extensions; using Object = Il2CppSystem.Object; -using Single = Il2CppSystem.Single; -using UInt16 = Il2CppSystem.UInt16; -using UInt32 = Il2CppSystem.UInt32; -using UInt64 = Il2CppSystem.UInt64; namespace Reactor.Localization.Extensions; public static class TranslationExtensions { - public readonly struct Il2CppObjectParsable - { - public readonly Object Object; - - public Il2CppObjectParsable(Object obj) => Object = obj; - - public static implicit operator Object(Il2CppObjectParsable parsable) => parsable.Object; - - public static implicit operator Il2CppObjectParsable(short value) => new(new Int16 {m_value = value}.BoxIl2CppObject()); - public static implicit operator Il2CppObjectParsable(int value) => new(new Int32 {m_value = value}.BoxIl2CppObject()); - public static implicit operator Il2CppObjectParsable(long value) => new(new Int64 {m_value = value}.BoxIl2CppObject()); - - public static implicit operator Il2CppObjectParsable(ushort value) => new(new UInt16 {m_value = value}.BoxIl2CppObject()); - public static implicit operator Il2CppObjectParsable(uint value) => new(new UInt32 {m_value = value}.BoxIl2CppObject()); - public static implicit operator Il2CppObjectParsable(ulong value) => new(new UInt64 {m_value = value}.BoxIl2CppObject()); - - public static implicit operator Il2CppObjectParsable(float value) => new(new Single {m_value = value}.BoxIl2CppObject()); - public static implicit operator Il2CppObjectParsable(double value) => new(new Double {m_value = value}.BoxIl2CppObject()); - - public static implicit operator Il2CppObjectParsable(string value) => new(value); - } - /// /// Invoking /// directly will generally cause exceptions, this version makes it easier for the developer to invoke this method without worrying about IL2CPP boxing bs. @@ -44,6 +15,6 @@ public readonly struct Il2CppObjectParsable /// /// /// - public static string GetStringFixed(this TranslationController self, StringNames name, params Il2CppObjectParsable[] args) + public static string GetStringFixed(this TranslationController self, StringNames name, params Il2CppInteropExtensions.Il2CppBoxedPrimitive[] args) => self.GetString(name, new Il2CppReferenceArray(args.Select(o => o.Object).ToArray())); } diff --git a/Reactor/Utilities/Extensions/Il2CppInteropExtensions.cs b/Reactor/Utilities/Extensions/Il2CppInteropExtensions.cs index 41f58ed..9c9b532 100644 --- a/Reactor/Utilities/Extensions/Il2CppInteropExtensions.cs +++ b/Reactor/Utilities/Extensions/Il2CppInteropExtensions.cs @@ -1,5 +1,14 @@ using System; using Il2CppInterop.Runtime.InteropTypes.Arrays; +using Double = Il2CppSystem.Double; +using Int16 = Il2CppSystem.Int16; +using Int32 = Il2CppSystem.Int32; +using Int64 = Il2CppSystem.Int64; +using Object = Il2CppSystem.Object; +using Single = Il2CppSystem.Single; +using UInt16 = Il2CppSystem.UInt16; +using UInt32 = Il2CppSystem.UInt32; +using UInt64 = Il2CppSystem.UInt64; namespace Reactor.Utilities.Extensions; @@ -8,6 +17,28 @@ namespace Reactor.Utilities.Extensions; /// public static class Il2CppInteropExtensions { + public readonly struct Il2CppBoxedPrimitive + { + public readonly Object Object; + + public Il2CppBoxedPrimitive(Object obj) => Object = obj; + + public static implicit operator Object(Il2CppBoxedPrimitive parsable) => parsable.Object; + + public static implicit operator Il2CppBoxedPrimitive(short value) => new(new Int16 { m_value = value }.BoxIl2CppObject()); + public static implicit operator Il2CppBoxedPrimitive(int value) => new(new Int32 { m_value = value }.BoxIl2CppObject()); + public static implicit operator Il2CppBoxedPrimitive(long value) => new(new Int64 { m_value = value }.BoxIl2CppObject()); + + public static implicit operator Il2CppBoxedPrimitive(ushort value) => new(new UInt16 { m_value = value }.BoxIl2CppObject()); + public static implicit operator Il2CppBoxedPrimitive(uint value) => new(new UInt32 { m_value = value }.BoxIl2CppObject()); + public static implicit operator Il2CppBoxedPrimitive(ulong value) => new(new UInt64 { m_value = value }.BoxIl2CppObject()); + + public static implicit operator Il2CppBoxedPrimitive(float value) => new(new Single { m_value = value }.BoxIl2CppObject()); + public static implicit operator Il2CppBoxedPrimitive(double value) => new(new Double { m_value = value }.BoxIl2CppObject()); + + public static implicit operator Il2CppBoxedPrimitive(string value) => new(value); + } + /// /// Creates a span over a . /// From 645b396920c9417eb5799343e427237822618dae Mon Sep 17 00:00:00 2001 From: AlexejheroYTB Date: Mon, 10 Oct 2022 19:31:57 +0300 Subject: [PATCH 06/22] Add Xml docs and fix some other warnings --- Reactor.Example/ExamplePlugin.cs | 2 +- .../Extensions/TranslationExtensions.cs | 11 ++-- Reactor/Localization/LocalizationManager.cs | 39 +++++++---- Reactor/Localization/LocalizationProvider.cs | 47 +++++++------- .../Localization/Patches/GetStringPatch.cs | 3 + .../HardCodedLocalizationProvider.cs | 10 ++- Reactor/ReactorPlugin.cs | 2 +- .../Extensions/Il2CppInteropExtensions.cs | 65 ++++++++++++++++++- Reactor/Utilities/ReactorPriority.cs | 38 +++++++++++ 9 files changed, 172 insertions(+), 45 deletions(-) diff --git a/Reactor.Example/ExamplePlugin.cs b/Reactor.Example/ExamplePlugin.cs index cdf7779..1e95b30 100644 --- a/Reactor.Example/ExamplePlugin.cs +++ b/Reactor.Example/ExamplePlugin.cs @@ -28,7 +28,7 @@ public override void Load() this.AddComponent(); _helloStringName = CustomStringName.Register("Hello!"); - LocalizationManager.Register(new ExampleLocalizationProvider()); + LocalizationManager.RegisterProvider(new ExampleLocalizationProvider()); } [RegisterInIl2Cpp] diff --git a/Reactor/Localization/Extensions/TranslationExtensions.cs b/Reactor/Localization/Extensions/TranslationExtensions.cs index dcd6275..948e92e 100644 --- a/Reactor/Localization/Extensions/TranslationExtensions.cs +++ b/Reactor/Localization/Extensions/TranslationExtensions.cs @@ -5,16 +5,19 @@ namespace Reactor.Localization.Extensions; +/// +/// Extension methods for . +/// public static class TranslationExtensions { /// /// Invoking /// directly will generally cause exceptions, this version makes it easier for the developer to invoke this method without worrying about IL2CPP boxing bs. /// - /// - /// - /// - /// + /// The instance. + /// The to convert into . + /// Optional arguments to be used in . + /// The representation of the . public static string GetStringFixed(this TranslationController self, StringNames name, params Il2CppInteropExtensions.Il2CppBoxedPrimitive[] args) => self.GetString(name, new Il2CppReferenceArray(args.Select(o => o.Object).ToArray())); } diff --git a/Reactor/Localization/LocalizationManager.cs b/Reactor/Localization/LocalizationManager.cs index 2fc76d9..8d4a180 100644 --- a/Reactor/Localization/LocalizationManager.cs +++ b/Reactor/Localization/LocalizationManager.cs @@ -3,28 +3,43 @@ namespace Reactor.Localization; +/// +/// Handles custom localization. +/// public static class LocalizationManager { - internal static List Providers = new(); + private static readonly List _providers = new(); - public static void Register(LocalizationProvider provider) + /// + /// Registers a new to be used for obtaining translations. + /// + /// A instance. + public static void RegisterProvider(LocalizationProvider provider) { - if (!Providers.Contains(provider)) Providers.Add(provider); + if (!_providers.Contains(provider)) _providers.Add(provider); } - public static void Unregister(LocalizationProvider provider) + /// + /// Unregisters a . + /// + /// The to unregister. + public static void UnregisterProvider(LocalizationProvider provider) { - Providers.Remove(provider); + _providers.Remove(provider); } - - public static void UnregisterAllByType() where T : LocalizationProvider + + /// + /// Unregisters all s of the given type. + /// + /// The type of the s to be unregistered. + public static void UnregisterProvidersByType() where T : LocalizationProvider { - Providers.RemoveAll(x => x is T); + _providers.RemoveAll(x => x is T); } internal static bool TryGetText(StringNames stringName, SupportedLangs language, out string text) { - foreach (var provider in Providers.OrderByDescending(p => p.Priority)) + foreach (var provider in _providers.OrderByDescending(p => p.Priority)) { if (provider.CanHandle(stringName)) { @@ -39,7 +54,7 @@ internal static bool TryGetText(StringNames stringName, SupportedLangs language, internal static bool TryGetStringName(SystemTypes systemType, out StringNames stringName) { - foreach (var provider in Providers.OrderByDescending(p => p.Priority)) + foreach (var provider in _providers.OrderByDescending(p => p.Priority)) { if (provider.CanHandle(systemType)) { @@ -51,10 +66,10 @@ internal static bool TryGetStringName(SystemTypes systemType, out StringNames st stringName = StringNames.NoTranslation; return false; } - + internal static bool TryGetStringName(TaskTypes taskTypes, out StringNames stringName) { - foreach (var provider in Providers.OrderByDescending(p => p.Priority)) + foreach (var provider in _providers.OrderByDescending(p => p.Priority)) { if (provider.CanHandle(taskTypes)) { diff --git a/Reactor/Localization/LocalizationProvider.cs b/Reactor/Localization/LocalizationProvider.cs index 3d5cd43..5d27ac9 100644 --- a/Reactor/Localization/LocalizationProvider.cs +++ b/Reactor/Localization/LocalizationProvider.cs @@ -1,12 +1,12 @@ namespace Reactor.Localization; /// -/// The required implementation of a localization provider class +/// The required implementation of a localization provider class. /// public abstract class LocalizationProvider { /// - /// The priority of this . + /// Gets the priority of this . /// The higher the priority is, the earlier it will be invoked in relation to other providers. ///
/// You can use the class for this value if you want to make this easier. @@ -16,48 +16,49 @@ public abstract class LocalizationProvider /// /// Whether or not this can handle this ///
- /// Returning true here will subsequently call with the same + /// Returning true here will subsequently call with the same . ///
- /// - /// + /// The to check for. + /// A value indicating whether or not this can handle this . public virtual bool CanHandle(StringNames stringName) => false; /// - /// Returns the localized text for the given + /// Returns the localized text for the given . /// - /// - /// + /// The to localize. + /// The current language Among Us is set to. + /// The representation of the given . public virtual string GetText(StringNames stringName, SupportedLangs language) => "STRMISS"; /// /// Whether or not this can handle this ///
- /// Returning true here will subsequently call with the same + /// Returning true here will subsequently call with the same . ///
- /// - /// + /// The to check for. + /// A value indicating whether or not this can handle this . public virtual bool CanHandle(SystemTypes systemType) => false; - + /// - /// Returns the matching for the given + /// Returns the matching for the given . /// - /// - /// + /// The to convert into . + /// The representation of the given . public virtual StringNames GetStringName(SystemTypes systemType) => StringNames.ExitButton; - + /// /// Whether or not this can handle this ///
- /// Returning true here will subsequently call with the same + /// Returning true here will subsequently call with the same . ///
- /// - /// + /// The to check for. + /// A value indicating whether or not this can handle this . public virtual bool CanHandle(TaskTypes taskType) => false; - + /// - /// Returns the matching for the given + /// Returns the matching for the given . /// - /// - /// + /// The to convert into . + /// The representation of the given . public virtual StringNames GetStringName(TaskTypes taskType) => StringNames.ExitButton; } diff --git a/Reactor/Localization/Patches/GetStringPatch.cs b/Reactor/Localization/Patches/GetStringPatch.cs index 1e0f369..c16d6f4 100644 --- a/Reactor/Localization/Patches/GetStringPatch.cs +++ b/Reactor/Localization/Patches/GetStringPatch.cs @@ -16,7 +16,10 @@ public static bool StringNamesPatch(TranslationController __instance, StringName if (LocalizationManager.TryGetText(id, currentLanguage, out var text)) { +#pragma warning disable CA1305 + // Warning disabled because this is how base-game does it __result = string.Format(text, parts); +#pragma warning restore CA1305 return false; } diff --git a/Reactor/Localization/Providers/HardCodedLocalizationProvider.cs b/Reactor/Localization/Providers/HardCodedLocalizationProvider.cs index fd07bba..1e278c7 100644 --- a/Reactor/Localization/Providers/HardCodedLocalizationProvider.cs +++ b/Reactor/Localization/Providers/HardCodedLocalizationProvider.cs @@ -5,18 +5,24 @@ namespace Reactor.Localization.Providers; +/// +/// Adds localization for strings registered through . +/// public sealed class HardCodedLocalizationProvider : LocalizationProvider { - internal static Dictionary Strings = new(); + internal static readonly Dictionary Strings = new(); + /// public override int Priority => ReactorPriority.Low; + /// public override bool CanHandle(StringNames stringName) { return Strings.ContainsKey(stringName); } - public override string GetText(StringNames stringName, SupportedLangs _) + /// + public override string GetText(StringNames stringName, SupportedLangs language) { if (!Strings.ContainsKey(stringName)) throw new InvalidOperationException("StringName not found: " + stringName); return Strings[stringName].Value; diff --git a/Reactor/ReactorPlugin.cs b/Reactor/ReactorPlugin.cs index ed2412c..77c8323 100644 --- a/Reactor/ReactorPlugin.cs +++ b/Reactor/ReactorPlugin.cs @@ -51,7 +51,7 @@ public ReactorPlugin() RegisterCustomRpcAttribute.Initialize(); MessageConverterAttribute.Initialize(); MethodRpcAttribute.Initialize(); - LocalizationManager.Register(new HardCodedLocalizationProvider()); + LocalizationManager.RegisterProvider(new HardCodedLocalizationProvider()); } /// diff --git a/Reactor/Utilities/Extensions/Il2CppInteropExtensions.cs b/Reactor/Utilities/Extensions/Il2CppInteropExtensions.cs index 9c9b532..ce65ca1 100644 --- a/Reactor/Utilities/Extensions/Il2CppInteropExtensions.cs +++ b/Reactor/Utilities/Extensions/Il2CppInteropExtensions.cs @@ -17,25 +17,86 @@ namespace Reactor.Utilities.Extensions; ///
public static class Il2CppInteropExtensions { + /// + /// Utility class used for calling IL2CPP methods with boxed paramters. + /// public readonly struct Il2CppBoxedPrimitive { - public readonly Object Object; + /// + /// The boxed . + /// + internal readonly Object Object; - public Il2CppBoxedPrimitive(Object obj) => Object = obj; + private Il2CppBoxedPrimitive(Object obj) => Object = obj; + /// + /// Returns the boxed by this . + /// + /// The . + /// The boxed . public static implicit operator Object(Il2CppBoxedPrimitive parsable) => parsable.Object; + /// + /// Creates a new instance of from a . + /// + /// The to box. + /// The instance. public static implicit operator Il2CppBoxedPrimitive(short value) => new(new Int16 { m_value = value }.BoxIl2CppObject()); + + /// + /// Creates a new instance of from an . + /// + /// The to box. + /// The instance. public static implicit operator Il2CppBoxedPrimitive(int value) => new(new Int32 { m_value = value }.BoxIl2CppObject()); + + /// + /// Creates a new instance of from a . + /// + /// The to box. + /// The instance. public static implicit operator Il2CppBoxedPrimitive(long value) => new(new Int64 { m_value = value }.BoxIl2CppObject()); + /// + /// Creates a new instance of from a . + /// + /// The to box. + /// The instance. public static implicit operator Il2CppBoxedPrimitive(ushort value) => new(new UInt16 { m_value = value }.BoxIl2CppObject()); + + /// + /// Creates a new instance of from a . + /// + /// The to box. + /// The instance. public static implicit operator Il2CppBoxedPrimitive(uint value) => new(new UInt32 { m_value = value }.BoxIl2CppObject()); + + /// + /// Creates a new instance of from a . + /// + /// The to box. + /// The instance. public static implicit operator Il2CppBoxedPrimitive(ulong value) => new(new UInt64 { m_value = value }.BoxIl2CppObject()); + /// + /// Creates a new instance of from a . + /// + /// The to box. + /// The instance. public static implicit operator Il2CppBoxedPrimitive(float value) => new(new Single { m_value = value }.BoxIl2CppObject()); + + /// + /// Creates a new instance of from a . + /// + /// The to box. + /// The instance. public static implicit operator Il2CppBoxedPrimitive(double value) => new(new Double { m_value = value }.BoxIl2CppObject()); + /// + /// Creates a new instance of from a . + /// + /// The to box. + /// The instance. public static implicit operator Il2CppBoxedPrimitive(string value) => new(value); } diff --git a/Reactor/Utilities/ReactorPriority.cs b/Reactor/Utilities/ReactorPriority.cs index 06d8257..3c68407 100644 --- a/Reactor/Utilities/ReactorPriority.cs +++ b/Reactor/Utilities/ReactorPriority.cs @@ -1,14 +1,52 @@ namespace Reactor.Utilities; +/// +/// Class containing common priorities to be used in various places across Reactor. +/// public static class ReactorPriority { + /// + /// Lowest priority, will happen last. + /// public const int Last = -800; + + /// + /// Very low priority. + /// public const int VeryLow = -600; + + /// + /// Low priority. + /// public const int Low = -400; + + /// + /// Lower than normal priority. + /// public const int LowerThanNormal = -200; + + /// + /// Normal priority. + /// public const int Normal = 0; + + /// + /// Higher than normal priority. + /// public const int HigherThanNormal = 200; + + /// + /// High priority. + /// public const int High = 400; + + /// + /// Very high priority. + /// public const int VeryHigh = 600; + + /// + /// Highest priority, will happen first. + /// public const int First = 800; } From c70f3f18f18958dbe06475eaf8a8cf26f42af70c Mon Sep 17 00:00:00 2001 From: AlexejheroYTB Date: Mon, 10 Oct 2022 19:42:09 +0300 Subject: [PATCH 07/22] Change CustomStringName to be less cringe --- Reactor.Example/ExamplePlugin.cs | 12 ++--- .../HardCodedLocalizationProvider.cs | 22 ++++++-- .../Utilities/CustomStringName.cs | 51 +++++-------------- Reactor/ReactorPlugin.cs | 5 +- 4 files changed, 42 insertions(+), 48 deletions(-) diff --git a/Reactor.Example/ExamplePlugin.cs b/Reactor.Example/ExamplePlugin.cs index 1e95b30..8477735 100644 --- a/Reactor.Example/ExamplePlugin.cs +++ b/Reactor.Example/ExamplePlugin.cs @@ -21,13 +21,13 @@ namespace Reactor.Example; [ReactorModFlags(ModFlags.RequireOnAllClients)] public partial class ExamplePlugin : BasePlugin { - private static CustomStringName? _helloStringName; + private static StringNames _helloStringName; public override void Load() { this.AddComponent(); - _helloStringName = CustomStringName.Register("Hello!"); + _helloStringName = CustomStringName.CreateAndRegister("Hello!"); LocalizationManager.RegisterProvider(new ExampleLocalizationProvider()); } @@ -45,15 +45,15 @@ public ExampleComponent(IntPtr ptr) : base(ptr) { if (GUILayout.Button("Send ExampleRpc")) { - var name = PlayerControl.LocalPlayer.Data.PlayerName; - Rpc.Instance.Send(new ExampleRpc.Data($"Send: from {name}"), ackCallback: () => + var playerName = PlayerControl.LocalPlayer.Data.PlayerName; + Rpc.Instance.Send(new ExampleRpc.Data($"Send: from {playerName}"), ackCallback: () => { Logger.Info("Got an acknowledgement for example rpc"); }); if (!AmongUsClient.Instance.AmHost) { - Rpc.Instance.SendTo(AmongUsClient.Instance.HostId, new ExampleRpc.Data($"SendTo: from {name} to host")); + Rpc.Instance.SendTo(AmongUsClient.Instance.HostId, new ExampleRpc.Data($"SendTo: from {playerName} to host")); } } @@ -64,7 +64,7 @@ public ExampleComponent(IntPtr ptr) : base(ptr) if (GUILayout.Button("Log CustomStringName")) { - Logger.Info(TranslationController.Instance.GetString(_helloStringName!)); + Logger.Info(TranslationController.Instance.GetString(_helloStringName)); } if (GUILayout.Button("Log localized string")) diff --git a/Reactor/Localization/Providers/HardCodedLocalizationProvider.cs b/Reactor/Localization/Providers/HardCodedLocalizationProvider.cs index 1e278c7..927eeb0 100644 --- a/Reactor/Localization/Providers/HardCodedLocalizationProvider.cs +++ b/Reactor/Localization/Providers/HardCodedLocalizationProvider.cs @@ -1,16 +1,30 @@ using System; using System.Collections.Generic; -using Reactor.Localization.Utilities; using Reactor.Utilities; namespace Reactor.Localization.Providers; /// -/// Adds localization for strings registered through . +/// Utility for adding hard-coded localization. /// public sealed class HardCodedLocalizationProvider : LocalizationProvider { - internal static readonly Dictionary Strings = new(); + internal static readonly Dictionary Strings = new(); + + /// + /// Adds a custom, hard-coded translation for a . + /// + /// The . + /// The text. + public static void RegisterStringName(StringNames stringName, string value) + { + if (Strings.ContainsKey(stringName)) + { + Warning($"Registering StringName {stringName} that already exists"); + } + + Strings[stringName] = value; + } /// public override int Priority => ReactorPriority.Low; @@ -25,6 +39,6 @@ public override bool CanHandle(StringNames stringName) public override string GetText(StringNames stringName, SupportedLangs language) { if (!Strings.ContainsKey(stringName)) throw new InvalidOperationException("StringName not found: " + stringName); - return Strings[stringName].Value; + return Strings[stringName]; } } diff --git a/Reactor/Localization/Utilities/CustomStringName.cs b/Reactor/Localization/Utilities/CustomStringName.cs index c8f7308..e543b02 100644 --- a/Reactor/Localization/Utilities/CustomStringName.cs +++ b/Reactor/Localization/Utilities/CustomStringName.cs @@ -3,54 +3,31 @@ namespace Reactor.Localization.Utilities; /// -/// Provides a way to use custom static StringNames. +/// Provides a way to use custom static . /// -public class CustomStringName +public static class CustomStringName { private static int _lastId = int.MinValue + 1; /// - /// Gets the id. + /// Creates an returns a unique value. /// - public int Id { get; } - - /// - /// Gets the value. - /// - public string Value { get; } - - private CustomStringName(int id, string value) + /// A unique . + public static StringNames Create() { - Id = id; - Value = value; + var id = _lastId++; + return (StringNames) id; } /// - /// Registers a with specified . + /// Creates, registeres and returns a unique value. /// - /// The value. - /// A . - public static CustomStringName Register(string value) + /// The text. + /// A unique . + public static StringNames CreateAndRegister(string text) { - var id = _lastId++; - var customStringName = new CustomStringName(id, value); - - HardCodedLocalizationProvider.Strings[(StringNames) id] = customStringName; - - return customStringName; + var stringName = Create(); + HardCodedLocalizationProvider.RegisterStringName(stringName, text); + return stringName; } - - /// - /// Defines an implicit conversion of a to a . - /// - /// The . - /// A . - public static implicit operator StringNames(CustomStringName name) => (StringNames) name.Id; - - /// - /// Defines an implicit conversion of a to a . - /// - /// The . - /// A . - public static implicit operator string(CustomStringName name) => name.Value; } diff --git a/Reactor/ReactorPlugin.cs b/Reactor/ReactorPlugin.cs index 77c8323..394a759 100644 --- a/Reactor/ReactorPlugin.cs +++ b/Reactor/ReactorPlugin.cs @@ -46,11 +46,14 @@ public ReactorPlugin() { PluginSingleton.Instance = this; PluginSingleton.Initialize(); + RegisterInIl2CppAttribute.Initialize(); - ModList.Initialize(); RegisterCustomRpcAttribute.Initialize(); MessageConverterAttribute.Initialize(); MethodRpcAttribute.Initialize(); + + ModList.Initialize(); + LocalizationManager.RegisterProvider(new HardCodedLocalizationProvider()); } From b0d231e0b877caa960811054ff0414cf3a2158cd Mon Sep 17 00:00:00 2001 From: AlexejheroYTB Date: Mon, 10 Oct 2022 19:46:37 +0300 Subject: [PATCH 08/22] Renamed some methods after 6pak DM a --- Reactor.Example/ExamplePlugin.cs | 2 +- Reactor/Localization/LocalizationManager.cs | 6 +++--- .../Localization/Providers/HardCodedLocalizationProvider.cs | 2 +- Reactor/Localization/Utilities/CustomStringName.cs | 2 +- Reactor/ReactorPlugin.cs | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Reactor.Example/ExamplePlugin.cs b/Reactor.Example/ExamplePlugin.cs index 8477735..4ea5851 100644 --- a/Reactor.Example/ExamplePlugin.cs +++ b/Reactor.Example/ExamplePlugin.cs @@ -28,7 +28,7 @@ public override void Load() this.AddComponent(); _helloStringName = CustomStringName.CreateAndRegister("Hello!"); - LocalizationManager.RegisterProvider(new ExampleLocalizationProvider()); + LocalizationManager.Register(new ExampleLocalizationProvider()); } [RegisterInIl2Cpp] diff --git a/Reactor/Localization/LocalizationManager.cs b/Reactor/Localization/LocalizationManager.cs index 8d4a180..1806c06 100644 --- a/Reactor/Localization/LocalizationManager.cs +++ b/Reactor/Localization/LocalizationManager.cs @@ -14,7 +14,7 @@ public static class LocalizationManager /// Registers a new to be used for obtaining translations. /// /// A instance. - public static void RegisterProvider(LocalizationProvider provider) + public static void Register(LocalizationProvider provider) { if (!_providers.Contains(provider)) _providers.Add(provider); } @@ -23,7 +23,7 @@ public static void RegisterProvider(LocalizationProvider provider) /// Unregisters a . /// /// The to unregister. - public static void UnregisterProvider(LocalizationProvider provider) + public static void Unregister(LocalizationProvider provider) { _providers.Remove(provider); } @@ -32,7 +32,7 @@ public static void UnregisterProvider(LocalizationProvider provider) /// Unregisters all s of the given type. /// /// The type of the s to be unregistered. - public static void UnregisterProvidersByType() where T : LocalizationProvider + public static void UnregisterAllByType() where T : LocalizationProvider { _providers.RemoveAll(x => x is T); } diff --git a/Reactor/Localization/Providers/HardCodedLocalizationProvider.cs b/Reactor/Localization/Providers/HardCodedLocalizationProvider.cs index 927eeb0..2411f1e 100644 --- a/Reactor/Localization/Providers/HardCodedLocalizationProvider.cs +++ b/Reactor/Localization/Providers/HardCodedLocalizationProvider.cs @@ -16,7 +16,7 @@ public sealed class HardCodedLocalizationProvider : LocalizationProvider /// /// The . /// The text. - public static void RegisterStringName(StringNames stringName, string value) + public static void Register(StringNames stringName, string value) { if (Strings.ContainsKey(stringName)) { diff --git a/Reactor/Localization/Utilities/CustomStringName.cs b/Reactor/Localization/Utilities/CustomStringName.cs index e543b02..e41236f 100644 --- a/Reactor/Localization/Utilities/CustomStringName.cs +++ b/Reactor/Localization/Utilities/CustomStringName.cs @@ -27,7 +27,7 @@ public static StringNames Create() public static StringNames CreateAndRegister(string text) { var stringName = Create(); - HardCodedLocalizationProvider.RegisterStringName(stringName, text); + HardCodedLocalizationProvider.Register(stringName, text); return stringName; } } diff --git a/Reactor/ReactorPlugin.cs b/Reactor/ReactorPlugin.cs index 394a759..5a5e1ba 100644 --- a/Reactor/ReactorPlugin.cs +++ b/Reactor/ReactorPlugin.cs @@ -54,7 +54,7 @@ public ReactorPlugin() ModList.Initialize(); - LocalizationManager.RegisterProvider(new HardCodedLocalizationProvider()); + LocalizationManager.Register(new HardCodedLocalizationProvider()); } /// From 45c8e1d6c62156cf1066683d4ea66349bea4fe1d Mon Sep 17 00:00:00 2001 From: AlexejheroYTB Date: Mon, 10 Oct 2022 20:10:32 +0300 Subject: [PATCH 09/22] Easier way of assigning task types and system types with string names --- Reactor/Localization/LocalizationManager.cs | 47 +++++++++++--------- Reactor/Localization/LocalizationProvider.cs | 36 +-------------- 2 files changed, 27 insertions(+), 56 deletions(-) diff --git a/Reactor/Localization/LocalizationManager.cs b/Reactor/Localization/LocalizationManager.cs index 1806c06..3d2f0ba 100644 --- a/Reactor/Localization/LocalizationManager.cs +++ b/Reactor/Localization/LocalizationManager.cs @@ -10,6 +10,9 @@ public static class LocalizationManager { private static readonly List _providers = new(); + internal static readonly Dictionary SystemTypes = new(); + internal static readonly Dictionary TaskTypes = new(); + /// /// Registers a new to be used for obtaining translations. /// @@ -37,48 +40,48 @@ public static void UnregisterAllByType() where T : LocalizationProvider _providers.RemoveAll(x => x is T); } - internal static bool TryGetText(StringNames stringName, SupportedLangs language, out string text) + /// + /// Assigns a to a . + /// + /// The . + /// The . + public static void AssignSystemType(SystemTypes systemType, StringNames stringName) { - foreach (var provider in _providers.OrderByDescending(p => p.Priority)) + if (SystemTypes.ContainsKey(systemType)) { - if (provider.CanHandle(stringName)) - { - text = provider.GetText(stringName, language); - return true; - } + Warning($"Assigning SystemType {stringName} that is already assigned"); } - text = string.Empty; - return false; + SystemTypes[systemType] = stringName; } - internal static bool TryGetStringName(SystemTypes systemType, out StringNames stringName) + /// + /// Assigns a to a . + /// + /// The . + /// The . + public static void AssignTaskType(TaskTypes taskTypes, StringNames stringName) { - foreach (var provider in _providers.OrderByDescending(p => p.Priority)) + if (TaskTypes.ContainsKey(taskTypes)) { - if (provider.CanHandle(systemType)) - { - stringName = provider.GetStringName(systemType); - return true; - } + Warning($"Assigning SystemType {stringName} that is already assigned"); } - stringName = StringNames.NoTranslation; - return false; + TaskTypes[taskTypes] = stringName; } - internal static bool TryGetStringName(TaskTypes taskTypes, out StringNames stringName) + internal static bool TryGetText(StringNames stringName, SupportedLangs language, out string text) { foreach (var provider in _providers.OrderByDescending(p => p.Priority)) { - if (provider.CanHandle(taskTypes)) + if (provider.CanHandle(stringName)) { - stringName = provider.GetStringName(taskTypes); + text = provider.GetText(stringName, language); return true; } } - stringName = StringNames.NoTranslation; + text = string.Empty; return false; } } diff --git a/Reactor/Localization/LocalizationProvider.cs b/Reactor/Localization/LocalizationProvider.cs index 5d27ac9..cd7d900 100644 --- a/Reactor/Localization/LocalizationProvider.cs +++ b/Reactor/Localization/LocalizationProvider.cs @@ -20,7 +20,7 @@ public abstract class LocalizationProvider /// /// The to check for. /// A value indicating whether or not this can handle this . - public virtual bool CanHandle(StringNames stringName) => false; + public abstract bool CanHandle(StringNames stringName); /// /// Returns the localized text for the given . @@ -28,37 +28,5 @@ public abstract class LocalizationProvider /// The to localize. /// The current language Among Us is set to. /// The representation of the given . - public virtual string GetText(StringNames stringName, SupportedLangs language) => "STRMISS"; - - /// - /// Whether or not this can handle this - ///
- /// Returning true here will subsequently call with the same . - ///
- /// The to check for. - /// A value indicating whether or not this can handle this . - public virtual bool CanHandle(SystemTypes systemType) => false; - - /// - /// Returns the matching for the given . - /// - /// The to convert into . - /// The representation of the given . - public virtual StringNames GetStringName(SystemTypes systemType) => StringNames.ExitButton; - - /// - /// Whether or not this can handle this - ///
- /// Returning true here will subsequently call with the same . - ///
- /// The to check for. - /// A value indicating whether or not this can handle this . - public virtual bool CanHandle(TaskTypes taskType) => false; - - /// - /// Returns the matching for the given . - /// - /// The to convert into . - /// The representation of the given . - public virtual StringNames GetStringName(TaskTypes taskType) => StringNames.ExitButton; + public abstract string GetText(StringNames stringName, SupportedLangs language); } From 1abf7d46e2579ffda5bc855187b76b9713487d28 Mon Sep 17 00:00:00 2001 From: AlexejheroYTB Date: Mon, 10 Oct 2022 20:10:34 +0300 Subject: [PATCH 10/22] Revert "Easier way of assigning task types and system types with string names" This reverts commit 45c8e1d6c62156cf1066683d4ea66349bea4fe1d. --- Reactor/Localization/LocalizationManager.cs | 47 +++++++++----------- Reactor/Localization/LocalizationProvider.cs | 36 ++++++++++++++- 2 files changed, 56 insertions(+), 27 deletions(-) diff --git a/Reactor/Localization/LocalizationManager.cs b/Reactor/Localization/LocalizationManager.cs index 3d2f0ba..1806c06 100644 --- a/Reactor/Localization/LocalizationManager.cs +++ b/Reactor/Localization/LocalizationManager.cs @@ -10,9 +10,6 @@ public static class LocalizationManager { private static readonly List _providers = new(); - internal static readonly Dictionary SystemTypes = new(); - internal static readonly Dictionary TaskTypes = new(); - /// /// Registers a new to be used for obtaining translations. /// @@ -40,48 +37,48 @@ public static void UnregisterAllByType() where T : LocalizationProvider _providers.RemoveAll(x => x is T); } - /// - /// Assigns a to a . - /// - /// The . - /// The . - public static void AssignSystemType(SystemTypes systemType, StringNames stringName) + internal static bool TryGetText(StringNames stringName, SupportedLangs language, out string text) { - if (SystemTypes.ContainsKey(systemType)) + foreach (var provider in _providers.OrderByDescending(p => p.Priority)) { - Warning($"Assigning SystemType {stringName} that is already assigned"); + if (provider.CanHandle(stringName)) + { + text = provider.GetText(stringName, language); + return true; + } } - SystemTypes[systemType] = stringName; + text = string.Empty; + return false; } - /// - /// Assigns a to a . - /// - /// The . - /// The . - public static void AssignTaskType(TaskTypes taskTypes, StringNames stringName) + internal static bool TryGetStringName(SystemTypes systemType, out StringNames stringName) { - if (TaskTypes.ContainsKey(taskTypes)) + foreach (var provider in _providers.OrderByDescending(p => p.Priority)) { - Warning($"Assigning SystemType {stringName} that is already assigned"); + if (provider.CanHandle(systemType)) + { + stringName = provider.GetStringName(systemType); + return true; + } } - TaskTypes[taskTypes] = stringName; + stringName = StringNames.NoTranslation; + return false; } - internal static bool TryGetText(StringNames stringName, SupportedLangs language, out string text) + internal static bool TryGetStringName(TaskTypes taskTypes, out StringNames stringName) { foreach (var provider in _providers.OrderByDescending(p => p.Priority)) { - if (provider.CanHandle(stringName)) + if (provider.CanHandle(taskTypes)) { - text = provider.GetText(stringName, language); + stringName = provider.GetStringName(taskTypes); return true; } } - text = string.Empty; + stringName = StringNames.NoTranslation; return false; } } diff --git a/Reactor/Localization/LocalizationProvider.cs b/Reactor/Localization/LocalizationProvider.cs index cd7d900..5d27ac9 100644 --- a/Reactor/Localization/LocalizationProvider.cs +++ b/Reactor/Localization/LocalizationProvider.cs @@ -20,7 +20,7 @@ public abstract class LocalizationProvider ///
/// The to check for. /// A value indicating whether or not this can handle this . - public abstract bool CanHandle(StringNames stringName); + public virtual bool CanHandle(StringNames stringName) => false; /// /// Returns the localized text for the given . @@ -28,5 +28,37 @@ public abstract class LocalizationProvider /// The to localize. /// The current language Among Us is set to. /// The representation of the given . - public abstract string GetText(StringNames stringName, SupportedLangs language); + public virtual string GetText(StringNames stringName, SupportedLangs language) => "STRMISS"; + + /// + /// Whether or not this can handle this + ///
+ /// Returning true here will subsequently call with the same . + ///
+ /// The to check for. + /// A value indicating whether or not this can handle this . + public virtual bool CanHandle(SystemTypes systemType) => false; + + /// + /// Returns the matching for the given . + /// + /// The to convert into . + /// The representation of the given . + public virtual StringNames GetStringName(SystemTypes systemType) => StringNames.ExitButton; + + /// + /// Whether or not this can handle this + ///
+ /// Returning true here will subsequently call with the same . + ///
+ /// The to check for. + /// A value indicating whether or not this can handle this . + public virtual bool CanHandle(TaskTypes taskType) => false; + + /// + /// Returns the matching for the given . + /// + /// The to convert into . + /// The representation of the given . + public virtual StringNames GetStringName(TaskTypes taskType) => StringNames.ExitButton; } From 5f133189ced7cae3c91f70dd0767339e62ece42d Mon Sep 17 00:00:00 2001 From: AlexejheroYTB Date: Mon, 10 Oct 2022 21:19:19 +0300 Subject: [PATCH 11/22] Use TryGet pattern --- .../ExampleLocalizationProvider.cs | 25 ++++---- Reactor/Localization/LocalizationManager.cs | 15 +++-- Reactor/Localization/LocalizationProvider.cs | 62 ++++++++----------- .../HardCodedLocalizationProvider.cs | 20 +++--- Reactor/ReactorPlugin.cs | 4 +- 5 files changed, 58 insertions(+), 68 deletions(-) diff --git a/Reactor.Example/ExampleLocalizationProvider.cs b/Reactor.Example/ExampleLocalizationProvider.cs index cfd1c35..ba50d1f 100644 --- a/Reactor.Example/ExampleLocalizationProvider.cs +++ b/Reactor.Example/ExampleLocalizationProvider.cs @@ -4,20 +4,23 @@ namespace Reactor.Example; public class ExampleLocalizationProvider : LocalizationProvider { - public override bool CanHandle(StringNames stringName) + public override bool TryGetText(StringNames stringName, SupportedLangs language, out string? result) { - return stringName == (StringNames) 1337; - } - - public override string GetText(StringNames stringName, SupportedLangs language) - { - switch (language) + if (stringName == (StringNames) 1337) { - case SupportedLangs.English: - return "Cringe English"; + switch (language) + { + case SupportedLangs.English: + result = "Cringe English"; + return true; - default: - return "Based " + language; + default: + result = "Based " + language; + return true; + } } + + result = null; + return false; } } diff --git a/Reactor/Localization/LocalizationManager.cs b/Reactor/Localization/LocalizationManager.cs index 1806c06..7437340 100644 --- a/Reactor/Localization/LocalizationManager.cs +++ b/Reactor/Localization/LocalizationManager.cs @@ -41,9 +41,8 @@ internal static bool TryGetText(StringNames stringName, SupportedLangs language, { foreach (var provider in _providers.OrderByDescending(p => p.Priority)) { - if (provider.CanHandle(stringName)) + if (provider.TryGetText(stringName, language, out text!)) { - text = provider.GetText(stringName, language); return true; } } @@ -56,14 +55,14 @@ internal static bool TryGetStringName(SystemTypes systemType, out StringNames st { foreach (var provider in _providers.OrderByDescending(p => p.Priority)) { - if (provider.CanHandle(systemType)) + if (provider.TryGetStringName(systemType, out var stringNameNullable)) { - stringName = provider.GetStringName(systemType); + stringName = stringNameNullable!.Value; return true; } } - stringName = StringNames.NoTranslation; + stringName = StringNames.ExitButton; return false; } @@ -71,14 +70,14 @@ internal static bool TryGetStringName(TaskTypes taskTypes, out StringNames strin { foreach (var provider in _providers.OrderByDescending(p => p.Priority)) { - if (provider.CanHandle(taskTypes)) + if (provider.TryGetStringName(taskTypes, out var stringNameNullable)) { - stringName = provider.GetStringName(taskTypes); + stringName = stringNameNullable!.Value; return true; } } - stringName = StringNames.NoTranslation; + stringName = StringNames.ExitButton; return false; } } diff --git a/Reactor/Localization/LocalizationProvider.cs b/Reactor/Localization/LocalizationProvider.cs index 5d27ac9..60ab239 100644 --- a/Reactor/Localization/LocalizationProvider.cs +++ b/Reactor/Localization/LocalizationProvider.cs @@ -13,52 +13,40 @@ public abstract class LocalizationProvider ///
public virtual int Priority => 0; - /// - /// Whether or not this can handle this - ///
- /// Returning true here will subsequently call with the same . - ///
- /// The to check for. - /// A value indicating whether or not this can handle this . - public virtual bool CanHandle(StringNames stringName) => false; - /// /// Returns the localized text for the given . /// /// The to localize. /// The current language Among Us is set to. - /// The representation of the given . - public virtual string GetText(StringNames stringName, SupportedLangs language) => "STRMISS"; - - /// - /// Whether or not this can handle this - ///
- /// Returning true here will subsequently call with the same . - ///
- /// The to check for. - /// A value indicating whether or not this can handle this . - public virtual bool CanHandle(SystemTypes systemType) => false; - - /// - /// Returns the matching for the given . - /// - /// The to convert into . - /// The representation of the given . - public virtual StringNames GetStringName(SystemTypes systemType) => StringNames.ExitButton; + /// The representation of the given . + /// Whether or not this can handle this . + public virtual bool TryGetText(StringNames stringName, SupportedLangs language, out string? result) + { + result = null; + return false; + } /// - /// Whether or not this can handle this - ///
- /// Returning true here will subsequently call with the same . + /// Returns the equivalent for the given . ///
- /// The to check for. - /// A value indicating whether or not this can handle this . - public virtual bool CanHandle(TaskTypes taskType) => false; + /// The value. + /// The representation of the given . + /// Whether or not this can handle this . + public virtual bool TryGetStringName(SystemTypes systemType, out StringNames? result) + { + result = null; + return false; + } /// - /// Returns the matching for the given . + /// Returns the equivalent for the given . /// - /// The to convert into . - /// The representation of the given . - public virtual StringNames GetStringName(TaskTypes taskType) => StringNames.ExitButton; + /// The value. + /// The representation of the given . + /// Whether or not this can handle this . + public virtual bool TryGetStringName(TaskTypes taskType, out StringNames? result) + { + result = null; + return false; + } } diff --git a/Reactor/Localization/Providers/HardCodedLocalizationProvider.cs b/Reactor/Localization/Providers/HardCodedLocalizationProvider.cs index 2411f1e..e3d55c0 100644 --- a/Reactor/Localization/Providers/HardCodedLocalizationProvider.cs +++ b/Reactor/Localization/Providers/HardCodedLocalizationProvider.cs @@ -1,5 +1,5 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using Reactor.Utilities; namespace Reactor.Localization.Providers; @@ -30,15 +30,15 @@ public static void Register(StringNames stringName, string value) public override int Priority => ReactorPriority.Low; /// - public override bool CanHandle(StringNames stringName) + public override bool TryGetText(StringNames stringName, SupportedLangs language, [NotNullWhen(true)] out string? result) { - return Strings.ContainsKey(stringName); - } + if (!Strings.ContainsKey(stringName)) + { + result = null; + return false; + } - /// - public override string GetText(StringNames stringName, SupportedLangs language) - { - if (!Strings.ContainsKey(stringName)) throw new InvalidOperationException("StringName not found: " + stringName); - return Strings[stringName]; + result = Strings[stringName]; + return true; } } diff --git a/Reactor/ReactorPlugin.cs b/Reactor/ReactorPlugin.cs index 5a5e1ba..a007ca9 100644 --- a/Reactor/ReactorPlugin.cs +++ b/Reactor/ReactorPlugin.cs @@ -48,12 +48,12 @@ public ReactorPlugin() PluginSingleton.Initialize(); RegisterInIl2CppAttribute.Initialize(); + ModList.Initialize(); + RegisterCustomRpcAttribute.Initialize(); MessageConverterAttribute.Initialize(); MethodRpcAttribute.Initialize(); - ModList.Initialize(); - LocalizationManager.Register(new HardCodedLocalizationProvider()); } From 94bd33215493bbe1d2ef71edb3697f5957d0eba6 Mon Sep 17 00:00:00 2001 From: AlexejheroYTB Date: Tue, 11 Oct 2022 00:06:29 +0300 Subject: [PATCH 12/22] Fix formatting --- Reactor/Localization/Patches/GetStringPatch.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Reactor/Localization/Patches/GetStringPatch.cs b/Reactor/Localization/Patches/GetStringPatch.cs index c16d6f4..11ececf 100644 --- a/Reactor/Localization/Patches/GetStringPatch.cs +++ b/Reactor/Localization/Patches/GetStringPatch.cs @@ -16,10 +16,7 @@ public static bool StringNamesPatch(TranslationController __instance, StringName if (LocalizationManager.TryGetText(id, currentLanguage, out var text)) { -#pragma warning disable CA1305 - // Warning disabled because this is how base-game does it - __result = string.Format(text, parts); -#pragma warning restore CA1305 + __result = Il2CppSystem.String.Format(text, parts); return false; } From 27785e36ab44b8d4c58c0754f10da6c1beac63b2 Mon Sep 17 00:00:00 2001 From: AlexejheroYTB Date: Tue, 11 Oct 2022 19:44:02 +0300 Subject: [PATCH 13/22] Allow localization providers to format their own strings --- Reactor/Localization/LocalizationManager.cs | 15 ++++++++++++ Reactor/Localization/LocalizationProvider.cs | 23 +++++++++++++++++-- .../Localization/Patches/GetStringPatch.cs | 5 ++-- 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/Reactor/Localization/LocalizationManager.cs b/Reactor/Localization/LocalizationManager.cs index 7437340..9916121 100644 --- a/Reactor/Localization/LocalizationManager.cs +++ b/Reactor/Localization/LocalizationManager.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using Il2CppInterop.Runtime.InteropTypes.Arrays; namespace Reactor.Localization; @@ -37,6 +38,20 @@ public static void UnregisterAllByType() where T : LocalizationProvider _providers.RemoveAll(x => x is T); } + internal static bool TryGetTextFormatted(StringNames stringName, SupportedLangs language, Il2CppReferenceArray parts, out string text) + { + foreach (var provider in _providers.OrderByDescending(p => p.Priority)) + { + if (provider.TryGetTextFormatted(stringName, language, parts, out text!)) + { + return true; + } + } + + text = string.Empty; + return false; + } + internal static bool TryGetText(StringNames stringName, SupportedLangs language, out string text) { foreach (var provider in _providers.OrderByDescending(p => p.Priority)) diff --git a/Reactor/Localization/LocalizationProvider.cs b/Reactor/Localization/LocalizationProvider.cs index 60ab239..6a87d81 100644 --- a/Reactor/Localization/LocalizationProvider.cs +++ b/Reactor/Localization/LocalizationProvider.cs @@ -1,4 +1,7 @@ -namespace Reactor.Localization; +using Il2CppInterop.Runtime.InteropTypes.Arrays; +using Reactor.Utilities; + +namespace Reactor.Localization; /// /// The required implementation of a localization provider class. @@ -9,7 +12,7 @@ public abstract class LocalizationProvider /// Gets the priority of this . /// The higher the priority is, the earlier it will be invoked in relation to other providers. ///
- /// You can use the class for this value if you want to make this easier. + /// You can use the class for this value if you want to make this easier. ///
public virtual int Priority => 0; @@ -26,6 +29,22 @@ public virtual bool TryGetText(StringNames stringName, SupportedLangs language, return false; } + /// + /// Returns the localized text for the given . + /// + /// The to localize. + /// The current language Among Us is set to. + /// The arguments used for formatting. + /// The representation of the given . + /// Whether or not this can handle this . + public virtual bool TryGetTextFormatted(StringNames stringName, SupportedLangs language, Il2CppReferenceArray parts, out string? result) + { + if (!TryGetText(stringName, language, out result)) return false; + + result = Il2CppSystem.String.Format(result, parts); + return true; + } + /// /// Returns the equivalent for the given . /// diff --git a/Reactor/Localization/Patches/GetStringPatch.cs b/Reactor/Localization/Patches/GetStringPatch.cs index 11ececf..d7421a3 100644 --- a/Reactor/Localization/Patches/GetStringPatch.cs +++ b/Reactor/Localization/Patches/GetStringPatch.cs @@ -10,13 +10,12 @@ internal static class GetStringPatch [HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetString), typeof(StringNames), typeof(Il2CppReferenceArray))] [HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetStringWithDefault), typeof(StringNames), typeof(string), typeof(Il2CppReferenceArray))] [HarmonyPrefix] - public static bool StringNamesPatch(TranslationController __instance, StringNames id, Il2CppReferenceArray parts, ref string __result) + public static bool StringNamesPatch(TranslationController __instance, StringNames id, Il2CppReferenceArray parts, out string __result) { var currentLanguage = __instance.currentLanguage.languageID; - if (LocalizationManager.TryGetText(id, currentLanguage, out var text)) + if (LocalizationManager.TryGetTextFormatted(id, currentLanguage, parts, out __result)) { - __result = Il2CppSystem.String.Format(text, parts); return false; } From a0b7aa2c30bee9a3d9ea55ea6f77ae1ac34a5daa Mon Sep 17 00:00:00 2001 From: AlexejheroYTB Date: Wed, 12 Oct 2022 10:34:56 +0300 Subject: [PATCH 14/22] Add on language changed event --- Reactor/Localization/LocalizationManager.cs | 8 +++++++ Reactor/Localization/LocalizationProvider.cs | 8 +++++++ .../Patches/LanguageChangedPatch.cs | 22 +++++++++++++++++++ 3 files changed, 38 insertions(+) create mode 100644 Reactor/Localization/Patches/LanguageChangedPatch.cs diff --git a/Reactor/Localization/LocalizationManager.cs b/Reactor/Localization/LocalizationManager.cs index 9916121..6e3585a 100644 --- a/Reactor/Localization/LocalizationManager.cs +++ b/Reactor/Localization/LocalizationManager.cs @@ -95,4 +95,12 @@ internal static bool TryGetStringName(TaskTypes taskTypes, out StringNames strin stringName = StringNames.ExitButton; return false; } + + internal static void OnLanguageChanged(SupportedLangs newLanguage) + { + foreach (var provider in _providers.OrderByDescending(p => p.Priority)) + { + provider.OnLanguageChanged(newLanguage); + } + } } diff --git a/Reactor/Localization/LocalizationProvider.cs b/Reactor/Localization/LocalizationProvider.cs index 6a87d81..3e09bd6 100644 --- a/Reactor/Localization/LocalizationProvider.cs +++ b/Reactor/Localization/LocalizationProvider.cs @@ -68,4 +68,12 @@ public virtual bool TryGetStringName(TaskTypes taskType, out StringNames? result result = null; return false; } + + /// + /// This method is called when the Among Us language is changed by the user. + /// + /// The new language that Among Us has been set to. + public virtual void OnLanguageChanged(SupportedLangs newLanguage) + { + } } diff --git a/Reactor/Localization/Patches/LanguageChangedPatch.cs b/Reactor/Localization/Patches/LanguageChangedPatch.cs new file mode 100644 index 0000000..53fb806 --- /dev/null +++ b/Reactor/Localization/Patches/LanguageChangedPatch.cs @@ -0,0 +1,22 @@ +using HarmonyLib; + +namespace Reactor.Localization.Patches; + +[HarmonyPatch] +internal static class LanguageChangedPatch +{ + [HarmonyPatch(typeof(TranslationController), nameof(TranslationController.Initialize))] + [HarmonyPostfix] + public static void Initialize(TranslationController __instance) + { + if (TranslationController.Instance.GetInstanceID() == __instance.GetInstanceID()) + LocalizationManager.OnLanguageChanged(__instance.currentLanguage.languageID); + } + + [HarmonyPatch(typeof(TranslationController), nameof(TranslationController.SetLanguage))] + [HarmonyPostfix] + public static void SetLanguage(TranslationController __instance) + { + LocalizationManager.OnLanguageChanged(__instance.currentLanguage.languageID); + } +} From 83fb1089105971c1ee33e1b4cc8737b197d76aca Mon Sep 17 00:00:00 2001 From: AlexejheroYTB Date: Thu, 13 Oct 2022 09:30:41 +0300 Subject: [PATCH 15/22] Store language as property instead of passing it as a parameter --- Directory.Build.props | 2 +- .../ExampleLocalizationProvider.cs | 6 +++--- Reactor.sln | 2 ++ Reactor/Localization/LocalizationManager.cs | 10 ++++----- Reactor/Localization/LocalizationProvider.cs | 21 ++++++++++++++----- .../Localization/Patches/GetStringPatch.cs | 14 ++++--------- .../HardCodedLocalizationProvider.cs | 2 +- .../Extensions/Il2CppInteropExtensions.cs | 2 +- 8 files changed, 33 insertions(+), 26 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 3052ee6..3ecaf53 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -31,7 +31,7 @@ - + $(MSBuildThisFileDirectory)\stylecop.ruleset diff --git a/Reactor.Example/ExampleLocalizationProvider.cs b/Reactor.Example/ExampleLocalizationProvider.cs index ba50d1f..90c8418 100644 --- a/Reactor.Example/ExampleLocalizationProvider.cs +++ b/Reactor.Example/ExampleLocalizationProvider.cs @@ -4,18 +4,18 @@ namespace Reactor.Example; public class ExampleLocalizationProvider : LocalizationProvider { - public override bool TryGetText(StringNames stringName, SupportedLangs language, out string? result) + public override bool TryGetText(StringNames stringName, out string? result) { if (stringName == (StringNames) 1337) { - switch (language) + switch (CurrentLanguage) { case SupportedLangs.English: result = "Cringe English"; return true; default: - result = "Based " + language; + result = "Based " + CurrentLanguage; return true; } } diff --git a/Reactor.sln b/Reactor.sln index 11fdc70..ba2a0bc 100644 --- a/Reactor.sln +++ b/Reactor.sln @@ -12,6 +12,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Files", "Solution AmongUs.props = AmongUs.props Directory.Build.props = Directory.Build.props nuget.config = nuget.config + stylecop.json = stylecop.json + stylecop.ruleset = stylecop.ruleset EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Reactor.Networking.Shared", "Reactor.Networking.Shared\Reactor.Networking.Shared.csproj", "{1E68CA20-22EB-4E57-B525-81970BE6363D}" diff --git a/Reactor/Localization/LocalizationManager.cs b/Reactor/Localization/LocalizationManager.cs index 6e3585a..51d5fa8 100644 --- a/Reactor/Localization/LocalizationManager.cs +++ b/Reactor/Localization/LocalizationManager.cs @@ -38,11 +38,11 @@ public static void UnregisterAllByType() where T : LocalizationProvider _providers.RemoveAll(x => x is T); } - internal static bool TryGetTextFormatted(StringNames stringName, SupportedLangs language, Il2CppReferenceArray parts, out string text) + internal static bool TryGetTextFormatted(StringNames stringName, Il2CppReferenceArray parts, out string text) { foreach (var provider in _providers.OrderByDescending(p => p.Priority)) { - if (provider.TryGetTextFormatted(stringName, language, parts, out text!)) + if (provider.TryGetTextFormatted(stringName, parts, out text!)) { return true; } @@ -52,11 +52,11 @@ internal static bool TryGetTextFormatted(StringNames stringName, SupportedLangs return false; } - internal static bool TryGetText(StringNames stringName, SupportedLangs language, out string text) + internal static bool TryGetText(StringNames stringName, out string text) { foreach (var provider in _providers.OrderByDescending(p => p.Priority)) { - if (provider.TryGetText(stringName, language, out text!)) + if (provider.TryGetText(stringName, out text!)) { return true; } @@ -100,7 +100,7 @@ internal static void OnLanguageChanged(SupportedLangs newLanguage) { foreach (var provider in _providers.OrderByDescending(p => p.Priority)) { - provider.OnLanguageChanged(newLanguage); + provider.SetLanguage(newLanguage); } } } diff --git a/Reactor/Localization/LocalizationProvider.cs b/Reactor/Localization/LocalizationProvider.cs index 3e09bd6..ef341a3 100644 --- a/Reactor/Localization/LocalizationProvider.cs +++ b/Reactor/Localization/LocalizationProvider.cs @@ -8,6 +8,13 @@ namespace Reactor.Localization; /// public abstract class LocalizationProvider { + /// + /// Gets the current language Among Us is set to. + ///
+ /// If used from , this property will return the old language, not the new one. + ///
+ public SupportedLangs? CurrentLanguage { get; private set; } + /// /// Gets the priority of this . /// The higher the priority is, the earlier it will be invoked in relation to other providers. @@ -20,10 +27,9 @@ public abstract class LocalizationProvider /// Returns the localized text for the given . /// /// The to localize. - /// The current language Among Us is set to. /// The representation of the given . /// Whether or not this can handle this . - public virtual bool TryGetText(StringNames stringName, SupportedLangs language, out string? result) + public virtual bool TryGetText(StringNames stringName, out string? result) { result = null; return false; @@ -33,13 +39,12 @@ public virtual bool TryGetText(StringNames stringName, SupportedLangs language, /// Returns the localized text for the given . /// /// The to localize. - /// The current language Among Us is set to. /// The arguments used for formatting. /// The representation of the given . /// Whether or not this can handle this . - public virtual bool TryGetTextFormatted(StringNames stringName, SupportedLangs language, Il2CppReferenceArray parts, out string? result) + public virtual bool TryGetTextFormatted(StringNames stringName, Il2CppReferenceArray parts, out string? result) { - if (!TryGetText(stringName, language, out result)) return false; + if (!TryGetText(stringName, out result)) return false; result = Il2CppSystem.String.Format(result, parts); return true; @@ -76,4 +81,10 @@ public virtual bool TryGetStringName(TaskTypes taskType, out StringNames? result public virtual void OnLanguageChanged(SupportedLangs newLanguage) { } + + internal void SetLanguage(SupportedLangs newLanguage) + { + OnLanguageChanged(newLanguage); + CurrentLanguage = newLanguage; + } } diff --git a/Reactor/Localization/Patches/GetStringPatch.cs b/Reactor/Localization/Patches/GetStringPatch.cs index d7421a3..b00f1ca 100644 --- a/Reactor/Localization/Patches/GetStringPatch.cs +++ b/Reactor/Localization/Patches/GetStringPatch.cs @@ -10,11 +10,9 @@ internal static class GetStringPatch [HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetString), typeof(StringNames), typeof(Il2CppReferenceArray))] [HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetStringWithDefault), typeof(StringNames), typeof(string), typeof(Il2CppReferenceArray))] [HarmonyPrefix] - public static bool StringNamesPatch(TranslationController __instance, StringNames id, Il2CppReferenceArray parts, out string __result) + public static bool StringNamesPatch(StringNames id, Il2CppReferenceArray parts, out string __result) { - var currentLanguage = __instance.currentLanguage.languageID; - - if (LocalizationManager.TryGetTextFormatted(id, currentLanguage, parts, out __result)) + if (LocalizationManager.TryGetTextFormatted(id, parts, out __result)) { return false; } @@ -26,11 +24,9 @@ public static bool StringNamesPatch(TranslationController __instance, StringName [HarmonyPrefix] public static bool SystemTypesStringPatch(TranslationController __instance, SystemTypes room, ref string __result) { - var currentLanguage = __instance.currentLanguage.languageID; - if (LocalizationManager.TryGetStringName(room, out var stringName)) { - if (LocalizationManager.TryGetText(stringName, currentLanguage, out var text)) + if (LocalizationManager.TryGetText(stringName, out var text)) { __result = text; return false; @@ -60,11 +56,9 @@ public static bool SystemTypesStringNamesPatch(SystemTypes room, ref StringNames [HarmonyPrefix] public static bool TaskTypesStringPatch(TranslationController __instance, TaskTypes task, ref string __result) { - var currentLanguage = __instance.currentLanguage.languageID; - if (LocalizationManager.TryGetStringName(task, out var stringName)) { - if (LocalizationManager.TryGetText(stringName, currentLanguage, out var text)) + if (LocalizationManager.TryGetText(stringName, out var text)) { __result = text; return false; diff --git a/Reactor/Localization/Providers/HardCodedLocalizationProvider.cs b/Reactor/Localization/Providers/HardCodedLocalizationProvider.cs index e3d55c0..116527c 100644 --- a/Reactor/Localization/Providers/HardCodedLocalizationProvider.cs +++ b/Reactor/Localization/Providers/HardCodedLocalizationProvider.cs @@ -30,7 +30,7 @@ public static void Register(StringNames stringName, string value) public override int Priority => ReactorPriority.Low; /// - public override bool TryGetText(StringNames stringName, SupportedLangs language, [NotNullWhen(true)] out string? result) + public override bool TryGetText(StringNames stringName, [NotNullWhen(true)] out string? result) { if (!Strings.ContainsKey(stringName)) { diff --git a/Reactor/Utilities/Extensions/Il2CppInteropExtensions.cs b/Reactor/Utilities/Extensions/Il2CppInteropExtensions.cs index ce65ca1..4f6871f 100644 --- a/Reactor/Utilities/Extensions/Il2CppInteropExtensions.cs +++ b/Reactor/Utilities/Extensions/Il2CppInteropExtensions.cs @@ -20,7 +20,7 @@ public static class Il2CppInteropExtensions /// /// Utility class used for calling IL2CPP methods with boxed paramters. /// - public readonly struct Il2CppBoxedPrimitive + public readonly struct Il2CppBoxedPrimitive // TODO: Remove this when Il2CppInterop updates { /// /// The boxed . From f4b13b295e1053ddaf7c37eedd407ca0d20a972f Mon Sep 17 00:00:00 2001 From: AlexejheroYTB Date: Thu, 13 Oct 2022 18:53:56 +0300 Subject: [PATCH 16/22] Address reviews --- Reactor.Example/ExamplePlugin.cs | 20 +++++++++---------- .../HardCodedLocalizationProvider.cs | 17 +++++----------- 2 files changed, 15 insertions(+), 22 deletions(-) diff --git a/Reactor.Example/ExamplePlugin.cs b/Reactor.Example/ExamplePlugin.cs index 4ea5851..4a768e8 100644 --- a/Reactor.Example/ExamplePlugin.cs +++ b/Reactor.Example/ExamplePlugin.cs @@ -41,6 +41,16 @@ public ExampleComponent(IntPtr ptr) : base(ptr) { TestWindow = new DragWindow(new Rect(60, 20, 0, 0), "Example", () => { + if (GUILayout.Button("Log CustomStringName")) + { + Logger.Info(TranslationController.Instance.GetString(_helloStringName)); + } + + if (GUILayout.Button("Log localized string")) + { + Logger.Info(TranslationController.Instance.GetString((StringNames) 1337)); + } + if (AmongUsClient.Instance && PlayerControl.LocalPlayer) { if (GUILayout.Button("Send ExampleRpc")) @@ -61,16 +71,6 @@ public ExampleComponent(IntPtr ptr) : base(ptr) { RpcSay(PlayerControl.LocalPlayer, "Hello from method rpc", Random.value, PlayerControl.LocalPlayer); } - - if (GUILayout.Button("Log CustomStringName")) - { - Logger.Info(TranslationController.Instance.GetString(_helloStringName)); - } - - if (GUILayout.Button("Log localized string")) - { - Logger.Info(TranslationController.Instance.GetString((StringNames) 1337)); - } } }) { diff --git a/Reactor/Localization/Providers/HardCodedLocalizationProvider.cs b/Reactor/Localization/Providers/HardCodedLocalizationProvider.cs index 116527c..185f688 100644 --- a/Reactor/Localization/Providers/HardCodedLocalizationProvider.cs +++ b/Reactor/Localization/Providers/HardCodedLocalizationProvider.cs @@ -9,7 +9,7 @@ namespace Reactor.Localization.Providers; /// public sealed class HardCodedLocalizationProvider : LocalizationProvider { - internal static readonly Dictionary Strings = new(); + private static readonly Dictionary _strings = new(); /// /// Adds a custom, hard-coded translation for a . @@ -18,27 +18,20 @@ public sealed class HardCodedLocalizationProvider : LocalizationProvider /// The text. public static void Register(StringNames stringName, string value) { - if (Strings.ContainsKey(stringName)) + if (_strings.ContainsKey(stringName)) { Warning($"Registering StringName {stringName} that already exists"); } - Strings[stringName] = value; + _strings[stringName] = value; } /// public override int Priority => ReactorPriority.Low; /// - public override bool TryGetText(StringNames stringName, [NotNullWhen(true)] out string? result) + public override bool TryGetText(StringNames stringName, out string? result) { - if (!Strings.ContainsKey(stringName)) - { - result = null; - return false; - } - - result = Strings[stringName]; - return true; + return _strings.TryGetValue(stringName, out result); } } From b553741889862e37df531f9b6f9bec362d5fbedf Mon Sep 17 00:00:00 2001 From: AlexejheroYTB Date: Thu, 13 Oct 2022 19:04:37 +0300 Subject: [PATCH 17/22] Sort providers less and update currentlanguage when one is added --- Reactor/Localization/LocalizationManager.cs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/Reactor/Localization/LocalizationManager.cs b/Reactor/Localization/LocalizationManager.cs index 51d5fa8..977cf45 100644 --- a/Reactor/Localization/LocalizationManager.cs +++ b/Reactor/Localization/LocalizationManager.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Linq; using Il2CppInterop.Runtime.InteropTypes.Arrays; namespace Reactor.Localization; @@ -17,7 +16,12 @@ public static class LocalizationManager /// A instance. public static void Register(LocalizationProvider provider) { - if (!_providers.Contains(provider)) _providers.Add(provider); + if (!_providers.Contains(provider)) + { + _providers.Add(provider); + provider.SetLanguage(TranslationController.Instance.currentLanguage.languageID); + _providers.Sort((a, b) => b.Priority - a.Priority); + } } /// @@ -40,7 +44,7 @@ public static void UnregisterAllByType() where T : LocalizationProvider internal static bool TryGetTextFormatted(StringNames stringName, Il2CppReferenceArray parts, out string text) { - foreach (var provider in _providers.OrderByDescending(p => p.Priority)) + foreach (var provider in _providers) { if (provider.TryGetTextFormatted(stringName, parts, out text!)) { @@ -54,7 +58,7 @@ internal static bool TryGetTextFormatted(StringNames stringName, Il2CppReference internal static bool TryGetText(StringNames stringName, out string text) { - foreach (var provider in _providers.OrderByDescending(p => p.Priority)) + foreach (var provider in _providers) { if (provider.TryGetText(stringName, out text!)) { @@ -68,7 +72,7 @@ internal static bool TryGetText(StringNames stringName, out string text) internal static bool TryGetStringName(SystemTypes systemType, out StringNames stringName) { - foreach (var provider in _providers.OrderByDescending(p => p.Priority)) + foreach (var provider in _providers) { if (provider.TryGetStringName(systemType, out var stringNameNullable)) { @@ -83,7 +87,7 @@ internal static bool TryGetStringName(SystemTypes systemType, out StringNames st internal static bool TryGetStringName(TaskTypes taskTypes, out StringNames stringName) { - foreach (var provider in _providers.OrderByDescending(p => p.Priority)) + foreach (var provider in _providers) { if (provider.TryGetStringName(taskTypes, out var stringNameNullable)) { @@ -98,7 +102,7 @@ internal static bool TryGetStringName(TaskTypes taskTypes, out StringNames strin internal static void OnLanguageChanged(SupportedLangs newLanguage) { - foreach (var provider in _providers.OrderByDescending(p => p.Priority)) + foreach (var provider in _providers) { provider.SetLanguage(newLanguage); } From ffe0db0f00907b80a83b5653c8d6ebcfe2ec8c0f Mon Sep 17 00:00:00 2001 From: AlexejheroYTB Date: Thu, 13 Oct 2022 19:06:48 +0300 Subject: [PATCH 18/22] Check if instance exists before calling setlanguage --- Reactor/Localization/LocalizationManager.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Reactor/Localization/LocalizationManager.cs b/Reactor/Localization/LocalizationManager.cs index 977cf45..bc82068 100644 --- a/Reactor/Localization/LocalizationManager.cs +++ b/Reactor/Localization/LocalizationManager.cs @@ -19,7 +19,12 @@ public static void Register(LocalizationProvider provider) if (!_providers.Contains(provider)) { _providers.Add(provider); - provider.SetLanguage(TranslationController.Instance.currentLanguage.languageID); + + if (TranslationController.InstanceExists) + { + provider.SetLanguage(TranslationController.Instance.currentLanguage.languageID); + } + _providers.Sort((a, b) => b.Priority - a.Priority); } } From 6e42df9b92aa413de61ea276f1ef3589f88bcda9 Mon Sep 17 00:00:00 2001 From: js6pak Date: Thu, 13 Oct 2022 18:16:24 +0200 Subject: [PATCH 19/22] Use default instead StringNames.ExitButton --- Reactor/Localization/LocalizationManager.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Reactor/Localization/LocalizationManager.cs b/Reactor/Localization/LocalizationManager.cs index bc82068..b1647f9 100644 --- a/Reactor/Localization/LocalizationManager.cs +++ b/Reactor/Localization/LocalizationManager.cs @@ -86,7 +86,7 @@ internal static bool TryGetStringName(SystemTypes systemType, out StringNames st } } - stringName = StringNames.ExitButton; + stringName = default; return false; } @@ -101,7 +101,7 @@ internal static bool TryGetStringName(TaskTypes taskTypes, out StringNames strin } } - stringName = StringNames.ExitButton; + stringName = default; return false; } From 398d5049544906eb0938a83401db49e151469917 Mon Sep 17 00:00:00 2001 From: js6pak Date: Thu, 13 Oct 2022 18:16:49 +0200 Subject: [PATCH 20/22] Add SupportedLangsExtensions --- .../Extensions/SupportedLangsExtensions.cs | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 Reactor/Localization/Extensions/SupportedLangsExtensions.cs diff --git a/Reactor/Localization/Extensions/SupportedLangsExtensions.cs b/Reactor/Localization/Extensions/SupportedLangsExtensions.cs new file mode 100644 index 0000000..03c26ef --- /dev/null +++ b/Reactor/Localization/Extensions/SupportedLangsExtensions.cs @@ -0,0 +1,39 @@ +using System; +using System.Globalization; + +namespace Reactor.Localization.Extensions; + +/// +/// Provides extension methods for . +/// +public static class SupportedLangsExtensions +{ + /// + /// Gets a from the specified . + /// + /// The . + /// a . + public static CultureInfo ToCultureInfo(this SupportedLangs language) + { + return language switch + { + SupportedLangs.English => CultureInfo.GetCultureInfo("en"), + SupportedLangs.Latam => CultureInfo.GetCultureInfo("es"), + SupportedLangs.Brazilian => CultureInfo.GetCultureInfo("pt-BR"), + SupportedLangs.Portuguese => CultureInfo.GetCultureInfo("pt"), + SupportedLangs.Korean => CultureInfo.GetCultureInfo("ko"), + SupportedLangs.Russian => CultureInfo.GetCultureInfo("ru"), + SupportedLangs.Dutch => CultureInfo.GetCultureInfo("nl"), + SupportedLangs.Filipino => CultureInfo.GetCultureInfo("fil"), + SupportedLangs.French => CultureInfo.GetCultureInfo("fr"), + SupportedLangs.German => CultureInfo.GetCultureInfo("de"), + SupportedLangs.Italian => CultureInfo.GetCultureInfo("it"), + SupportedLangs.Japanese => CultureInfo.GetCultureInfo("ja"), + SupportedLangs.Spanish => CultureInfo.GetCultureInfo("es"), + SupportedLangs.SChinese => CultureInfo.GetCultureInfo("zh-Hans"), + SupportedLangs.TChinese => CultureInfo.GetCultureInfo("zh-Hant"), + SupportedLangs.Irish => CultureInfo.GetCultureInfo("ga"), + _ => throw new ArgumentOutOfRangeException(nameof(language), language, null), + }; + } +} From d5ee29ff211b6b57e575d06b1e7f1ece233befa2 Mon Sep 17 00:00:00 2001 From: js6pak Date: Tue, 18 Oct 2022 22:44:34 +0200 Subject: [PATCH 21/22] Remove Il2CppBoxedPrimitive in favor of updated Il2CppInterop --- AmongUs.props | 2 +- Reactor.Benchmarks/packages.lock.json | 50 +++++----- Reactor.Debugger/packages.lock.json | 50 +++++----- Reactor.Example/packages.lock.json | 50 +++++----- .../Extensions/TranslationExtensions.cs | 23 ----- .../Localization/Patches/GetStringPatch.cs | 5 +- .../Extensions/Il2CppInteropExtensions.cs | 92 ------------------- Reactor/packages.lock.json | 48 +++++----- 8 files changed, 102 insertions(+), 218 deletions(-) delete mode 100644 Reactor/Localization/Extensions/TranslationExtensions.cs diff --git a/AmongUs.props b/AmongUs.props index ff68350..c25a739 100644 --- a/AmongUs.props +++ b/AmongUs.props @@ -6,7 +6,7 @@ - + diff --git a/Reactor.Benchmarks/packages.lock.json b/Reactor.Benchmarks/packages.lock.json index 8007400..d896b07 100644 --- a/Reactor.Benchmarks/packages.lock.json +++ b/Reactor.Benchmarks/packages.lock.json @@ -42,17 +42,17 @@ }, "BepInEx.Unity.IL2CPP": { "type": "Direct", - "requested": "[6.0.0-be.660, )", - "resolved": "6.0.0-be.660", - "contentHash": "jYBL1hNrEKmS7FKnUIKqxU026nvvy0s5TJufkoAiLVq19ficXL/Edy72wHNKXS2GcWY1JwdTLWx44SGStyiNQw==", + "requested": "[6.0.0-be.662, )", + "resolved": "6.0.0-be.662", + "contentHash": "fn7jQ88IBmjssoY9XjGBTg3cULkS+N/le/eUijYf2VV8raWok/6cU/GbU9bejkJS8g+2MvzIwnROAhAxvrGI2Q==", "dependencies": { - "BepInEx.Core": "6.0.0-be.660", - "BepInEx.Unity.Common": "6.0.0-be.660", + "BepInEx.Core": "6.0.0-be.662", + "BepInEx.Unity.Common": "6.0.0-be.662", "HarmonyX": "2.10.0", "Iced": "1.17.0", - "Il2CppInterop.Generator": "1.2.0", - "Il2CppInterop.HarmonySupport": "1.2.0", - "Il2CppInterop.Runtime": "1.2.0", + "Il2CppInterop.Generator": "1.3.0", + "Il2CppInterop.HarmonySupport": "1.3.0", + "Il2CppInterop.Runtime": "1.3.0", "MonoMod.RuntimeDetour": "22.5.1.1", "Samboy063.Cpp2IL.Core": "2022.0.7.2" } @@ -78,8 +78,8 @@ }, "BepInEx.Core": { "type": "Transitive", - "resolved": "6.0.0-be.660", - "contentHash": "6Dbje92nIRcLALn8aqqLEuZbD3Ob/V8A7m2jHB7PhTA6HmIVZ1jJTkMRAKVRKrzAIDZITKZ1j8cGsx2HcMVPEg==", + "resolved": "6.0.0-be.662", + "contentHash": "VVBeCD/KQVy0/TK3V6SD8QZ/es35Xb1mEz/+PbBs3ST1yUC1r7k2JOymhSnmghVqf6UsvlMglOO9pljqhuE/Pw==", "dependencies": { "HarmonyX": "2.10.0", "MonoMod.Utils": "22.5.1.1", @@ -88,8 +88,8 @@ }, "BepInEx.Unity.Common": { "type": "Transitive", - "resolved": "6.0.0-be.660", - "contentHash": "FS1JbYusO407yB0FgBJfgUoCLhCa2iZBL7bLBWeafjupVPU8fkpxoV6jhPDMncbrISqA4SE21wfrHMBLv/EdjQ==", + "resolved": "6.0.0-be.662", + "contentHash": "BgETw6+snwY//3xjQxLiiEAFRmXaMTcSkg+1UQz6fVBG0YA5Usm/m4GflhTc3nwF61KO3Iznn1AORi5CwLJoUw==", "dependencies": { "AssetRipper.VersionUtilities": "1.2.1", "MonoMod.Utils": "22.5.1.1" @@ -116,8 +116,8 @@ }, "Il2CppInterop.Common": { "type": "Transitive", - "resolved": "1.2.0", - "contentHash": "igx3+2h5cdquSFn7yfZenxBnoSnczZlwhCEInil/ioULMOVeVoxTXaB07qI5I1fwDhSa37nugTx1eNqp+YP0fA==", + "resolved": "1.3.0", + "contentHash": "IR3BrZXvL2nvJAn4pruPMgC78Y87hVa5xTYZCuHN67OzRD6WDl5dTO55vtvTl8dXFALKvlN+spja2tXhVuquOw==", "dependencies": { "Iced": "1.17.0", "Microsoft.Extensions.Logging.Abstractions": "6.0.1", @@ -126,29 +126,29 @@ }, "Il2CppInterop.Generator": { "type": "Transitive", - "resolved": "1.2.0", - "contentHash": "g/CB12CCGgCUf/ykgP0LyFXPQpAy4M5kYqy43m2P0+R3htwnKs+0tF7HDCHXlOMclk/40SOThjnf7NlSXJnw+Q==", + "resolved": "1.3.0", + "contentHash": "FuhPxbh/K4K94U3xac/ClMaaBp+MZ4aIaqi5dR0QihyGQoombT+OM/A22RwAIzbaCTbFbvabWaAuOSgB69ZwWQ==", "dependencies": { - "Il2CppInterop.Common": "1.2.0", + "Il2CppInterop.Common": "1.3.0", "Mono.Cecil": "0.11.3" } }, "Il2CppInterop.HarmonySupport": { "type": "Transitive", - "resolved": "1.2.0", - "contentHash": "scyvkvZA4/vSIwaSn8G31+i1969Grve/si+V6HrVudMVsR9IsAJVhEae9KDFJGrmTdTVAFfWZvIqeS3qjDxdrA==", + "resolved": "1.3.0", + "contentHash": "VppBnXtbMNGFhX8a1gg/85E883t2pW/+FZyV7eOaOXMNQyorg++u+kUFOIYwNpzTVqxWmMeoPS0DH0toVpjoKA==", "dependencies": { "HarmonyX": "2.10.0", - "Il2CppInterop.Runtime": "1.2.0" + "Il2CppInterop.Runtime": "1.3.0" } }, "Il2CppInterop.Runtime": { "type": "Transitive", - "resolved": "1.2.0", - "contentHash": "8nv5Jb9cqqIqVgbFCW2vsEcNYrSGFPgEE7XXePR3HhIl3CMbbHJxEAYDatJY4GfNQeeE4avLpXiV6XVkFnWGQg==", + "resolved": "1.3.0", + "contentHash": "8A+N2yvja960Ap+s2RpW7Nb6HSpyuXJy2ipIlU+1erYU9SWHMyU9JZzUZGOhwWXJChKGvRmDdTZAg12k1+72dg==", "dependencies": { "Iced": "1.17.0", - "Il2CppInterop.Common": "1.2.0" + "Il2CppInterop.Common": "1.3.0" } }, "IndexRange": { @@ -1074,9 +1074,9 @@ "reactor": { "type": "Project", "dependencies": { - "BepInEx.Unity.IL2CPP": "[6.0.0-be.660, )" + "BepInEx.Unity.IL2CPP": "[6.0.0-be.662, )" } } } } -} \ No newline at end of file +} diff --git a/Reactor.Debugger/packages.lock.json b/Reactor.Debugger/packages.lock.json index 5e55856..1c7fa57 100644 --- a/Reactor.Debugger/packages.lock.json +++ b/Reactor.Debugger/packages.lock.json @@ -22,17 +22,17 @@ }, "BepInEx.Unity.IL2CPP": { "type": "Direct", - "requested": "[6.0.0-be.660, )", - "resolved": "6.0.0-be.660", - "contentHash": "jYBL1hNrEKmS7FKnUIKqxU026nvvy0s5TJufkoAiLVq19ficXL/Edy72wHNKXS2GcWY1JwdTLWx44SGStyiNQw==", + "requested": "[6.0.0-be.662, )", + "resolved": "6.0.0-be.662", + "contentHash": "fn7jQ88IBmjssoY9XjGBTg3cULkS+N/le/eUijYf2VV8raWok/6cU/GbU9bejkJS8g+2MvzIwnROAhAxvrGI2Q==", "dependencies": { - "BepInEx.Core": "6.0.0-be.660", - "BepInEx.Unity.Common": "6.0.0-be.660", + "BepInEx.Core": "6.0.0-be.662", + "BepInEx.Unity.Common": "6.0.0-be.662", "HarmonyX": "2.10.0", "Iced": "1.17.0", - "Il2CppInterop.Generator": "1.2.0", - "Il2CppInterop.HarmonySupport": "1.2.0", - "Il2CppInterop.Runtime": "1.2.0", + "Il2CppInterop.Generator": "1.3.0", + "Il2CppInterop.HarmonySupport": "1.3.0", + "Il2CppInterop.Runtime": "1.3.0", "MonoMod.RuntimeDetour": "22.5.1.1", "Samboy063.Cpp2IL.Core": "2022.0.7.2" } @@ -53,8 +53,8 @@ }, "BepInEx.Core": { "type": "Transitive", - "resolved": "6.0.0-be.660", - "contentHash": "6Dbje92nIRcLALn8aqqLEuZbD3Ob/V8A7m2jHB7PhTA6HmIVZ1jJTkMRAKVRKrzAIDZITKZ1j8cGsx2HcMVPEg==", + "resolved": "6.0.0-be.662", + "contentHash": "VVBeCD/KQVy0/TK3V6SD8QZ/es35Xb1mEz/+PbBs3ST1yUC1r7k2JOymhSnmghVqf6UsvlMglOO9pljqhuE/Pw==", "dependencies": { "HarmonyX": "2.10.0", "MonoMod.Utils": "22.5.1.1", @@ -63,8 +63,8 @@ }, "BepInEx.Unity.Common": { "type": "Transitive", - "resolved": "6.0.0-be.660", - "contentHash": "FS1JbYusO407yB0FgBJfgUoCLhCa2iZBL7bLBWeafjupVPU8fkpxoV6jhPDMncbrISqA4SE21wfrHMBLv/EdjQ==", + "resolved": "6.0.0-be.662", + "contentHash": "BgETw6+snwY//3xjQxLiiEAFRmXaMTcSkg+1UQz6fVBG0YA5Usm/m4GflhTc3nwF61KO3Iznn1AORi5CwLJoUw==", "dependencies": { "AssetRipper.VersionUtilities": "1.2.1", "MonoMod.Utils": "22.5.1.1" @@ -86,8 +86,8 @@ }, "Il2CppInterop.Common": { "type": "Transitive", - "resolved": "1.2.0", - "contentHash": "igx3+2h5cdquSFn7yfZenxBnoSnczZlwhCEInil/ioULMOVeVoxTXaB07qI5I1fwDhSa37nugTx1eNqp+YP0fA==", + "resolved": "1.3.0", + "contentHash": "IR3BrZXvL2nvJAn4pruPMgC78Y87hVa5xTYZCuHN67OzRD6WDl5dTO55vtvTl8dXFALKvlN+spja2tXhVuquOw==", "dependencies": { "Iced": "1.17.0", "Microsoft.Extensions.Logging.Abstractions": "6.0.1", @@ -96,29 +96,29 @@ }, "Il2CppInterop.Generator": { "type": "Transitive", - "resolved": "1.2.0", - "contentHash": "g/CB12CCGgCUf/ykgP0LyFXPQpAy4M5kYqy43m2P0+R3htwnKs+0tF7HDCHXlOMclk/40SOThjnf7NlSXJnw+Q==", + "resolved": "1.3.0", + "contentHash": "FuhPxbh/K4K94U3xac/ClMaaBp+MZ4aIaqi5dR0QihyGQoombT+OM/A22RwAIzbaCTbFbvabWaAuOSgB69ZwWQ==", "dependencies": { - "Il2CppInterop.Common": "1.2.0", + "Il2CppInterop.Common": "1.3.0", "Mono.Cecil": "0.11.3" } }, "Il2CppInterop.HarmonySupport": { "type": "Transitive", - "resolved": "1.2.0", - "contentHash": "scyvkvZA4/vSIwaSn8G31+i1969Grve/si+V6HrVudMVsR9IsAJVhEae9KDFJGrmTdTVAFfWZvIqeS3qjDxdrA==", + "resolved": "1.3.0", + "contentHash": "VppBnXtbMNGFhX8a1gg/85E883t2pW/+FZyV7eOaOXMNQyorg++u+kUFOIYwNpzTVqxWmMeoPS0DH0toVpjoKA==", "dependencies": { "HarmonyX": "2.10.0", - "Il2CppInterop.Runtime": "1.2.0" + "Il2CppInterop.Runtime": "1.3.0" } }, "Il2CppInterop.Runtime": { "type": "Transitive", - "resolved": "1.2.0", - "contentHash": "8nv5Jb9cqqIqVgbFCW2vsEcNYrSGFPgEE7XXePR3HhIl3CMbbHJxEAYDatJY4GfNQeeE4avLpXiV6XVkFnWGQg==", + "resolved": "1.3.0", + "contentHash": "8A+N2yvja960Ap+s2RpW7Nb6HSpyuXJy2ipIlU+1erYU9SWHMyU9JZzUZGOhwWXJChKGvRmDdTZAg12k1+72dg==", "dependencies": { "Iced": "1.17.0", - "Il2CppInterop.Common": "1.2.0" + "Il2CppInterop.Common": "1.3.0" } }, "IndexRange": { @@ -867,9 +867,9 @@ "reactor": { "type": "Project", "dependencies": { - "BepInEx.Unity.IL2CPP": "[6.0.0-be.660, )" + "BepInEx.Unity.IL2CPP": "[6.0.0-be.662, )" } } } } -} \ No newline at end of file +} diff --git a/Reactor.Example/packages.lock.json b/Reactor.Example/packages.lock.json index 5e55856..1c7fa57 100644 --- a/Reactor.Example/packages.lock.json +++ b/Reactor.Example/packages.lock.json @@ -22,17 +22,17 @@ }, "BepInEx.Unity.IL2CPP": { "type": "Direct", - "requested": "[6.0.0-be.660, )", - "resolved": "6.0.0-be.660", - "contentHash": "jYBL1hNrEKmS7FKnUIKqxU026nvvy0s5TJufkoAiLVq19ficXL/Edy72wHNKXS2GcWY1JwdTLWx44SGStyiNQw==", + "requested": "[6.0.0-be.662, )", + "resolved": "6.0.0-be.662", + "contentHash": "fn7jQ88IBmjssoY9XjGBTg3cULkS+N/le/eUijYf2VV8raWok/6cU/GbU9bejkJS8g+2MvzIwnROAhAxvrGI2Q==", "dependencies": { - "BepInEx.Core": "6.0.0-be.660", - "BepInEx.Unity.Common": "6.0.0-be.660", + "BepInEx.Core": "6.0.0-be.662", + "BepInEx.Unity.Common": "6.0.0-be.662", "HarmonyX": "2.10.0", "Iced": "1.17.0", - "Il2CppInterop.Generator": "1.2.0", - "Il2CppInterop.HarmonySupport": "1.2.0", - "Il2CppInterop.Runtime": "1.2.0", + "Il2CppInterop.Generator": "1.3.0", + "Il2CppInterop.HarmonySupport": "1.3.0", + "Il2CppInterop.Runtime": "1.3.0", "MonoMod.RuntimeDetour": "22.5.1.1", "Samboy063.Cpp2IL.Core": "2022.0.7.2" } @@ -53,8 +53,8 @@ }, "BepInEx.Core": { "type": "Transitive", - "resolved": "6.0.0-be.660", - "contentHash": "6Dbje92nIRcLALn8aqqLEuZbD3Ob/V8A7m2jHB7PhTA6HmIVZ1jJTkMRAKVRKrzAIDZITKZ1j8cGsx2HcMVPEg==", + "resolved": "6.0.0-be.662", + "contentHash": "VVBeCD/KQVy0/TK3V6SD8QZ/es35Xb1mEz/+PbBs3ST1yUC1r7k2JOymhSnmghVqf6UsvlMglOO9pljqhuE/Pw==", "dependencies": { "HarmonyX": "2.10.0", "MonoMod.Utils": "22.5.1.1", @@ -63,8 +63,8 @@ }, "BepInEx.Unity.Common": { "type": "Transitive", - "resolved": "6.0.0-be.660", - "contentHash": "FS1JbYusO407yB0FgBJfgUoCLhCa2iZBL7bLBWeafjupVPU8fkpxoV6jhPDMncbrISqA4SE21wfrHMBLv/EdjQ==", + "resolved": "6.0.0-be.662", + "contentHash": "BgETw6+snwY//3xjQxLiiEAFRmXaMTcSkg+1UQz6fVBG0YA5Usm/m4GflhTc3nwF61KO3Iznn1AORi5CwLJoUw==", "dependencies": { "AssetRipper.VersionUtilities": "1.2.1", "MonoMod.Utils": "22.5.1.1" @@ -86,8 +86,8 @@ }, "Il2CppInterop.Common": { "type": "Transitive", - "resolved": "1.2.0", - "contentHash": "igx3+2h5cdquSFn7yfZenxBnoSnczZlwhCEInil/ioULMOVeVoxTXaB07qI5I1fwDhSa37nugTx1eNqp+YP0fA==", + "resolved": "1.3.0", + "contentHash": "IR3BrZXvL2nvJAn4pruPMgC78Y87hVa5xTYZCuHN67OzRD6WDl5dTO55vtvTl8dXFALKvlN+spja2tXhVuquOw==", "dependencies": { "Iced": "1.17.0", "Microsoft.Extensions.Logging.Abstractions": "6.0.1", @@ -96,29 +96,29 @@ }, "Il2CppInterop.Generator": { "type": "Transitive", - "resolved": "1.2.0", - "contentHash": "g/CB12CCGgCUf/ykgP0LyFXPQpAy4M5kYqy43m2P0+R3htwnKs+0tF7HDCHXlOMclk/40SOThjnf7NlSXJnw+Q==", + "resolved": "1.3.0", + "contentHash": "FuhPxbh/K4K94U3xac/ClMaaBp+MZ4aIaqi5dR0QihyGQoombT+OM/A22RwAIzbaCTbFbvabWaAuOSgB69ZwWQ==", "dependencies": { - "Il2CppInterop.Common": "1.2.0", + "Il2CppInterop.Common": "1.3.0", "Mono.Cecil": "0.11.3" } }, "Il2CppInterop.HarmonySupport": { "type": "Transitive", - "resolved": "1.2.0", - "contentHash": "scyvkvZA4/vSIwaSn8G31+i1969Grve/si+V6HrVudMVsR9IsAJVhEae9KDFJGrmTdTVAFfWZvIqeS3qjDxdrA==", + "resolved": "1.3.0", + "contentHash": "VppBnXtbMNGFhX8a1gg/85E883t2pW/+FZyV7eOaOXMNQyorg++u+kUFOIYwNpzTVqxWmMeoPS0DH0toVpjoKA==", "dependencies": { "HarmonyX": "2.10.0", - "Il2CppInterop.Runtime": "1.2.0" + "Il2CppInterop.Runtime": "1.3.0" } }, "Il2CppInterop.Runtime": { "type": "Transitive", - "resolved": "1.2.0", - "contentHash": "8nv5Jb9cqqIqVgbFCW2vsEcNYrSGFPgEE7XXePR3HhIl3CMbbHJxEAYDatJY4GfNQeeE4avLpXiV6XVkFnWGQg==", + "resolved": "1.3.0", + "contentHash": "8A+N2yvja960Ap+s2RpW7Nb6HSpyuXJy2ipIlU+1erYU9SWHMyU9JZzUZGOhwWXJChKGvRmDdTZAg12k1+72dg==", "dependencies": { "Iced": "1.17.0", - "Il2CppInterop.Common": "1.2.0" + "Il2CppInterop.Common": "1.3.0" } }, "IndexRange": { @@ -867,9 +867,9 @@ "reactor": { "type": "Project", "dependencies": { - "BepInEx.Unity.IL2CPP": "[6.0.0-be.660, )" + "BepInEx.Unity.IL2CPP": "[6.0.0-be.662, )" } } } } -} \ No newline at end of file +} diff --git a/Reactor/Localization/Extensions/TranslationExtensions.cs b/Reactor/Localization/Extensions/TranslationExtensions.cs deleted file mode 100644 index 948e92e..0000000 --- a/Reactor/Localization/Extensions/TranslationExtensions.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Linq; -using Il2CppInterop.Runtime.InteropTypes.Arrays; -using Reactor.Utilities.Extensions; -using Object = Il2CppSystem.Object; - -namespace Reactor.Localization.Extensions; - -/// -/// Extension methods for . -/// -public static class TranslationExtensions -{ - /// - /// Invoking - /// directly will generally cause exceptions, this version makes it easier for the developer to invoke this method without worrying about IL2CPP boxing bs. - /// - /// The instance. - /// The to convert into . - /// Optional arguments to be used in . - /// The representation of the . - public static string GetStringFixed(this TranslationController self, StringNames name, params Il2CppInteropExtensions.Il2CppBoxedPrimitive[] args) - => self.GetString(name, new Il2CppReferenceArray(args.Select(o => o.Object).ToArray())); -} diff --git a/Reactor/Localization/Patches/GetStringPatch.cs b/Reactor/Localization/Patches/GetStringPatch.cs index b00f1ca..aa765c5 100644 --- a/Reactor/Localization/Patches/GetStringPatch.cs +++ b/Reactor/Localization/Patches/GetStringPatch.cs @@ -1,6 +1,5 @@ using HarmonyLib; using Il2CppInterop.Runtime.InteropTypes.Arrays; -using Reactor.Localization.Extensions; namespace Reactor.Localization.Patches; @@ -32,7 +31,7 @@ public static bool SystemTypesStringPatch(TranslationController __instance, Syst return false; } - __result = __instance.GetStringFixed(stringName); + __result = __instance.GetString(stringName); return false; } @@ -64,7 +63,7 @@ public static bool TaskTypesStringPatch(TranslationController __instance, TaskTy return false; } - __result = __instance.GetStringFixed(stringName); + __result = __instance.GetString(stringName); return false; } diff --git a/Reactor/Utilities/Extensions/Il2CppInteropExtensions.cs b/Reactor/Utilities/Extensions/Il2CppInteropExtensions.cs index 4f6871f..41f58ed 100644 --- a/Reactor/Utilities/Extensions/Il2CppInteropExtensions.cs +++ b/Reactor/Utilities/Extensions/Il2CppInteropExtensions.cs @@ -1,14 +1,5 @@ using System; using Il2CppInterop.Runtime.InteropTypes.Arrays; -using Double = Il2CppSystem.Double; -using Int16 = Il2CppSystem.Int16; -using Int32 = Il2CppSystem.Int32; -using Int64 = Il2CppSystem.Int64; -using Object = Il2CppSystem.Object; -using Single = Il2CppSystem.Single; -using UInt16 = Il2CppSystem.UInt16; -using UInt32 = Il2CppSystem.UInt32; -using UInt64 = Il2CppSystem.UInt64; namespace Reactor.Utilities.Extensions; @@ -17,89 +8,6 @@ namespace Reactor.Utilities.Extensions; /// public static class Il2CppInteropExtensions { - /// - /// Utility class used for calling IL2CPP methods with boxed paramters. - /// - public readonly struct Il2CppBoxedPrimitive // TODO: Remove this when Il2CppInterop updates - { - /// - /// The boxed . - /// - internal readonly Object Object; - - private Il2CppBoxedPrimitive(Object obj) => Object = obj; - - /// - /// Returns the boxed by this . - /// - /// The . - /// The boxed . - public static implicit operator Object(Il2CppBoxedPrimitive parsable) => parsable.Object; - - /// - /// Creates a new instance of from a . - /// - /// The to box. - /// The instance. - public static implicit operator Il2CppBoxedPrimitive(short value) => new(new Int16 { m_value = value }.BoxIl2CppObject()); - - /// - /// Creates a new instance of from an . - /// - /// The to box. - /// The instance. - public static implicit operator Il2CppBoxedPrimitive(int value) => new(new Int32 { m_value = value }.BoxIl2CppObject()); - - /// - /// Creates a new instance of from a . - /// - /// The to box. - /// The instance. - public static implicit operator Il2CppBoxedPrimitive(long value) => new(new Int64 { m_value = value }.BoxIl2CppObject()); - - /// - /// Creates a new instance of from a . - /// - /// The to box. - /// The instance. - public static implicit operator Il2CppBoxedPrimitive(ushort value) => new(new UInt16 { m_value = value }.BoxIl2CppObject()); - - /// - /// Creates a new instance of from a . - /// - /// The to box. - /// The instance. - public static implicit operator Il2CppBoxedPrimitive(uint value) => new(new UInt32 { m_value = value }.BoxIl2CppObject()); - - /// - /// Creates a new instance of from a . - /// - /// The to box. - /// The instance. - public static implicit operator Il2CppBoxedPrimitive(ulong value) => new(new UInt64 { m_value = value }.BoxIl2CppObject()); - - /// - /// Creates a new instance of from a . - /// - /// The to box. - /// The instance. - public static implicit operator Il2CppBoxedPrimitive(float value) => new(new Single { m_value = value }.BoxIl2CppObject()); - - /// - /// Creates a new instance of from a . - /// - /// The to box. - /// The instance. - public static implicit operator Il2CppBoxedPrimitive(double value) => new(new Double { m_value = value }.BoxIl2CppObject()); - - /// - /// Creates a new instance of from a . - /// - /// The to box. - /// The instance. - public static implicit operator Il2CppBoxedPrimitive(string value) => new(value); - } - /// /// Creates a span over a . /// diff --git a/Reactor/packages.lock.json b/Reactor/packages.lock.json index a901255..02c04ae 100644 --- a/Reactor/packages.lock.json +++ b/Reactor/packages.lock.json @@ -22,17 +22,17 @@ }, "BepInEx.Unity.IL2CPP": { "type": "Direct", - "requested": "[6.0.0-be.660, )", - "resolved": "6.0.0-be.660", - "contentHash": "jYBL1hNrEKmS7FKnUIKqxU026nvvy0s5TJufkoAiLVq19ficXL/Edy72wHNKXS2GcWY1JwdTLWx44SGStyiNQw==", + "requested": "[6.0.0-be.662, )", + "resolved": "6.0.0-be.662", + "contentHash": "fn7jQ88IBmjssoY9XjGBTg3cULkS+N/le/eUijYf2VV8raWok/6cU/GbU9bejkJS8g+2MvzIwnROAhAxvrGI2Q==", "dependencies": { - "BepInEx.Core": "6.0.0-be.660", - "BepInEx.Unity.Common": "6.0.0-be.660", + "BepInEx.Core": "6.0.0-be.662", + "BepInEx.Unity.Common": "6.0.0-be.662", "HarmonyX": "2.10.0", "Iced": "1.17.0", - "Il2CppInterop.Generator": "1.2.0", - "Il2CppInterop.HarmonySupport": "1.2.0", - "Il2CppInterop.Runtime": "1.2.0", + "Il2CppInterop.Generator": "1.3.0", + "Il2CppInterop.HarmonySupport": "1.3.0", + "Il2CppInterop.Runtime": "1.3.0", "MonoMod.RuntimeDetour": "22.5.1.1", "Samboy063.Cpp2IL.Core": "2022.0.7.2" } @@ -63,8 +63,8 @@ }, "BepInEx.Core": { "type": "Transitive", - "resolved": "6.0.0-be.660", - "contentHash": "6Dbje92nIRcLALn8aqqLEuZbD3Ob/V8A7m2jHB7PhTA6HmIVZ1jJTkMRAKVRKrzAIDZITKZ1j8cGsx2HcMVPEg==", + "resolved": "6.0.0-be.662", + "contentHash": "VVBeCD/KQVy0/TK3V6SD8QZ/es35Xb1mEz/+PbBs3ST1yUC1r7k2JOymhSnmghVqf6UsvlMglOO9pljqhuE/Pw==", "dependencies": { "HarmonyX": "2.10.0", "MonoMod.Utils": "22.5.1.1", @@ -73,8 +73,8 @@ }, "BepInEx.Unity.Common": { "type": "Transitive", - "resolved": "6.0.0-be.660", - "contentHash": "FS1JbYusO407yB0FgBJfgUoCLhCa2iZBL7bLBWeafjupVPU8fkpxoV6jhPDMncbrISqA4SE21wfrHMBLv/EdjQ==", + "resolved": "6.0.0-be.662", + "contentHash": "BgETw6+snwY//3xjQxLiiEAFRmXaMTcSkg+1UQz6fVBG0YA5Usm/m4GflhTc3nwF61KO3Iznn1AORi5CwLJoUw==", "dependencies": { "AssetRipper.VersionUtilities": "1.2.1", "MonoMod.Utils": "22.5.1.1" @@ -96,8 +96,8 @@ }, "Il2CppInterop.Common": { "type": "Transitive", - "resolved": "1.2.0", - "contentHash": "igx3+2h5cdquSFn7yfZenxBnoSnczZlwhCEInil/ioULMOVeVoxTXaB07qI5I1fwDhSa37nugTx1eNqp+YP0fA==", + "resolved": "1.3.0", + "contentHash": "IR3BrZXvL2nvJAn4pruPMgC78Y87hVa5xTYZCuHN67OzRD6WDl5dTO55vtvTl8dXFALKvlN+spja2tXhVuquOw==", "dependencies": { "Iced": "1.17.0", "Microsoft.Extensions.Logging.Abstractions": "6.0.1", @@ -106,29 +106,29 @@ }, "Il2CppInterop.Generator": { "type": "Transitive", - "resolved": "1.2.0", - "contentHash": "g/CB12CCGgCUf/ykgP0LyFXPQpAy4M5kYqy43m2P0+R3htwnKs+0tF7HDCHXlOMclk/40SOThjnf7NlSXJnw+Q==", + "resolved": "1.3.0", + "contentHash": "FuhPxbh/K4K94U3xac/ClMaaBp+MZ4aIaqi5dR0QihyGQoombT+OM/A22RwAIzbaCTbFbvabWaAuOSgB69ZwWQ==", "dependencies": { - "Il2CppInterop.Common": "1.2.0", + "Il2CppInterop.Common": "1.3.0", "Mono.Cecil": "0.11.3" } }, "Il2CppInterop.HarmonySupport": { "type": "Transitive", - "resolved": "1.2.0", - "contentHash": "scyvkvZA4/vSIwaSn8G31+i1969Grve/si+V6HrVudMVsR9IsAJVhEae9KDFJGrmTdTVAFfWZvIqeS3qjDxdrA==", + "resolved": "1.3.0", + "contentHash": "VppBnXtbMNGFhX8a1gg/85E883t2pW/+FZyV7eOaOXMNQyorg++u+kUFOIYwNpzTVqxWmMeoPS0DH0toVpjoKA==", "dependencies": { "HarmonyX": "2.10.0", - "Il2CppInterop.Runtime": "1.2.0" + "Il2CppInterop.Runtime": "1.3.0" } }, "Il2CppInterop.Runtime": { "type": "Transitive", - "resolved": "1.2.0", - "contentHash": "8nv5Jb9cqqIqVgbFCW2vsEcNYrSGFPgEE7XXePR3HhIl3CMbbHJxEAYDatJY4GfNQeeE4avLpXiV6XVkFnWGQg==", + "resolved": "1.3.0", + "contentHash": "8A+N2yvja960Ap+s2RpW7Nb6HSpyuXJy2ipIlU+1erYU9SWHMyU9JZzUZGOhwWXJChKGvRmDdTZAg12k1+72dg==", "dependencies": { "Iced": "1.17.0", - "Il2CppInterop.Common": "1.2.0" + "Il2CppInterop.Common": "1.3.0" } }, "IndexRange": { @@ -886,4 +886,4 @@ } } } -} \ No newline at end of file +} From 51698711136bca271c38c3a3dd036dca541d2721 Mon Sep 17 00:00:00 2001 From: js6pak Date: Sun, 23 Oct 2022 15:24:27 +0200 Subject: [PATCH 22/22] Expose providers as a readonly list --- Reactor/Localization/LocalizationManager.cs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/Reactor/Localization/LocalizationManager.cs b/Reactor/Localization/LocalizationManager.cs index b1647f9..6f12b09 100644 --- a/Reactor/Localization/LocalizationManager.cs +++ b/Reactor/Localization/LocalizationManager.cs @@ -10,6 +10,11 @@ public static class LocalizationManager { private static readonly List _providers = new(); + /// + /// Gets registered s. + /// + public static IReadOnlyList Providers { get; } = _providers.AsReadOnly(); + /// /// Registers a new to be used for obtaining translations. /// @@ -38,15 +43,6 @@ public static void Unregister(LocalizationProvider provider) _providers.Remove(provider); } - /// - /// Unregisters all s of the given type. - /// - /// The type of the s to be unregistered. - public static void UnregisterAllByType() where T : LocalizationProvider - { - _providers.RemoveAll(x => x is T); - } - internal static bool TryGetTextFormatted(StringNames stringName, Il2CppReferenceArray parts, out string text) { foreach (var provider in _providers)