This repository has been archived by the owner on Sep 22, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathMoreLanguagesPlugin.cs
152 lines (131 loc) · 5.63 KB
/
MoreLanguagesPlugin.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Timberborn.Localization;
namespace MoreLanguages
{
[HarmonyPatch]
[BepInPlugin("com.timbercentral.morelanguages", "MoreLanguages", "MOD_VERSION_PLACEHOLDER")]
public class MoreLanguagesPlugin : BaseUnityPlugin
{
private static ConfigEntry<bool> _missingKeyLogging;
private void Awake()
{
_missingKeyLogging = Config.Bind("Logging", "MissingKeyLogging", false, "Log message when Loc doesn't have the given key in directory (devs only)");
Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly());
}
/// <summary>
/// Adds the new languages to the language selection box
/// </summary>
/// <param name="values"></param>
/// <returns></returns>
[HarmonyPostfix]
[HarmonyPatch(typeof(Timberborn.Localization.LocalizationService), "AvailableLanguages", MethodType.Getter)]
private static IEnumerable<LanguageInfo> AddNewTranslations(IEnumerable<LanguageInfo> values)
{
foreach (LanguageInfo languageInfo in values)
yield return languageInfo;
if (!Directory.Exists(LocalizationService.LangPath))
yield break;
foreach (string filePath in Directory.GetFiles(LocalizationService.LangPath).Where(path => !path.Contains("_names")))
{
string localizationCode = Path.GetFileNameWithoutExtension(filePath);
string displayName = LocalizationService.TryToReadRecords(localizationCode, filePath).SingleOrDefault(record => record.Id.Equals("Settings.Language.Name"))?.Text ?? Path.GetFileNameWithoutExtension(filePath);
yield return new LanguageInfo(localizationCode, displayName, false);
}
}
/// <summary>
/// Ignores the original code when it's a custom language preventing errors
/// </summary>
/// <param name="localizationKey"></param>
/// <param name="__result"></param>
/// <returns></returns>
[HarmonyPrefix]
[HarmonyPatch(typeof(LocalizationRepository), "GetLocalization", typeof(string), typeof(bool))]
private static bool IgnoreOriginalWithNewLanguages(string localizationKey, ref Dictionary<string, string> __result)
{
if (GetFieldValuesFromStatic(typeof(LocalizationCodes)).ContainsValue(localizationKey))
return true;
__result = LocalizationService.GetLocalization(localizationKey);
return false;
}
/// <summary>
/// Ignores the original code when it's a custom language preventing errors
/// </summary>
/// <param name="languageName"></param>
/// <param name="__instance"></param>
/// <param name="____localizationRepository"></param>
/// <param name="____loc"></param>
/// <returns></returns>
[HarmonyPrefix]
[HarmonyPatch(typeof(Timberborn.Localization.LocalizationService), "Load", typeof(string))]
[SuppressMessage("Member Access", "Publicizer001:Accessing a member that was not originally public")]
private static bool IgnoreOriginalWithNewLanguagesLoad(string localizationCode, Timberborn.Localization.LocalizationService __instance, LocalizationRepository ____localizationRepository, ILoc ____loc)
{
if (GetFieldValuesFromStatic(typeof(LocalizationCodes)).ContainsValue(localizationCode))
return true;
__instance.CurrentLanguage = localizationCode;
____loc.Initialize(____localizationRepository.GetLocalization(localizationCode));
return false;
}
/// <summary>
/// Patch to ignore the debugging warning when localization is missing. Keeps console cleaner with experimental items.
/// </summary>
[HarmonyPatch(typeof(Loc), "T", typeof(string))]
public static class PatchLocKeyLogging
{
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
if (_missingKeyLogging.Value)
return instructions;
var foundMassUsageMethod = false;
int startIndex = -1;
int endIndex = -1;
List<CodeInstruction> codes = new (instructions);
for (var i = 0; i < codes.Count; i++)
{
if (codes[i].opcode != OpCodes.Ret)
continue;
if (foundMassUsageMethod)
{
endIndex = i; // include current 'ret'
break;
}
startIndex = i + 1; // exclude current 'ret'
for (int j = startIndex; j < codes.Count; j++)
{
if (codes[j].opcode == OpCodes.Ret)
break;
var strOperand = codes[j].operand as string;
if (strOperand != "The given key ")
continue;
foundMassUsageMethod = true;
break;
}
}
if (startIndex > -1 && endIndex > -1)
codes.RemoveRange(startIndex + 1, endIndex - startIndex - 1);
return codes.AsEnumerable();
}
}
/// <summary>
/// Get all properties key, values from given static class
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
private static Dictionary<string, string> GetFieldValuesFromStatic(IReflect type)
{
return type
.GetFields(BindingFlags.Static | BindingFlags.Public)
.Where(f => f.FieldType == typeof(string))
.ToDictionary(f => f.Name,
f => (string) f.GetValue(null));
}
}
}