using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.Json;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using Il2CppInterop.Runtime.Injection;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Localization;
using UnityEngine.Localization.Settings;
using UnityEngine.Localization.Tables;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("TranslationFix")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("TranslationFix")]
[assembly: AssemblyTitle("TranslationFix")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace TranslationFix
{
[BepInPlugin("com.custom.translationfix", "Custom Character Translation Fix", "3.1.0")]
public class TranslationFixPlugin : BasePlugin
{
internal static ManualLogSource Logger;
public override void Load()
{
Logger = ((BasePlugin)this).Log;
ClassInjector.RegisterTypeInIl2Cpp<TranslationFixRunner>();
((BasePlugin)this).AddComponent<TranslationFixRunner>();
((BasePlugin)this).Log.LogInfo((object)"Custom Character Translation Fix 3.1.0 loaded.");
}
}
public class TranslationFixRunner : MonoBehaviour
{
private const string TableName = "Main Menu";
private static readonly Regex CustomKey = new Regex("^\\d{6,}\\.", RegexOptions.Compiled);
private static readonly Dictionary<string, (string section, string field)> Fields = new Dictionary<string, (string, string)>
{
{
"characterName",
("character", "characterName")
},
{
"characterDescription",
("character", "characterDescription")
},
{
"weaponName",
("weapon", "weaponName")
},
{
"weaponDescription",
("weapon", "weaponDescription")
},
{
"passiveName",
("passive", "passiveName")
},
{
"passiveDescription",
("passive", "passiveDescription")
}
};
private Dictionary<string, string> _values;
private readonly HashSet<string> _reported = new HashSet<string>();
private float _nextRun;
private int _totalFixed;
private bool _loggedError;
public TranslationFixRunner(IntPtr ptr)
: base(ptr)
{
}
private void Update()
{
if (Time.unscaledTime < _nextRun)
{
return;
}
_nextRun = Time.unscaledTime + 1.5f;
try
{
Fix();
}
catch (Exception ex)
{
if (!_loggedError)
{
_loggedError = true;
TranslationFixPlugin.Logger.LogWarning((object)("Translation fix failed: " + ex));
}
}
}
private void LoadJsonValues()
{
_values = new Dictionary<string, string>();
string[] files = Directory.GetFiles(Paths.BepInExRootPath, "*.custom.json", SearchOption.AllDirectories);
TranslationFixPlugin.Logger.LogInfo((object)("Found " + files.Length + " .custom.json file(s)."));
string[] array = files;
foreach (string text in array)
{
try
{
using JsonDocument jsonDocument = JsonDocument.Parse(File.ReadAllText(text), new JsonDocumentOptions
{
AllowTrailingCommas = true
});
JsonElement rootElement = jsonDocument.RootElement;
if (!rootElement.TryGetProperty("character", out var value) || !value.TryGetProperty("eCharacter", out var value2))
{
continue;
}
long @int = value2.GetInt64();
foreach (KeyValuePair<string, (string, string)> field in Fields)
{
if (rootElement.TryGetProperty(field.Value.Item1, out var value3) && value3.TryGetProperty(field.Value.Item2, out var value4) && value4.ValueKind == JsonValueKind.String)
{
_values[@int + "." + field.Key] = value4.GetString();
}
}
if (rootElement.TryGetProperty("skins", out var value5) && value5.ValueKind == JsonValueKind.Array)
{
int num = 0;
foreach (JsonElement item in value5.EnumerateArray())
{
num++;
JsonElement value7;
string value6 = ((item.TryGetProperty("skinName", out value7) && value7.ValueKind == JsonValueKind.String) ? value7.GetString() : null);
JsonElement value8;
string text2 = ((item.TryGetProperty("description", out value8) && value8.ValueKind == JsonValueKind.String) ? value8.GetString() : null);
if (!string.IsNullOrEmpty(value6))
{
_values[@int + ".skinName" + num] = value6;
}
_values[@int + ".skinDescription" + num] = (string.IsNullOrEmpty(text2) ? " " : text2);
}
}
TranslationFixPlugin.Logger.LogInfo((object)("Read texts for character id " + @int + " from " + Path.GetFileName(text)));
}
catch (Exception ex)
{
TranslationFixPlugin.Logger.LogWarning((object)("Could not read " + text + ": " + ex.Message));
}
}
}
private void Fix()
{
if (!LocalizationSettings.HasSettings || !LocalizationSettings.InitializationOperation.IsDone)
{
return;
}
if (_values == null)
{
LoadJsonValues();
}
List<Locale> locales = LocalizationSettings.AvailableLocales.Locales;
LocalizedStringDatabase stringDatabase = LocalizationSettings.StringDatabase;
TableReference val = TableReference.TableReferenceFromString("Main Menu");
List<StringTable> list = new List<StringTable>();
for (int i = 0; i < locales.Count; i++)
{
StringTable table = ((LocalizedDatabase<StringTable, StringTableEntry>)(object)stringDatabase).GetTable(val, locales[i]);
if ((Object)(object)table != (Object)null)
{
list.Add(table);
}
}
if (list.Count == 0)
{
return;
}
List<SharedTableEntry> entries = ((LocalizationTable)list[0]).SharedData.Entries;
int num = 0;
for (int j = 0; j < entries.Count; j++)
{
string key = entries[j].Key;
if (string.IsNullOrEmpty(key) || !CustomKey.IsMatch(key))
{
continue;
}
string value = null;
for (int k = 0; k < list.Count; k++)
{
if (value != null)
{
break;
}
StringTableEntry entry = ((DetailedLocalizationTable<StringTableEntry>)(object)list[k]).GetEntry(key);
if (entry != null && !string.IsNullOrEmpty(entry.Value))
{
value = entry.Value;
}
}
if (value == null)
{
_values.TryGetValue(key, out value);
}
if (value == null)
{
if (_reported.Add(key))
{
TranslationFixPlugin.Logger.LogWarning((object)("No text known for key '" + key + "' (not in any language, not in the JSON files)."));
}
continue;
}
for (int l = 0; l < list.Count; l++)
{
StringTableEntry entry2 = ((DetailedLocalizationTable<StringTableEntry>)(object)list[l]).GetEntry(key);
if (entry2 == null || string.IsNullOrEmpty(entry2.Value))
{
((DetailedLocalizationTable<StringTableEntry>)(object)list[l]).AddEntry(key, value);
num++;
}
}
}
if (num > 0)
{
_totalFixed += num;
TranslationFixPlugin.Logger.LogInfo((object)("Filled " + num + " missing entries across " + list.Count + " language table(s) (total " + _totalFixed + ")."));
}
}
}
}