using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("TABSArabic")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("TABSArabic")]
[assembly: AssemblyTitle("TABSArabic")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
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 TABSKorean
{
public static class KoreanLanguage
{
public const int LanguageIndex = 9;
public static bool Enabled { get; private set; }
public static void Enable()
{
Enabled = true;
}
public static void Disable()
{
Enabled = false;
}
}
[HarmonyPatch(typeof(GlobalSettingsHandler), "GetSettingsInstance", new Type[] { typeof(string) })]
internal static class GlobalSettingsHandler_GetSettingsInstance_Patch
{
private static void Postfix(string settingsKey, ref SettingsInstance __result)
{
if (__result != null && !(settingsKey != "VIDEO_LANGUAGE"))
{
AddKoreanOption(__result);
}
}
private static void AddKoreanOption(SettingsInstance settings)
{
if (settings.options == null)
{
Plugin.Log.LogWarning((object)"VIDEO_LANGUAGE has no options array.");
}
else
{
if (settings.options.Length > 9 && settings.options[9] == "Arabic")
{
return;
}
if (settings.options.Length > 9)
{
Plugin.Log.LogWarning((object)"VIDEO_LANGUAGE already has an option at index 9. Arabic option was not overwritten.");
return;
}
string[] array = new string[10];
for (int i = 0; i < settings.options.Length; i++)
{
array[i] = settings.options[i];
}
array[9] = "Arabic";
settings.options = array;
Plugin.Log.LogInfo((object)"Added Arabic language option to VIDEO_LANGUAGE.");
}
}
}
internal static class KoreanLanguageSwitchPath
{
public const int LanguageIndex = 9;
public static bool Enabled { get; private set; }
public static void Enable()
{
Enabled = true;
}
public static void Disable()
{
Enabled = false;
}
}
[HarmonyPatch(typeof(Localizer), "SetLanguage")]
internal static class Localizer_SetLanguage_Patch
{
private static readonly FieldInfo CallbacksField;
private static bool Prefix(Language lang)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Expected I4, but got Unknown
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Invalid comparison between Unknown and I4
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Expected I4, but got Unknown
Plugin.Log.LogInfo((object)$"Localizer.SetLanguage called: {(int)lang}");
if ((int)lang == 9)
{
KoreanLanguage.Enable();
SetKoreanCulture();
RefreshLocalization();
Plugin.Log.LogInfo((object)"Korean language enabled.");
return false;
}
KoreanLanguage.Disable();
Plugin.Log.LogInfo((object)$"Arabic language disabled. Using TABS language {(int)lang}.");
return true;
}
private static void SetKoreanCulture()
{
try
{
CultureInfo cultureInfo = CultureInfo.GetCultureInfo("ar-AR");
Thread.CurrentThread.CurrentCulture = cultureInfo;
Thread.CurrentThread.CurrentUICulture = cultureInfo;
}
catch (CultureNotFoundException)
{
Plugin.Log.LogWarning((object)"Could not set Arabic culture.");
}
}
private static void RefreshLocalization()
{
if (CallbacksField == null)
{
Plugin.Log.LogWarning((object)"Could not find Localizer.m_callbacks.");
return;
}
try
{
object value = CallbacksField.GetValue(null);
if (value == null)
{
Plugin.Log.LogWarning((object)"Localizer.m_callbacks is null.");
return;
}
if (!(value is IDictionary dictionary))
{
Plugin.Log.LogWarning((object)"Localizer.m_callbacks is not an IDictionary.");
return;
}
List<Delegate> list = new List<Delegate>();
foreach (DictionaryEntry item2 in dictionary)
{
if (item2.Value is Delegate item)
{
list.Add(item);
}
}
Plugin.Log.LogInfo((object)$"Refreshing {list.Count} localization callbacks.");
foreach (Delegate item3 in list)
{
try
{
item3.DynamicInvoke();
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("Localization callback failed: " + ex.Message));
}
}
}
catch (Exception ex2)
{
ManualLogSource log = Plugin.Log;
string text = "Failed to refresh localization: ";
log.LogError((object)(text + ex2));
}
}
static Localizer_SetLanguage_Patch()
{
CallbacksField = typeof(Localizer).GetField("m_callbacks", BindingFlags.Static | BindingFlags.NonPublic);
}
}
internal static class KoreanLocalization
{
private static readonly Dictionary<string, string> Translations = new Dictionary<string, string>(StringComparer.Ordinal);
private static string FilePath;
public static int Count => Translations.Count;
public static void Initialize()
{
try
{
string? directoryName = Path.GetDirectoryName(typeof(KoreanLocalization).Assembly.Location);
FilePath = Path.Combine(directoryName, "Localization", "tabs_ar.txt");
LoadFile(FilePath);
ApplyArabicFont(directoryName);
}
catch (Exception arg)
{
Plugin.Log.LogError((object)$"Failed to initialize Arabic localization: {arg}");
}
}
private static void LoadFile(string path)
{
Translations.Clear();
if (!File.Exists(path))
{
Plugin.Log.LogError((object)"Arabic localization file was not found.");
Plugin.Log.LogError((object)("Expected path: " + path));
return;
}
string[] array = File.ReadAllLines(path, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
int num = 0;
int num2 = 0;
string[] array2 = array;
foreach (string text in array2)
{
string text2 = text.Trim();
if (string.IsNullOrEmpty(text2) || text2.StartsWith("#"))
{
continue;
}
int num3 = text2.IndexOf('=');
if (num3 <= 0)
{
num2++;
Plugin.Log.LogWarning((object)("Invalid localization line: " + text));
continue;
}
string text3 = text2.Substring(0, num3).Trim();
string text4 = text2.Substring(num3 + 1);
if (string.IsNullOrEmpty(text3))
{
num2++;
continue;
}
if (IsMenuKey(text3) && !text4.Contains("<size="))
{
text4 = "<size=130%>" + text4 + "</size>";
}
Translations[text3] = text4;
num++;
}
Plugin.Log.LogInfo((object)$"Arabic localization loaded: {num} entries.");
if (num2 > 0)
{
Plugin.Log.LogWarning((object)$"Skipped {num2} invalid localization lines.");
}
}
public static bool TryGet(string key, out string value)
{
return Translations.TryGetValue(key, out value);
}
public static string Translate(string phraseID, string[] args)
{
if (string.IsNullOrEmpty(phraseID))
{
return phraseID;
}
if (!TryGet(phraseID, out var value))
{
return null;
}
value = ResolveNestedLocalization(value);
if (args != null && args.Length != 0)
{
string[] array = new string[args.Length];
for (int i = 0; i < args.Length; i++)
{
array[i] = args[i];
if (!string.IsNullOrEmpty(array[i]) && array[i].Length > 1 && array[i][0] == '$')
{
string text = Translate(array[i].Substring(1), null);
if (text != null)
{
array[i] = text;
}
}
}
try
{
string format = value;
object[] args2 = array;
value = string.Format(format, args2);
}
catch (FormatException)
{
Plugin.Log.LogWarning((object)("Invalid format string for key: " + phraseID));
}
}
return value;
}
private static string ResolveNestedLocalization(string text)
{
if (string.IsNullOrEmpty(text))
{
return text;
}
for (int i = 0; i < 32; i++)
{
int num = text.IndexOf('$');
if (num < 0)
{
break;
}
int num2 = text.IndexOf('$', num + 1);
if (num2 < 0)
{
break;
}
string text2 = text.Substring(num + 1, num2 - num - 1);
if (string.IsNullOrEmpty(text2) || !TryGet(text2, out var value))
{
break;
}
value = ResolveNestedLocalization(value);
text = text.Replace(text.Substring(num, num2 - num + 1), value);
}
return text;
}
private static bool IsMenuKey(string key)
{
string[] array = new string[17]
{
"MENU_", "BUTTON_", "TITLE_", "SETTINGS_", "VIDEO_", "AUDIO_", "GAMEPLAY_", "CONTROLS_", "POPUP_", "PAUSE_",
"MAIN_", "EXIT_", "QUIT_", "RESUME_", "RESTART_", "LOAD_", "SAVE_"
};
for (int i = 0; i < array.Length; i++)
{
if (key.StartsWith(array[i], StringComparison.Ordinal))
{
return true;
}
}
return false;
}
private static void ApplyArabicFont(string modDirectory)
{
string text = Path.Combine(modDirectory, "Fonts", "notoarabic_assets");
if (!File.Exists(text))
{
Plugin.Log.LogWarning((object)("Noto Sans Arabic AssetBundle not found: " + text));
Plugin.Log.LogWarning((object)"Create a TMP_FontAsset AssetBundle named 'notoarabic_assets' and place it in Fonts.");
return;
}
AssetBundle val = AssetBundle.LoadFromFile(text);
if ((Object)(object)val == (Object)null)
{
Plugin.Log.LogError((object)"Could not load Noto Sans Arabic AssetBundle.");
return;
}
TMP_FontAsset val2 = val.LoadAsset<TMP_FontAsset>("NotoSansArabic SDF");
if ((Object)(object)val2 == (Object)null)
{
val2 = val.LoadAsset<TMP_FontAsset>("NotoSansArabic");
}
if ((Object)(object)val2 == (Object)null)
{
Plugin.Log.LogError((object)"The AssetBundle does not contain a TMP_FontAsset named NotoSansArabic or NotoSansArabic SDF.");
return;
}
ApplyToScene(val2);
Plugin.Log.LogInfo((object)"Noto Sans Arabic font applied to the current UI.");
}
public static void ApplyToScene(TMP_FontAsset font)
{
TMP_Text[] array = Resources.FindObjectsOfTypeAll<TMP_Text>();
for (int i = 0; i < array.Length; i++)
{
if (!((Object)(object)array[i] == (Object)null) && !((Object)(object)((Component)array[i]).gameObject == (Object)null))
{
array[i].font = font;
if (IsMenuObject(((Component)array[i]).gameObject))
{
TMP_Text obj = array[i];
obj.fontSize *= 1.3f;
}
}
}
}
private static bool IsMenuObject(GameObject obj)
{
string text = ((Object)obj).name.ToLowerInvariant();
if (!text.Contains("menu") && !text.Contains("button") && !text.Contains("settings") && !text.Contains("popup") && !text.Contains("pause") && !text.Contains("options"))
{
return text.Contains("title");
}
return true;
}
}
[HarmonyPatch(typeof(Localizer), "GetSinglePhrase", new Type[]
{
typeof(string),
typeof(string[])
})]
internal static class Localizer_GetSinglePhrase_Patch
{
private static bool Prefix(string phraseID, string[] args, ref string __result)
{
if (!KoreanLanguage.Enabled)
{
return true;
}
string text = KoreanLocalization.Translate(phraseID, args);
if (text == null)
{
return true;
}
__result = text;
return false;
}
}
[BepInPlugin("com.anhyeongseop.tabs.arabic", "Arabic", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
public const string GUID = "com.anhyeongseop.tabs.arabic";
public const string NAME = "Arabic";
public const string VERSION = "1.0.0";
internal static ManualLogSource Log;
internal static Harmony HarmonyInstance;
private void Awake()
{
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
Log.LogInfo((object)"=================================");
Log.LogInfo((object)"TABS Arabic starting...");
Log.LogInfo((object)"=================================");
KoreanLocalization.Initialize();
HarmonyInstance = new Harmony("com.anhyeongseop.tabs.arabic");
HarmonyInstance.PatchAll();
Log.LogInfo((object)"Arabic loaded successfully.");
Log.LogInfo((object)$"Loaded Arabic strings: {KoreanLocalization.Count}");
}
private void OnDestroy()
{
if (HarmonyInstance != null)
{
HarmonyInstance.UnpatchSelf();
HarmonyInstance = null;
}
ManualLogSource log = Log;
if (log != null)
{
log.LogInfo((object)"Arabic unloaded.");
}
}
}
}