mirror of
https://github.com/NuclearPowered/Reactor.git
synced 2026-10-19 15:51:54 +00:00
Add localization API (#64)
Co-authored-by: js6pak <kubastaron@hotmail.com>
This commit is contained in:
1 parent
f2da251ae5
commit
0c8156aaf6
14 files changed
+523
-86
No files matched your search
@@ -31,7 +31,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="all" />
|
||||
<AdditionalFiles Include="$(MSBuildThisFileDirectory)\stylecop.json" Link="stylecop.json" />
|
||||
<AdditionalFiles Include="$(MSBuildThisFileDirectory)\stylecop.json" Link="stylecop.json" Visible="false" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)\stylecop.ruleset</CodeAnalysisRuleSet>
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
using Reactor.Localization;
|
||||
|
||||
namespace Reactor.Example;
|
||||
|
||||
public class ExampleLocalizationProvider : LocalizationProvider
|
||||
{
|
||||
public override bool TryGetText(StringNames stringName, out string? result)
|
||||
{
|
||||
if (stringName == (StringNames) 1337)
|
||||
{
|
||||
switch (CurrentLanguage)
|
||||
{
|
||||
case SupportedLangs.English:
|
||||
result = "Cringe English";
|
||||
return true;
|
||||
|
||||
default:
|
||||
result = "Based " + CurrentLanguage;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,8 @@ using System;
|
||||
using BepInEx;
|
||||
using BepInEx.Unity.IL2CPP;
|
||||
using Il2CppInterop.Runtime.Attributes;
|
||||
using Reactor.Localization;
|
||||
using Reactor.Localization.Utilities;
|
||||
using Reactor.Networking;
|
||||
using Reactor.Networking.Attributes;
|
||||
using Reactor.Networking.Rpc;
|
||||
@@ -19,9 +21,14 @@ namespace Reactor.Example;
|
||||
[ReactorModFlags(ModFlags.RequireOnAllClients)]
|
||||
public partial class ExamplePlugin : BasePlugin
|
||||
{
|
||||
private static StringNames _helloStringName;
|
||||
|
||||
public override void Load()
|
||||
{
|
||||
this.AddComponent<ExampleComponent>();
|
||||
|
||||
_helloStringName = CustomStringName.CreateAndRegister("Hello!");
|
||||
LocalizationManager.Register(new ExampleLocalizationProvider());
|
||||
}
|
||||
|
||||
[RegisterInIl2Cpp]
|
||||
@@ -34,19 +41,29 @@ public partial class ExamplePlugin : BasePlugin
|
||||
{
|
||||
TestWindow = new DragWindow(new Rect(60, 20, 0, 0), "Example", () =>
|
||||
{
|
||||
if (GUILayout.Button("Log CustomStringName"))
|
||||
{
|
||||
Logger<ExamplePlugin>.Info(TranslationController.Instance.GetString(_helloStringName));
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Log localized string"))
|
||||
{
|
||||
Logger<ExamplePlugin>.Info(TranslationController.Instance.GetString((StringNames) 1337));
|
||||
}
|
||||
|
||||
if (AmongUsClient.Instance && PlayerControl.LocalPlayer)
|
||||
{
|
||||
if (GUILayout.Button("Send ExampleRpc"))
|
||||
{
|
||||
var name = PlayerControl.LocalPlayer.Data.PlayerName;
|
||||
Rpc<ExampleRpc>.Instance.Send(new ExampleRpc.Data($"Send: from {name}"), ackCallback: () =>
|
||||
var playerName = PlayerControl.LocalPlayer.Data.PlayerName;
|
||||
Rpc<ExampleRpc>.Instance.Send(new ExampleRpc.Data($"Send: from {playerName}"), ackCallback: () =>
|
||||
{
|
||||
Logger<ExamplePlugin>.Info("Got an acknowledgement for example rpc");
|
||||
});
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost)
|
||||
{
|
||||
Rpc<ExampleRpc>.Instance.SendTo(AmongUsClient.Instance.HostId, new ExampleRpc.Data($"SendTo: from {name} to host"));
|
||||
Rpc<ExampleRpc>.Instance.SendTo(AmongUsClient.Instance.HostId, new ExampleRpc.Data($"SendTo: from {playerName} to host"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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}"
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using HarmonyLib;
|
||||
using Il2CppInterop.Runtime.InteropTypes.Arrays;
|
||||
|
||||
namespace Reactor.Localization;
|
||||
|
||||
/// <summary>
|
||||
/// Provides a way to use custom static StringNames.
|
||||
/// </summary>
|
||||
public class CustomStringName
|
||||
{
|
||||
private static int _lastId = -1;
|
||||
|
||||
private static readonly List<CustomStringName> _list = new();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of all <see cref="CustomStringName"/>s.
|
||||
/// </summary>
|
||||
public static IReadOnlyList<CustomStringName> List => _list.AsReadOnly();
|
||||
|
||||
/// <summary>
|
||||
/// Registers a <see cref="CustomStringName"/> with specified <paramref name="value"/>.
|
||||
/// </summary>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <returns>A <see cref="CustomStringName"/>.</returns>
|
||||
public static CustomStringName Register(string value)
|
||||
{
|
||||
var customStringName = new CustomStringName(_lastId--, value);
|
||||
_list.Add(customStringName);
|
||||
|
||||
return customStringName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the id.
|
||||
/// </summary>
|
||||
public int Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value.
|
||||
/// </summary>
|
||||
public string Value { get; }
|
||||
|
||||
private CustomStringName(int id, string value)
|
||||
{
|
||||
Id = id;
|
||||
Value = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines an implicit conversion of a <see cref="CustomStringName"/> to a <see cref="StringNames"/>.
|
||||
/// </summary>
|
||||
/// <param name="name">The <see cref="CustomStringName"/>.</param>
|
||||
/// <returns>A <see cref="StringNames"/>.</returns>
|
||||
public static implicit operator StringNames(CustomStringName name) => (StringNames) name.Id;
|
||||
|
||||
/// <summary>
|
||||
/// Defines an explicit conversion of a <see cref="StringNames"/> to a <see cref="CustomStringName"/>.
|
||||
/// </summary>
|
||||
/// <param name="name">The <see cref="StringNames"/>.</param>
|
||||
/// <returns>A <see cref="CustomStringName"/>.</returns>
|
||||
public static explicit operator CustomStringName?(StringNames name) => List.SingleOrDefault(x => x.Id == (int) name);
|
||||
|
||||
[HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetString), typeof(StringNames), typeof(Il2CppReferenceArray<Il2CppSystem.Object>))]
|
||||
private static class GetStringPatch
|
||||
{
|
||||
public static bool Prefix(StringNames id, Il2CppReferenceArray<Il2CppSystem.Object> parts, ref string __result)
|
||||
{
|
||||
var customStringName = (CustomStringName?) id;
|
||||
|
||||
if (customStringName != null)
|
||||
{
|
||||
__result = string.Format(CultureInfo.InvariantCulture, customStringName.Value, parts);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Reactor.Localization.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// Provides extension methods for <see cref="SupportedLangs"/>.
|
||||
/// </summary>
|
||||
public static class SupportedLangsExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a <see cref="CultureInfo"/> from the specified <paramref name="language"/>.
|
||||
/// </summary>
|
||||
/// <param name="language">The <see cref="SupportedLangs"/>.</param>
|
||||
/// <returns>a <see cref="CultureInfo"/>.</returns>
|
||||
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),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
using System.Collections.Generic;
|
||||
using Il2CppInterop.Runtime.InteropTypes.Arrays;
|
||||
|
||||
namespace Reactor.Localization;
|
||||
|
||||
/// <summary>
|
||||
/// Handles custom <see cref="StringNames"/> localization.
|
||||
/// </summary>
|
||||
public static class LocalizationManager
|
||||
{
|
||||
private static readonly List<LocalizationProvider> _providers = new();
|
||||
|
||||
/// <summary>
|
||||
/// Gets registered <see cref="LocalizationProvider"/>s.
|
||||
/// </summary>
|
||||
public static IReadOnlyList<LocalizationProvider> Providers { get; } = _providers.AsReadOnly();
|
||||
|
||||
/// <summary>
|
||||
/// Registers a new <see cref="LocalizationProvider"/> to be used for obtaining translations.
|
||||
/// </summary>
|
||||
/// <param name="provider">A <see cref="LocalizationProvider"/> instance.</param>
|
||||
public static void Register(LocalizationProvider provider)
|
||||
{
|
||||
if (!_providers.Contains(provider))
|
||||
{
|
||||
_providers.Add(provider);
|
||||
|
||||
if (TranslationController.InstanceExists)
|
||||
{
|
||||
provider.SetLanguage(TranslationController.Instance.currentLanguage.languageID);
|
||||
}
|
||||
|
||||
_providers.Sort((a, b) => b.Priority - a.Priority);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unregisters a <see cref="LocalizationProvider"/>.
|
||||
/// </summary>
|
||||
/// <param name="provider">The <see cref="LocalizationProvider"/> to unregister.</param>
|
||||
public static void Unregister(LocalizationProvider provider)
|
||||
{
|
||||
_providers.Remove(provider);
|
||||
}
|
||||
|
||||
internal static bool TryGetTextFormatted(StringNames stringName, Il2CppReferenceArray<Il2CppSystem.Object> parts, out string text)
|
||||
{
|
||||
foreach (var provider in _providers)
|
||||
{
|
||||
if (provider.TryGetTextFormatted(stringName, parts, out text!))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
text = string.Empty;
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static bool TryGetText(StringNames stringName, out string text)
|
||||
{
|
||||
foreach (var provider in _providers)
|
||||
{
|
||||
if (provider.TryGetText(stringName, out text!))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
text = string.Empty;
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static bool TryGetStringName(SystemTypes systemType, out StringNames stringName)
|
||||
{
|
||||
foreach (var provider in _providers)
|
||||
{
|
||||
if (provider.TryGetStringName(systemType, out var stringNameNullable))
|
||||
{
|
||||
stringName = stringNameNullable!.Value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
stringName = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static bool TryGetStringName(TaskTypes taskTypes, out StringNames stringName)
|
||||
{
|
||||
foreach (var provider in _providers)
|
||||
{
|
||||
if (provider.TryGetStringName(taskTypes, out var stringNameNullable))
|
||||
{
|
||||
stringName = stringNameNullable!.Value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
stringName = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static void OnLanguageChanged(SupportedLangs newLanguage)
|
||||
{
|
||||
foreach (var provider in _providers)
|
||||
{
|
||||
provider.SetLanguage(newLanguage);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
using Il2CppInterop.Runtime.InteropTypes.Arrays;
|
||||
using Reactor.Utilities;
|
||||
|
||||
namespace Reactor.Localization;
|
||||
|
||||
/// <summary>
|
||||
/// The required implementation of a localization provider class.
|
||||
/// </summary>
|
||||
public abstract class LocalizationProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the current language Among Us is set to.
|
||||
/// <br/>
|
||||
/// If used from <see cref="OnLanguageChanged"/>, this property will return the old language, not the new one.
|
||||
/// </summary>
|
||||
public SupportedLangs? CurrentLanguage { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the priority of this <see cref="LocalizationProvider"/>.
|
||||
/// The higher the priority is, the earlier it will be invoked in relation to other providers.
|
||||
/// <br/>
|
||||
/// You can use the <see cref="ReactorPriority"/> class for this value if you want to make this easier.
|
||||
/// </summary>
|
||||
public virtual int Priority => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the localized text for the given <see cref="StringNames"/>.
|
||||
/// </summary>
|
||||
/// <param name="stringName">The <see cref="StringNames"/> to localize.</param>
|
||||
/// <param name="result">The <see cref="string"/> representation of the given <see cref="StringNames"/>.</param>
|
||||
/// <returns>Whether or not this <see cref="LocalizationProvider"/> can handle this <see cref="StringNames"/>.</returns>
|
||||
public virtual bool TryGetText(StringNames stringName, out string? result)
|
||||
{
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the localized text for the given <see cref="StringNames"/>.
|
||||
/// </summary>
|
||||
/// <param name="stringName">The <see cref="StringNames"/> to localize.</param>
|
||||
/// <param name="parts">The arguments used for formatting.</param>
|
||||
/// <param name="result">The <see cref="string"/> representation of the given <see cref="StringNames"/>.</param>
|
||||
/// <returns>Whether or not this <see cref="LocalizationProvider"/> can handle this <see cref="StringNames"/>.</returns>
|
||||
public virtual bool TryGetTextFormatted(StringNames stringName, Il2CppReferenceArray<Il2CppSystem.Object> parts, out string? result)
|
||||
{
|
||||
if (!TryGetText(stringName, out result)) return false;
|
||||
|
||||
result = Il2CppSystem.String.Format(result, parts);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the <see cref="StringNames"/> equivalent for the given <see cref="SystemTypes"/>.
|
||||
/// </summary>
|
||||
/// <param name="systemType">The <see cref="SystemTypes"/> value.</param>
|
||||
/// <param name="result">The <see cref="string"/> representation of the given <see cref="StringNames"/>.</param>
|
||||
/// <returns>Whether or not this <see cref="LocalizationProvider"/> can handle this <see cref="StringNames"/>.</returns>
|
||||
public virtual bool TryGetStringName(SystemTypes systemType, out StringNames? result)
|
||||
{
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the <see cref="StringNames"/> equivalent for the given <see cref="TaskTypes"/>.
|
||||
/// </summary>
|
||||
/// <param name="taskType">The <see cref="TaskTypes"/> value.</param>
|
||||
/// <param name="result">The <see cref="string"/> representation of the given <see cref="StringNames"/>.</param>
|
||||
/// <returns>Whether or not this <see cref="LocalizationProvider"/> can handle this <see cref="StringNames"/>.</returns>
|
||||
public virtual bool TryGetStringName(TaskTypes taskType, out StringNames? result)
|
||||
{
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method is called when the Among Us language is changed by the user.
|
||||
/// </summary>
|
||||
/// <param name="newLanguage">The new language that Among Us has been set to.</param>
|
||||
public virtual void OnLanguageChanged(SupportedLangs newLanguage)
|
||||
{
|
||||
}
|
||||
|
||||
internal void SetLanguage(SupportedLangs newLanguage)
|
||||
{
|
||||
OnLanguageChanged(newLanguage);
|
||||
CurrentLanguage = newLanguage;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
using HarmonyLib;
|
||||
using Il2CppInterop.Runtime.InteropTypes.Arrays;
|
||||
|
||||
namespace Reactor.Localization.Patches;
|
||||
|
||||
[HarmonyPatch]
|
||||
internal static class GetStringPatch
|
||||
{
|
||||
[HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetString), typeof(StringNames), typeof(Il2CppReferenceArray<Il2CppSystem.Object>))]
|
||||
[HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetStringWithDefault), typeof(StringNames), typeof(string), typeof(Il2CppReferenceArray<Il2CppSystem.Object>))]
|
||||
[HarmonyPrefix]
|
||||
public static bool StringNamesPatch(StringNames id, Il2CppReferenceArray<Il2CppSystem.Object> parts, out string __result)
|
||||
{
|
||||
if (LocalizationManager.TryGetTextFormatted(id, parts, out __result))
|
||||
{
|
||||
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.GetString(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.GetString(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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using System.Collections.Generic;
|
||||
using Reactor.Utilities;
|
||||
|
||||
namespace Reactor.Localization.Providers;
|
||||
|
||||
/// <summary>
|
||||
/// Utility for adding hard-coded localization.
|
||||
/// </summary>
|
||||
public sealed class HardCodedLocalizationProvider : LocalizationProvider
|
||||
{
|
||||
private static readonly Dictionary<StringNames, string> _strings = new();
|
||||
|
||||
/// <summary>
|
||||
/// Adds a custom, hard-coded translation for a <see cref="StringNames"/>.
|
||||
/// </summary>
|
||||
/// <param name="stringName">The <see cref="StringNames"/>.</param>
|
||||
/// <param name="value">The text.</param>
|
||||
public static void Register(StringNames stringName, string value)
|
||||
{
|
||||
if (_strings.ContainsKey(stringName))
|
||||
{
|
||||
Warning($"Registering StringName {stringName} that already exists");
|
||||
}
|
||||
|
||||
_strings[stringName] = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int Priority => ReactorPriority.Low;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool TryGetText(StringNames stringName, out string? result)
|
||||
{
|
||||
return _strings.TryGetValue(stringName, out result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using Reactor.Localization.Providers;
|
||||
|
||||
namespace Reactor.Localization.Utilities;
|
||||
|
||||
/// <summary>
|
||||
/// Provides a way to use custom static <see cref="StringNames"/>.
|
||||
/// </summary>
|
||||
public static class CustomStringName
|
||||
{
|
||||
private static int _lastId = int.MinValue + 1;
|
||||
|
||||
/// <summary>
|
||||
/// Creates an returns a unique <see cref="StringNames"/> value.
|
||||
/// </summary>
|
||||
/// <returns>A unique <see cref="StringNames"/>.</returns>
|
||||
public static StringNames Create()
|
||||
{
|
||||
var id = _lastId++;
|
||||
return (StringNames) id;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates, registeres and returns a unique <see cref="StringNames"/> value.
|
||||
/// </summary>
|
||||
/// <param name="text">The text.</param>
|
||||
/// <returns>A unique <see cref="StringNames"/>.</returns>
|
||||
public static StringNames CreateAndRegister(string text)
|
||||
{
|
||||
var stringName = Create();
|
||||
HardCodedLocalizationProvider.Register(stringName, text);
|
||||
return stringName;
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,8 @@ using BepInEx.Configuration;
|
||||
using BepInEx.Unity.IL2CPP;
|
||||
using HarmonyLib;
|
||||
using Il2CppInterop.Runtime.Attributes;
|
||||
using Reactor.Localization;
|
||||
using Reactor.Localization.Providers;
|
||||
using Reactor.Networking;
|
||||
using Reactor.Networking.Attributes;
|
||||
using Reactor.Networking.Rpc;
|
||||
@@ -44,11 +46,15 @@ public partial class ReactorPlugin : BasePlugin
|
||||
{
|
||||
PluginSingleton<ReactorPlugin>.Instance = this;
|
||||
PluginSingleton<BasePlugin>.Initialize();
|
||||
|
||||
RegisterInIl2CppAttribute.Initialize();
|
||||
ModList.Initialize();
|
||||
|
||||
RegisterCustomRpcAttribute.Initialize();
|
||||
MessageConverterAttribute.Initialize();
|
||||
MethodRpcAttribute.Initialize();
|
||||
|
||||
LocalizationManager.Register(new HardCodedLocalizationProvider());
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
namespace Reactor.Utilities;
|
||||
|
||||
/// <summary>
|
||||
/// Class containing common priorities to be used in various places across Reactor.
|
||||
/// </summary>
|
||||
public static class ReactorPriority
|
||||
{
|
||||
/// <summary>
|
||||
/// Lowest priority, will happen last.
|
||||
/// </summary>
|
||||
public const int Last = -800;
|
||||
|
||||
/// <summary>
|
||||
/// Very low priority.
|
||||
/// </summary>
|
||||
public const int VeryLow = -600;
|
||||
|
||||
/// <summary>
|
||||
/// Low priority.
|
||||
/// </summary>
|
||||
public const int Low = -400;
|
||||
|
||||
/// <summary>
|
||||
/// Lower than normal priority.
|
||||
/// </summary>
|
||||
public const int LowerThanNormal = -200;
|
||||
|
||||
/// <summary>
|
||||
/// Normal priority.
|
||||
/// </summary>
|
||||
public const int Normal = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Higher than normal priority.
|
||||
/// </summary>
|
||||
public const int HigherThanNormal = 200;
|
||||
|
||||
/// <summary>
|
||||
/// High priority.
|
||||
/// </summary>
|
||||
public const int High = 400;
|
||||
|
||||
/// <summary>
|
||||
/// Very high priority.
|
||||
/// </summary>
|
||||
public const int VeryHigh = 600;
|
||||
|
||||
/// <summary>
|
||||
/// Highest priority, will happen first.
|
||||
/// </summary>
|
||||
public const int First = 800;
|
||||
}
|
||||
Reference in new issue
Block a user