using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Localization;
using UnityEngine.Localization.Components;
using UnityEngine.Localization.Metadata;
using UnityEngine.Localization.Settings;
using UnityEngine.Localization.Tables;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.SceneManagement;
using UnityEngine.TextCore.LowLevel;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("MegabonkArabic")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.2.0.0")]
[assembly: AssemblyInformationalVersion("1.2.0")]
[assembly: AssemblyProduct("MegabonkArabic")]
[assembly: AssemblyTitle("MegabonkArabic")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.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 MegabonkArabic
{
internal static class ArabicLocale
{
public const string Code = "ar";
public const string DisplayName = "العربية";
private static Locale _arabic;
private static Locale _english;
private static bool _failed;
private static bool _started;
private static float _nextScan;
private static LanguageWindow _window;
private static SelectionGroupToggleSingleButton _englishRow;
private static bool _englishRowArmed;
private static readonly Dictionary<IntPtr, (StringTable Table, Dictionary<long, string> English)> Swapped = new Dictionary<IntPtr, (StringTable, Dictionary<long, string>)>();
public static bool Active { get; private set; }
public static void Tick()
{
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: Expected O, but got Unknown
if (_failed)
{
return;
}
try
{
if ((Object)(object)_arabic == (Object)null && !Register())
{
return;
}
TrackSelection();
WatchEnglishRow();
if (Active && Time.realtimeSinceStartup < 20f && SwapInNewTables() > 0)
{
RefreshGameText();
}
if (!(Time.unscaledTime < _nextScan))
{
_nextScan = Time.unscaledTime + 0.5f;
if (Active && SwapInNewTables() > 0)
{
RefreshGameText();
}
UpdateLanguageLabels();
}
}
catch (Exception ex)
{
_failed = true;
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(30, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Arabic language setup failed: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
}
logger.LogError(val);
}
}
private static bool Register()
{
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Expected O, but got Unknown
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Expected O, but got Unknown
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Expected O, but got Unknown
//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
AsyncOperationHandle<LocalizationSettings> initializationOperation = LocalizationSettings.InitializationOperation;
if (!initializationOperation.IsValid() || !initializationOperation.IsDone)
{
return false;
}
ILocalesProvider availableLocales = LocalizationSettings.AvailableLocales;
_english = ((availableLocales != null) ? availableLocales.GetLocale(new LocaleIdentifier("en")) : null);
if ((Object)(object)_english == (Object)null)
{
return false;
}
Locale locale = availableLocales.GetLocale(new LocaleIdentifier("ar"));
if ((Object)(object)locale != (Object)null)
{
_arabic = locale;
return true;
}
Locale val = Locale.CreateLocale(new LocaleIdentifier("ar"));
((Object)val).name = "Arabic (ar)";
val.LocaleName = "العربية";
((Object)val).hideFlags = (HideFlags)61;
Object.DontDestroyOnLoad((Object)(object)val);
val.Metadata.AddMetadata(((Il2CppObjectBase)new FallbackLocale(_english)).Cast<IMetadata>());
availableLocales.AddLocale(val);
_arabic = val;
Plugin.Logger.LogInfo((object)"Arabic added to the language list.");
return true;
}
private static void TrackSelection()
{
Locale selectedLocale = LocalizationSettings.SelectedLocale;
if ((Object)(object)selectedLocale == (Object)null)
{
return;
}
string code = selectedLocale.Identifier.Code;
if (!_started)
{
if (!(Time.realtimeSinceStartup < 30f) || !(code != "en") || !(code != "ar"))
{
_started = true;
if (code == "ar" || (code == "en" && Plugin.LastLanguageArabic.Value))
{
SetActive(active: true);
}
if (code == "ar")
{
SelectGameLanguage(_english);
}
}
}
else if (code == "ar")
{
SelectGameLanguage(_english);
SetActive(active: true);
}
else if (code != "en" && Active)
{
SetActive(active: false);
}
}
private static void WatchEnglishRow()
{
if (Active && !((Object)(object)_englishRow == (Object)null) && _englishRowArmed)
{
if (!((Object)(object)_window != (Object)null) || !((Behaviour)_window).isActiveAndEnabled)
{
_englishRowArmed = false;
}
else if (_englishRow.isSelected)
{
SetActive(active: false);
}
}
}
private static void SetActive(bool active)
{
if (active == Active)
{
return;
}
Active = active;
Plugin.LastLanguageArabic.Value = active;
Plugin.Logger.LogInfo((object)(active ? "Arabic mode on" : "Arabic mode off"));
if (active)
{
SwapInNewTables();
}
else
{
RestoreEnglish();
try
{
SelectionGroupToggleSingle val = (((Object)(object)_window != (Object)null) ? _window.selectionGroup : null);
List<Locale> locales = LocalizationSettings.AvailableLocales.Locales;
if ((Object)(object)val != (Object)null)
{
SelectionGroupToggleSingleButton button = val.GetButton(locales.IndexOf(_arabic));
if (button != null)
{
button.Deselect();
}
SelectionGroupToggleSingleButton button2 = val.GetButton(locales.IndexOf(_english));
if (button2 != null)
{
button2.Select();
}
}
}
catch
{
}
_englishRowArmed = false;
}
TextPatches.OnLanguageChanged(active);
RefreshGameText();
}
private static void RefreshGameText()
{
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_009e: Unknown result type (might be due to invalid IL or missing references)
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
TableSwapper.RefreshVisibleText();
Locale selectedLocale = LocalizationSettings.SelectedLocale;
Scene scene;
foreach (Object item in (Il2CppArrayBase<Object>)(object)Resources.FindObjectsOfTypeAll(Il2CppType.Of<MapEntry>()))
{
try
{
MapEntry val = ((Il2CppObjectBase)item).TryCast<MapEntry>();
if ((Object)(object)val != (Object)null)
{
scene = ((Component)val).gameObject.scene;
if (((Scene)(ref scene)).IsValid())
{
val.OnLocaleChanged(selectedLocale);
}
}
}
catch
{
}
}
foreach (Object item2 in (Il2CppArrayBase<Object>)(object)Resources.FindObjectsOfTypeAll(Il2CppType.Of<QuickQuestContainer>()))
{
try
{
QuickQuestContainer val2 = ((Il2CppObjectBase)item2).TryCast<QuickQuestContainer>();
if ((Object)(object)val2 != (Object)null)
{
scene = ((Component)val2).gameObject.scene;
if (((Scene)(ref scene)).IsValid())
{
val2.OnLocaleChanged(selectedLocale);
}
}
}
catch
{
}
}
}
private static void SelectGameLanguage(Locale locale)
{
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Expected O, but got Unknown
try
{
CurrentSettings instance = CurrentSettings.Instance;
int num = LocalizationSettings.AvailableLocales.Locales.IndexOf(locale);
if ((Object)(object)instance != (Object)null && num >= 0)
{
instance.UpdateLanguage(num);
return;
}
}
catch (Exception ex)
{
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExDebugLogInterpolatedStringHandler val = new BepInExDebugLogInterpolatedStringHandler(23, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Game language setting: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
}
logger.LogDebug(val);
}
LocalizationSettings.SelectedLocale = locale;
}
private static int SwapInNewTables()
{
int num = 0;
foreach (Object item in (Il2CppArrayBase<Object>)(object)Resources.FindObjectsOfTypeAll(Il2CppType.Of<StringTable>()))
{
StringTable val = ((Il2CppObjectBase)item).TryCast<StringTable>();
if ((Object)(object)val == (Object)null || Swapped.ContainsKey(((Il2CppObjectBase)val).Pointer) || ((LocalizationTable)val).LocaleIdentifier.Code != "en")
{
continue;
}
Dictionary<long, string> dictionary = new Dictionary<long, string>();
Swapped[((Il2CppObjectBase)val).Pointer] = (val, dictionary);
if (!Translations.TryGetTable(((LocalizationTable)val).TableCollectionName, out var table))
{
continue;
}
foreach (KeyValuePair<long, string> item2 in table)
{
item2.Deconstruct(out var key, out var value);
long num2 = key;
string value2 = value;
StringTableEntry entry = ((DetailedLocalizationTable<StringTableEntry>)(object)val).GetEntry(num2);
if (entry != null)
{
dictionary[num2] = entry.Value;
entry.Value = value2;
}
}
if (dictionary.Count > 0)
{
num++;
}
}
return num;
}
private static void RestoreEnglish()
{
foreach (var (val, dictionary) in Swapped.Values)
{
try
{
foreach (var (num2, value) in dictionary)
{
((DetailedLocalizationTable<StringTableEntry>)(object)val).GetEntry(num2).Value = value;
}
}
catch
{
}
}
Swapped.Clear();
}
private static void UpdateLanguageLabels()
{
foreach (Object item in (Il2CppArrayBase<Object>)(object)Object.FindObjectsOfType(Il2CppType.Of<LanguageButtonMenu>()))
{
LanguageButtonMenu obj = ((Il2CppObjectBase)item).TryCast<LanguageButtonMenu>();
TextMeshProUGUI val = ((obj != null) ? obj.languageText : null);
if (!((Object)(object)val == (Object)null))
{
bool flag = ArabicShaper.ContainsArabic(((TMP_Text)val).text);
if (Active && !flag)
{
((TMP_Text)val).text = "العربية";
}
else if (!Active && flag && (Object)(object)LocalizationSettings.SelectedLocale == (Object)(object)_english)
{
((TMP_Text)val).text = "English";
}
}
}
_window = null;
foreach (Object item2 in (Il2CppArrayBase<Object>)(object)Object.FindObjectsOfType(Il2CppType.Of<LanguageWindow>()))
{
LanguageWindow val2 = ((Il2CppObjectBase)item2).TryCast<LanguageWindow>();
if ((Object)(object)val2 == (Object)null)
{
continue;
}
_window = val2;
List<Locale> locales = LocalizationSettings.AvailableLocales.Locales;
int num = locales.IndexOf(_english);
int num2 = locales.IndexOf(_arabic);
SelectionGroupToggleSingle selectionGroup = val2.selectionGroup;
foreach (SelectionGroupToggleSingleButton componentsInChild in ((Component)val2).GetComponentsInChildren<SelectionGroupToggleSingleButton>(true))
{
foreach (TMP_Text componentsInChild2 in ((Component)componentsInChild).GetComponentsInChildren<TMP_Text>(true))
{
if (string.IsNullOrWhiteSpace(componentsInChild2.text))
{
componentsInChild2.text = "العربية";
}
}
}
if (!Active || (Object)(object)selectionGroup == (Object)null || num < 0)
{
continue;
}
_englishRow = selectionGroup.GetButton(num);
if (!_englishRowArmed && (Object)(object)_englishRow != (Object)null)
{
if (_englishRow.isSelected)
{
_englishRow.Deselect();
}
SelectionGroupToggleSingleButton obj2 = ((num2 >= 0) ? selectionGroup.GetButton(num2) : null);
if (obj2 != null)
{
obj2.Select();
}
_englishRowArmed = !_englishRow.isSelected;
}
}
}
}
internal static class ArabicShaper
{
private static readonly Dictionary<char, char[]> Forms = new Dictionary<char, char[]>
{
['ء'] = new char[4] { 'ﺀ', '\0', '\0', '\0' },
['آ'] = new char[4] { 'ﺁ', 'ﺂ', '\0', '\0' },
['أ'] = new char[4] { 'ﺃ', 'ﺄ', '\0', '\0' },
['ؤ'] = new char[4] { 'ﺅ', 'ﺆ', '\0', '\0' },
['إ'] = new char[4] { 'ﺇ', 'ﺈ', '\0', '\0' },
['ئ'] = new char[4] { 'ﺉ', 'ﺊ', 'ﺋ', 'ﺌ' },
['ا'] = new char[4] { 'ﺍ', 'ﺎ', '\0', '\0' },
['ب'] = new char[4] { 'ﺏ', 'ﺐ', 'ﺑ', 'ﺒ' },
['ة'] = new char[4] { 'ﺓ', 'ﺔ', '\0', '\0' },
['ت'] = new char[4] { 'ﺕ', 'ﺖ', 'ﺗ', 'ﺘ' },
['ث'] = new char[4] { 'ﺙ', 'ﺚ', 'ﺛ', 'ﺜ' },
['ج'] = new char[4] { 'ﺝ', 'ﺞ', 'ﺟ', 'ﺠ' },
['ح'] = new char[4] { 'ﺡ', 'ﺢ', 'ﺣ', 'ﺤ' },
['خ'] = new char[4] { 'ﺥ', 'ﺦ', 'ﺧ', 'ﺨ' },
['د'] = new char[4] { 'ﺩ', 'ﺪ', '\0', '\0' },
['ذ'] = new char[4] { 'ﺫ', 'ﺬ', '\0', '\0' },
['ر'] = new char[4] { 'ﺭ', 'ﺮ', '\0', '\0' },
['ز'] = new char[4] { 'ﺯ', 'ﺰ', '\0', '\0' },
['س'] = new char[4] { 'ﺱ', 'ﺲ', 'ﺳ', 'ﺴ' },
['ش'] = new char[4] { 'ﺵ', 'ﺶ', 'ﺷ', 'ﺸ' },
['ص'] = new char[4] { 'ﺹ', 'ﺺ', 'ﺻ', 'ﺼ' },
['ض'] = new char[4] { 'ﺽ', 'ﺾ', 'ﺿ', 'ﻀ' },
['ط'] = new char[4] { 'ﻁ', 'ﻂ', 'ﻃ', 'ﻄ' },
['ظ'] = new char[4] { 'ﻅ', 'ﻆ', 'ﻇ', 'ﻈ' },
['ع'] = new char[4] { 'ﻉ', 'ﻊ', 'ﻋ', 'ﻌ' },
['غ'] = new char[4] { 'ﻍ', 'ﻎ', 'ﻏ', 'ﻐ' },
['ـ'] = new char[4] { 'ـ', 'ـ', 'ـ', 'ـ' },
['ف'] = new char[4] { 'ﻑ', 'ﻒ', 'ﻓ', 'ﻔ' },
['ق'] = new char[4] { 'ﻕ', 'ﻖ', 'ﻗ', 'ﻘ' },
['ك'] = new char[4] { 'ﻙ', 'ﻚ', 'ﻛ', 'ﻜ' },
['ل'] = new char[4] { 'ﻝ', 'ﻞ', 'ﻟ', 'ﻠ' },
['م'] = new char[4] { 'ﻡ', 'ﻢ', 'ﻣ', 'ﻤ' },
['ن'] = new char[4] { 'ﻥ', 'ﻦ', 'ﻧ', 'ﻨ' },
['ه'] = new char[4] { 'ﻩ', 'ﻪ', 'ﻫ', 'ﻬ' },
['و'] = new char[4] { 'ﻭ', 'ﻮ', '\0', '\0' },
['ى'] = new char[4] { 'ﻯ', 'ﻰ', '\0', '\0' },
['ي'] = new char[4] { 'ﻱ', 'ﻲ', 'ﻳ', 'ﻴ' }
};
private static readonly Dictionary<char, (char Isolated, char Final)> LamAlef = new Dictionary<char, (char, char)>
{
['آ'] = ('ﻵ', 'ﻶ'),
['أ'] = ('ﻷ', 'ﻸ'),
['إ'] = ('ﻹ', 'ﻺ'),
['ا'] = ('ﻻ', 'ﻼ')
};
private const char Lam = 'ل';
public static bool NeedsShaping(string s)
{
if (string.IsNullOrEmpty(s))
{
return false;
}
foreach (char c in s)
{
if (c >= 'ء' && c <= 'ي')
{
return true;
}
}
return false;
}
public static bool ContainsArabic(string s)
{
if (string.IsNullOrEmpty(s))
{
return false;
}
foreach (char c in s)
{
if ((c >= '\u0600' && c <= 'ۿ') || (c >= 'ﹰ' && c <= '\ufeff'))
{
return true;
}
}
return false;
}
public static string Shape(string s)
{
bool[] tag = MarkTags(s);
string s2 = JoinLetters(s, tag);
return FixDirection(s2, MarkTags(s2));
}
private static string JoinLetters(string s, bool[] tag)
{
StringBuilder stringBuilder = new StringBuilder(s.Length);
for (int i = 0; i < s.Length; i++)
{
char c = s[i];
if (tag[i] || !Forms.TryGetValue(c, out var value))
{
stringBuilder.Append(c);
continue;
}
int num = Neighbour(s, tag, i, -1);
int num2 = Neighbour(s, tag, i, 1);
bool flag = num >= 0 && JoinsForward(s[num]);
if (c == 'ل' && num2 >= 0 && LamAlef.TryGetValue(s[num2], out (char, char) value2) && OnlyTransparentBetween(s, tag, i, num2))
{
stringBuilder.Append(flag ? value2.Item2 : value2.Item1);
for (int j = i + 1; j < num2; j++)
{
stringBuilder.Append(s[j]);
}
i = num2;
}
else
{
bool num3 = num2 >= 0 && JoinsBackward(s[num2]);
bool flag2 = flag && value[1] != '\0';
bool flag3 = num3 && value[2] != '\0';
char value3 = ((flag2 && flag3 && value[3] != 0) ? value[3] : (flag2 ? value[1] : (flag3 ? value[2] : value[0])));
stringBuilder.Append(value3);
}
}
return stringBuilder.ToString();
}
private static bool JoinsForward(char c)
{
if (Forms.TryGetValue(c, out var value))
{
return value[2] != '\0';
}
return false;
}
private static bool JoinsBackward(char c)
{
if (Forms.TryGetValue(c, out var value))
{
return value[1] != '\0';
}
return false;
}
private static bool IsTransparent(char c)
{
if (c < '\u064b' || c > '\u065f')
{
return c == '\u0670';
}
return true;
}
private static int Neighbour(string s, bool[] tag, int i, int step)
{
for (int j = i + step; j >= 0 && j < s.Length; j += step)
{
if (!tag[j] && !IsTransparent(s[j]))
{
return j;
}
}
return -1;
}
private static bool OnlyTransparentBetween(string s, bool[] tag, int a, int b)
{
for (int i = a + 1; i < b; i++)
{
if (!tag[i] && !IsTransparent(s[i]))
{
return false;
}
}
return true;
}
private static string FixDirection(string s, bool[] tag)
{
char[] array = s.ToCharArray();
int num = 0;
while (num < array.Length)
{
if (tag[num])
{
num++;
}
else if (IsRunChar(array, num))
{
int num2 = num;
for (int i = num + 1; i < array.Length && !tag[i] && !IsRtl(array[i]) && array[i] != '\n'; i++)
{
if (IsRunChar(array, i))
{
num2 = i;
}
}
Array.Reverse(array, num, num2 - num + 1);
num = num2 + 1;
}
else
{
array[num] = Mirror(array[num]);
num++;
}
}
return new string(array);
}
private static bool IsNumberAffix(char c)
{
switch (c)
{
case '%':
case '+':
case '-':
case '٪':
return true;
default:
return false;
}
}
private static bool IsRunChar(char[] chars, int i)
{
char c = chars[i];
if (IsLtrStrong(c))
{
return true;
}
if (!IsNumberAffix(c))
{
return false;
}
bool num = i > 0 && chars[i - 1] >= '0' && chars[i - 1] <= '9';
bool flag = i + 1 < chars.Length && chars[i + 1] >= '0' && chars[i + 1] <= '9';
return num || flag;
}
private static bool IsRtl(char c)
{
if (c < '\u0600' || c > 'ۿ')
{
if (c >= 'ﹰ')
{
return c <= '\ufeff';
}
return false;
}
return true;
}
private static bool IsLtrStrong(char c)
{
if ((c < '0' || c > '9') && (c < 'A' || c > 'Z') && (c < 'a' || c > 'z'))
{
if (c >= 'À')
{
return c <= 'ɏ';
}
return false;
}
return true;
}
private static char Mirror(char c)
{
return c switch
{
'(' => ')',
')' => '(',
'[' => ']',
']' => '[',
'{' => '}',
'}' => '{',
'«' => '»',
'»' => '«',
_ => c,
};
}
private static bool[] MarkTags(string s)
{
bool[] array = new bool[s.Length];
for (int i = 0; i < s.Length; i++)
{
if (s[i] != '<' || i + 1 >= s.Length)
{
continue;
}
char c = s[i + 1];
if ((!char.IsLetter(c) || c >= '\u0080') && c != '/' && c != '#')
{
continue;
}
int num = s.IndexOf('>', i + 1);
if (num >= 0 && num - i <= 80 && s.IndexOf('<', i + 1, num - i - 1) < 0)
{
for (int j = i; j <= num; j++)
{
array[j] = true;
}
i = num;
}
}
return array;
}
}
internal static class FontInstaller
{
private static TMP_FontAsset _arabic;
private static bool _failed;
private static readonly HashSet<IntPtr> Patched = new HashSet<IntPtr>();
private static bool _refreshAfterInstall;
public static void Tick()
{
if (_failed)
{
return;
}
if ((Object)(object)_arabic == (Object)null)
{
if (!Create())
{
return;
}
_refreshAfterInstall = true;
}
List<TMP_FontAsset> fallbackFontAssets = TMP_Settings.fallbackFontAssets;
if (fallbackFontAssets != null && !fallbackFontAssets.Contains(_arabic))
{
fallbackFontAssets.Add(_arabic);
}
foreach (Object item in (Il2CppArrayBase<Object>)(object)Resources.FindObjectsOfTypeAll(Il2CppType.Of<TMP_FontAsset>()))
{
TMP_FontAsset val = ((Il2CppObjectBase)item).TryCast<TMP_FontAsset>();
if (!((Object)(object)val == (Object)null) && !(((Il2CppObjectBase)val).Pointer == ((Il2CppObjectBase)_arabic).Pointer) && !Patched.Contains(((Il2CppObjectBase)val).Pointer))
{
Patched.Add(((Il2CppObjectBase)val).Pointer);
List<TMP_FontAsset> val2 = val.fallbackFontAssetTable;
if (val2 == null)
{
val2 = (val.fallbackFontAssetTable = new List<TMP_FontAsset>());
}
if (!val2.Contains(_arabic))
{
val2.Insert(0, _arabic);
}
}
}
if (_refreshAfterInstall)
{
_refreshAfterInstall = false;
RefreshArabicLabels();
}
}
private static bool Create()
{
//IL_011e: Unknown result type (might be due to invalid IL or missing references)
//IL_0125: Expected O, but got Unknown
//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
//IL_00ee: Expected O, but got Unknown
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00a6: Expected O, but got Unknown
string[] array = Plugin.FontFiles.Value.Split(';', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
string text2 = default(string);
bool flag = default(bool);
bool flag2 = default(bool);
foreach (string text in array)
{
if (!File.Exists(text))
{
continue;
}
try
{
TMP_FontAsset val = TMP_FontAsset.CreateFontAsset(text, 0, 72, 7, (GlyphRenderMode)4165, 2048, 2048, (AtlasPopulationMode)1, true);
if ((Object)(object)val == (Object)null)
{
continue;
}
((Object)val).name = "Arabic (" + Path.GetFileNameWithoutExtension(text) + ")";
((Object)val).hideFlags = (HideFlags)61;
Object.DontDestroyOnLoad((Object)(object)val);
val.TryAddCharacters(AllArabicCharacters(), ref text2, false);
if (!string.IsNullOrEmpty(text2))
{
ManualLogSource logger = Plugin.Logger;
BepInExDebugLogInterpolatedStringHandler val2 = new BepInExDebugLogInterpolatedStringHandler(30, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Font lacks ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(text2.Length);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" Arabic characters.");
}
logger.LogDebug(val2);
}
_arabic = val;
ManualLogSource logger2 = Plugin.Logger;
BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(19, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Arabic font ready: ");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(text);
}
logger2.LogInfo(val3);
flag = true;
return flag;
}
catch (Exception ex)
{
ManualLogSource logger3 = Plugin.Logger;
BepInExWarningLogInterpolatedStringHandler val4 = new BepInExWarningLogInterpolatedStringHandler(22, 2, ref flag2);
if (flag2)
{
((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("Could not load font ");
((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(text);
((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(": ");
((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(ex.Message);
}
logger3.LogWarning(val4);
}
}
_failed = true;
Plugin.Logger.LogError((object)"No Arabic font could be loaded. Set [Font] FontFiles in the config to an Arabic .ttf file.");
return false;
}
private static string AllArabicCharacters()
{
StringBuilder stringBuilder = new StringBuilder();
for (char c = 'ﹰ'; c <= 'ﻼ'; c = (char)(c + 1))
{
stringBuilder.Append(c);
}
for (char c2 = '\u0600'; c2 <= 'ۿ'; c2 = (char)(c2 + 1))
{
stringBuilder.Append(c2);
}
stringBuilder.Append("0123456789 .,:;!?%/+-()[]«»…");
return stringBuilder.ToString();
}
public static void RefreshArabicLabels()
{
foreach (Object item in (Il2CppArrayBase<Object>)(object)Resources.FindObjectsOfTypeAll(Il2CppType.Of<TMP_Text>()))
{
try
{
TMP_Text val = ((Il2CppObjectBase)item).TryCast<TMP_Text>();
if (!((Object)(object)val == (Object)null) && ((Behaviour)val).isActiveAndEnabled && ArabicShaper.ContainsArabic(val.text))
{
val.ForceMeshUpdate(true, true);
}
}
catch
{
}
}
}
}
[BepInPlugin("arabic.megabonk", "Megabonk Arabic", "1.2.0")]
public class Plugin : BasePlugin
{
public const string Guid = "arabic.megabonk";
public const string Name = "Megabonk Arabic";
public const string Version = "1.2.0";
internal static ManualLogSource Logger;
internal static ConfigEntry<bool> Enabled;
internal static ConfigEntry<string> ReplaceLocale;
internal static ConfigEntry<bool> LastLanguageArabic;
internal static ConfigEntry<bool> CheckForUpdates;
internal static UpdateChecker Updates;
internal const bool Verbose = false;
internal static ConfigEntry<string> FontFiles;
internal static ConfigEntry<bool> RightAlign;
internal static ConfigEntry<bool> DebugNoTextHook;
internal static ConfigEntry<bool> DebugNoSkinHook;
internal static ConfigEntry<bool> DebugNoTables;
internal static ConfigEntry<bool> DebugNoFont;
internal static ConfigEntry<bool> DebugNoPopupWords;
internal static bool ReplaceMode => !string.IsNullOrWhiteSpace(ReplaceLocale.Value);
internal static bool ArabicOn
{
get
{
if (!ReplaceMode)
{
return ArabicLocale.Active;
}
return true;
}
}
internal static string Visual(string s)
{
char[] array = ArabicShaper.Shape(s ?? "").ToCharArray();
Array.Reverse(array);
return new string(array);
}
public override void Load()
{
//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
//IL_01c4: Expected O, but got Unknown
//IL_018a: Unknown result type (might be due to invalid IL or missing references)
//IL_0190: Expected O, but got Unknown
//IL_024c: Unknown result type (might be due to invalid IL or missing references)
//IL_0252: Expected O, but got Unknown
Logger = ((BasePlugin)this).Log;
Enabled = ((BasePlugin)this).Config.Bind<bool>("General", "Enabled", true, "Turn the Arabic translation on or off.");
ReplaceLocale = ((BasePlugin)this).Config.Bind<string>("General", "ReplaceLanguageInstead", "", "Leave empty: Arabic is added to the game's language list as its own language. Or put a language code (e.g. en) to replace that language with Arabic instead, the old way.");
LastLanguageArabic = ((BasePlugin)this).Config.Bind<bool>("State", "ArabicSelected", false, "Remembers that you picked Arabic. Set automatically.");
CheckForUpdates = ((BasePlugin)this).Config.Bind<bool>("General", "CheckForUpdates", true, "Once per launch, ask Nexus if a newer Megabonk Arabic is out and show a small notice in the menus. Nothing is downloaded.");
FontFiles = ((BasePlugin)this).Config.Bind<string>("Font", "FontFiles", "C:\\Windows\\Fonts\\segoeuib.ttf;C:\\Windows\\Fonts\\tahomabd.ttf;C:\\Windows\\Fonts\\arialbd.ttf", "Arabic font files to try, in order (separated by ;). The first one that exists is used.");
RightAlign = ((BasePlugin)this).Config.Bind<bool>("Layout", "MoveLeftAlignedTextRight", false, "Move left-aligned Arabic text to the right edge. Off by default: many window titles have corner decorations on the right, so moving text there clips it. Arabic stays readable in the game's original layout.");
DebugNoTextHook = ((BasePlugin)this).Config.Bind<bool>("Troubleshooting", "DisableTextShaping", false, "Turn off Arabic letter joining / right-to-left on game text.");
DebugNoSkinHook = ((BasePlugin)this).Config.Bind<bool>("Troubleshooting", "DisableSkinNameOrder", false, "Turn off the skin-name word order fix.");
DebugNoTables = ((BasePlugin)this).Config.Bind<bool>("Troubleshooting", "DisableTranslation", false, "Keep the game's English text tables.");
DebugNoFont = ((BasePlugin)this).Config.Bind<bool>("Troubleshooting", "DisableArabicFont", false, "Don't add the Arabic font.");
DebugNoPopupWords = ((BasePlugin)this).Config.Bind<bool>("Troubleshooting", "DisablePopupWords", false, "Keep the English popup-word pictures (CRIT, LEVEL UP...).");
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val;
if (!Enabled.Value)
{
ManualLogSource log = ((BasePlugin)this).Log;
val = new BepInExInfoLogInterpolatedStringHandler(27, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("Megabonk Arabic");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" is disabled in the config.");
}
log.LogInfo(val);
return;
}
Translations.Load();
TextPatches.Apply(new Harmony("arabic.megabonk"));
((BasePlugin)this).AddComponent<ArabicBehaviour>();
if (CheckForUpdates.Value)
{
Updates = new UpdateChecker("Megabonk Arabic", 193, "1.2.0", 1, () => ArabicOn, Visual);
Updates.Start(delegate(string msg)
{
((BasePlugin)this).Log.LogInfo((object)msg);
});
}
ManualLogSource log2 = ((BasePlugin)this).Log;
val = new BepInExInfoLogInterpolatedStringHandler(32, 3, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("Megabonk Arabic");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("1.2.0");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" loaded with ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(Translations.Count);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" translated lines.");
}
log2.LogInfo(val);
}
}
public class ArabicBehaviour : MonoBehaviour
{
private float _next;
public ArabicBehaviour(IntPtr ptr)
: base(ptr)
{
}
public void OnGUI()
{
bool flag;
try
{
flag = (Object)(object)GameManager.Instance != (Object)null;
}
catch
{
flag = true;
}
try
{
Plugin.Updates?.OnGUI(!flag);
}
catch
{
}
}
public void Update()
{
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Expected O, but got Unknown
//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
//IL_00ae: Expected O, but got Unknown
if (Time.realtimeSinceStartup < 20f || !Plugin.ReplaceMode)
{
Translate();
}
if (Time.unscaledTime < _next)
{
return;
}
_next = Time.unscaledTime + 0.5f;
bool flag = default(bool);
if (!Plugin.DebugNoFont.Value)
{
try
{
FontInstaller.Tick();
}
catch (Exception ex)
{
ManualLogSource logger = Plugin.Logger;
BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(18, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Font setup error: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
}
logger.LogWarning(val);
}
}
if (Plugin.ReplaceMode)
{
Translate();
}
if (Plugin.DebugNoTextHook.Value)
{
return;
}
try
{
TextPatches.ScanFixedLabels();
}
catch (Exception ex2)
{
ManualLogSource logger2 = Plugin.Logger;
BepInExDebugLogInterpolatedStringHandler val2 = new BepInExDebugLogInterpolatedStringHandler(18, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Fixed label scan: ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex2.Message);
}
logger2.LogDebug(val2);
}
}
private static void Translate()
{
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Expected O, but got Unknown
if (Plugin.DebugNoTables.Value)
{
return;
}
try
{
if (Plugin.ReplaceMode)
{
TableSwapper.Tick();
}
else
{
ArabicLocale.Tick();
}
}
catch (Exception ex)
{
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(19, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Translation error: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
}
logger.LogWarning(val);
}
}
}
internal static class TextPatches
{
private static readonly Dictionary<IntPtr, TextAlignmentOptions> OriginalAlignment = new Dictionary<IntPtr, TextAlignmentOptions>();
private static readonly HashSet<IntPtr> RtlLabels = new HashSet<IntPtr>();
private static readonly Dictionary<string, string> Cache = new Dictionary<string, string>();
private static readonly Dictionary<IntPtr, (string Original, string Shaped)> LastSet = new Dictionary<IntPtr, (string, string)>();
private const int CacheLimit = 4096;
private static readonly Dictionary<IntPtr, string> FixedOriginal = new Dictionary<IntPtr, string>();
private static readonly Regex MissingRx = new Regex("^\\s*No translation found for '(.+?)' in (.+?)\\s*$", RegexOptions.IgnoreCase);
private static float _nextScan;
private const string Level = "مستوى";
private static readonly Regex LevelRx = new Regex("^\\s*LVL\\s*(\\d+)\\s*$");
private static readonly HashSet<IntPtr> Fitted = new HashSet<IntPtr>();
public static void Apply(Harmony harmony)
{
if (!Plugin.DebugNoTextHook.Value)
{
Patch(harmony, AccessTools.PropertySetter(typeof(TMP_Text), "text"));
Patch(harmony, AccessTools.Method(typeof(TMP_Text), "SetText", new Type[2]
{
typeof(string),
typeof(bool)
}, (Type[])null));
Patch(harmony, AccessTools.Method(typeof(TMP_Text), "SetText", new Type[1] { typeof(string) }, (Type[])null));
}
if (!Plugin.DebugNoSkinHook.Value)
{
PatchPostfix(harmony, AccessTools.Method(typeof(SkinData), "GetName", (Type[])null, (Type[])null));
}
}
private static void PatchPostfix(Harmony harmony, MethodInfo target)
{
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Expected O, but got Unknown
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Expected O, but got Unknown
if (target == null)
{
return;
}
try
{
harmony.Patch((MethodBase)target, (HarmonyMethod)null, new HarmonyMethod(typeof(TextPatches), "FixNameOrder", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
}
catch (Exception ex)
{
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(18, 3, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Could not hook ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(target.DeclaringType?.Name);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(target.Name);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
}
logger.LogWarning(val);
}
}
private static void FixNameOrder(ref string __result)
{
if (!Plugin.ArabicOn)
{
return;
}
try
{
__result = Translations.FixSkinOrder(__result);
}
catch
{
}
}
private static void Patch(Harmony harmony, MethodInfo target)
{
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Expected O, but got Unknown
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Expected O, but got Unknown
if (target == null)
{
return;
}
try
{
harmony.Patch((MethodBase)target, new HarmonyMethod(typeof(TextPatches), "BeforeSetText", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
}
catch (Exception ex)
{
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(17, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Could not hook ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(target.Name);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
}
logger.LogWarning(val);
}
}
private static void BeforeSetText(TMP_Text __instance, ref string __0)
{
//IL_010f: Unknown result type (might be due to invalid IL or missing references)
//IL_0116: Expected O, but got Unknown
try
{
string text = __0;
if (string.IsNullOrEmpty(text) || (Object)(object)__instance == (Object)null)
{
return;
}
IntPtr pointer = ((Il2CppObjectBase)__instance).Pointer;
if (LastSet.TryGetValue(pointer, out (string, string) value) && text.Length > value.Item2.Length && text.StartsWith(value.Item2, StringComparison.Ordinal))
{
text = value.Item1 + text.Substring(value.Item2.Length);
}
if (TryRecoverMissing(text, out var recovered))
{
text = recovered;
}
if (Plugin.ArabicOn)
{
text = TranslateLabel(__instance, text);
}
__0 = text;
if (ArabicShaper.NeedsShaping(text))
{
__0 = ShapeCached(text);
if (LastSet.Count >= 4096)
{
LastSet.Clear();
}
LastSet[pointer] = (text, __0);
MakeRightToLeft(__instance);
}
else
{
LastSet.Remove(pointer);
if ((RtlLabels.Contains(pointer) || __instance.isRightToLeftText) && !ArabicShaper.ContainsArabic(text))
{
MakeLeftToRight(__instance);
}
}
}
catch (Exception ex)
{
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExDebugLogInterpolatedStringHandler val = new BepInExDebugLogInterpolatedStringHandler(18, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Arabic text hook: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
}
logger.LogDebug(val);
}
}
private static bool TryRecoverMissing(string text, out string recovered)
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Expected O, but got Unknown
recovered = null;
Match match = MissingRx.Match(text);
if (!match.Success)
{
return false;
}
try
{
Locale locale = LocalizationSettings.AvailableLocales.GetLocale(new LocaleIdentifier("en"));
string localizedString = LocalizationSettings.StringDatabase.GetLocalizedString(TableReference.op_Implicit(match.Groups[2].Value), TableEntryReference.op_Implicit(match.Groups[1].Value), locale, (FallbackBehavior)0, (Il2CppReferenceArray<Object>)null);
if (!string.IsNullOrEmpty(localizedString) && !MissingRx.IsMatch(localizedString))
{
recovered = localizedString;
return true;
}
}
catch
{
}
if (match.Groups[1].Value.IndexOf("MULTIPLAYER", StringComparison.OrdinalIgnoreCase) >= 0)
{
recovered = "MULTIPLAYER";
return true;
}
return false;
}
private static string TranslateLabel(TMP_Text label, string text)
{
string text2 = text.Trim();
if (Translations.TryGetExact(text2, out var arabic))
{
if (text2.Length <= 4)
{
FitToBox(label);
}
FixedOriginal[((Il2CppObjectBase)label).Pointer] = text;
return arabic;
}
if (Translations.FixSkinOrderIfCharacter(text, out var fixedText))
{
return fixedText;
}
Match match = LevelRx.Match(text);
if (match != null && match.Success)
{
FitToBox(label);
FixedOriginal[((Il2CppObjectBase)label).Pointer] = text;
return "مستوى " + match.Groups[1].Value;
}
if (text.StartsWith("مستوى ", StringComparison.Ordinal))
{
FitToBox(label);
}
return text;
}
public static void OnLanguageChanged(bool arabic)
{
LastSet.Clear();
_nextScan = 0f;
if (arabic)
{
return;
}
foreach (Object item in (Il2CppArrayBase<Object>)(object)Object.FindObjectsOfType(Il2CppType.Of<TMP_Text>()))
{
TMP_Text val = ((Il2CppObjectBase)item).TryCast<TMP_Text>();
if (!((Object)(object)val == (Object)null))
{
IntPtr pointer = ((Il2CppObjectBase)val).Pointer;
if (Fitted.Remove(pointer))
{
val.enableAutoSizing = false;
val.fontSize = val.fontSizeMax;
}
if (FixedOriginal.TryGetValue(pointer, out var value))
{
val.text = value;
}
}
}
FixedOriginal.Clear();
Fitted.Clear();
}
public static void ScanFixedLabels()
{
if (Time.unscaledTime < _nextScan)
{
return;
}
_nextScan = Time.unscaledTime + 1f;
foreach (Object item in (Il2CppArrayBase<Object>)(object)Object.FindObjectsOfType(Il2CppType.Of<TMP_Text>()))
{
TMP_Text val = ((Il2CppObjectBase)item).TryCast<TMP_Text>();
string text = ((val != null) ? val.text : null);
if (!string.IsNullOrEmpty(text) && ((Plugin.ArabicOn && text.Length <= 40 && Translations.TryGetExact(text.Trim(), out var _)) || MissingRx.IsMatch(text)))
{
val.text = text;
}
}
}
private static void FitToBox(TMP_Text label)
{
if (Fitted.Add(((Il2CppObjectBase)label).Pointer))
{
float fontSize = label.fontSize;
label.enableWordWrapping = false;
label.fontSizeMax = fontSize;
label.fontSizeMin = fontSize * 0.4f;
label.enableAutoSizing = true;
}
}
private static string ShapeCached(string text)
{
if (Cache.TryGetValue(text, out var value))
{
return value;
}
value = ArabicShaper.Shape(text);
if (Cache.Count >= 4096)
{
Cache.Clear();
}
Cache[text] = value;
return value;
}
private static void MakeRightToLeft(TMP_Text label)
{
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
IntPtr pointer = ((Il2CppObjectBase)label).Pointer;
if (!label.isRightToLeftText)
{
label.isRightToLeftText = true;
}
RtlLabels.Add(pointer);
if (Plugin.RightAlign.Value && !Fitted.Contains(pointer) && !OriginalAlignment.ContainsKey(pointer))
{
TextAlignmentOptions alignment = label.alignment;
TextAlignmentOptions val = Flip(alignment);
if (val != alignment)
{
OriginalAlignment[pointer] = alignment;
label.alignment = val;
}
}
}
private static void MakeLeftToRight(TMP_Text label)
{
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
IntPtr pointer = ((Il2CppObjectBase)label).Pointer;
label.isRightToLeftText = false;
RtlLabels.Remove(pointer);
if (OriginalAlignment.TryGetValue(pointer, out var value))
{
label.alignment = value;
OriginalAlignment.Remove(pointer);
}
}
private static TextAlignmentOptions Flip(TextAlignmentOptions a)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Invalid comparison between Unknown and I4
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Invalid comparison between Unknown and I4
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Invalid comparison between Unknown and I4
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Invalid comparison between Unknown and I4
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Invalid comparison between Unknown and I4
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Invalid comparison between Unknown and I4
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Invalid comparison between Unknown and I4
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
if ((int)a <= 1025)
{
if ((int)a == 257)
{
return (TextAlignmentOptions)260;
}
if ((int)a == 513)
{
return (TextAlignmentOptions)516;
}
if ((int)a == 1025)
{
return (TextAlignmentOptions)1028;
}
}
else
{
if ((int)a == 2049)
{
return (TextAlignmentOptions)2052;
}
if ((int)a == 4097)
{
return (TextAlignmentOptions)4100;
}
if ((int)a == 8193)
{
return (TextAlignmentOptions)8196;
}
}
return a;
}
}
internal static class TextureSwapper
{
private const string AtlasName = "atlas_emojis_PSD";
private static Texture2D _arabicAtlas;
private static Il2CppStructArray<byte> _pngBytes;
private static bool _failed;
private static readonly HashSet<IntPtr> Swapped = new HashSet<IntPtr>();
private static float _nextScan;
public static void Tick()
{
//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0103: Expected O, but got Unknown
if (_failed || Time.unscaledTime < _nextScan)
{
return;
}
_nextScan = Time.unscaledTime + 1f;
if ((Object)(object)_arabicAtlas == (Object)null && !Create())
{
return;
}
bool flag2 = default(bool);
foreach (Object item in (Il2CppArrayBase<Object>)(object)Resources.FindObjectsOfTypeAll(Il2CppType.Of<Material>()))
{
Material val = ((Il2CppObjectBase)item).TryCast<Material>();
if ((Object)(object)val == (Object)null || Swapped.Contains(((Il2CppObjectBase)val).Pointer))
{
continue;
}
try
{
bool flag = false;
foreach (string item2 in (Il2CppArrayBase<string>)(object)val.GetTexturePropertyNames())
{
Texture texture = val.GetTexture(item2);
if (!((Object)(object)texture == (Object)null) && !(((Object)texture).name != "atlas_emojis_PSD"))
{
val.SetTexture(item2, (Texture)(object)_arabicAtlas);
flag = true;
}
}
if (flag)
{
Swapped.Add(((Il2CppObjectBase)val).Pointer);
ManualLogSource logger = Plugin.Logger;
BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(33, 1, ref flag2);
if (flag2)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Arabic: popup words on material ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((Object)val).name);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(".");
}
logger.LogInfo(val2);
}
}
catch
{
Swapped.Add(((Il2CppObjectBase)val).Pointer);
}
}
}
private static bool Create()
{
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: Expected O, but got Unknown
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Expected O, but got Unknown
try
{
byte[] array = LoadResource("atlas_emojis_ar.png");
if (array == null)
{
_failed = true;
return false;
}
_pngBytes = Il2CppStructArray<byte>.op_Implicit(array);
Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true);
if (!ImageConversion.LoadImage(val, _pngBytes, false))
{
_failed = true;
return false;
}
((Object)val).name = "atlas_emojis_PSD_ar";
((Texture)val).filterMode = (FilterMode)1;
((Texture)val).wrapMode = (TextureWrapMode)1;
((Object)val).hideFlags = (HideFlags)61;
Object.DontDestroyOnLoad((Object)(object)val);
_arabicAtlas = val;
return true;
}
catch (Exception ex)
{
_failed = true;
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(29, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Arabic popup words disabled: ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
}
logger.LogWarning(val2);
return false;
}
}
private static byte[] LoadResource(string name)
{
string path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? "", name);
if (File.Exists(path))
{
return File.ReadAllBytes(path);
}
using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(name);
if (stream == null)
{
return null;
}
using MemoryStream memoryStream = new MemoryStream();
stream.CopyTo(memoryStream);
return memoryStream.ToArray();
}
}
internal static class Translations
{
private static Dictionary<string, Dictionary<long, string>> _tables = new Dictionary<string, Dictionary<long, string>>();
private static Dictionary<string, string> _exact = new Dictionary<string, string>();
public static int Count { get; private set; }
public static HashSet<string> SkinWords { get; private set; } = new HashSet<string>();
public static HashSet<string> CharacterNames { get; private set; } = new HashSet<string>();
public static bool TryGetExact(string text, out string arabic)
{
return _exact.TryGetValue(text, out arabic);
}
public static bool FixSkinOrderIfCharacter(string text, out string fixedText)
{
fixedText = text;
if (string.IsNullOrEmpty(text))
{
return false;
}
int num = text.IndexOf(' ');
if (num <= 0 || !SkinWords.Contains(text.Substring(0, num)))
{
return false;
}
if (!CharacterNames.Contains(text.Substring(num + 1).Trim()))
{
return false;
}
fixedText = text.Substring(num + 1).Trim() + " " + text.Substring(0, num);
return true;
}
public static string FixSkinOrder(string name)
{
if (string.IsNullOrEmpty(name))
{
return name;
}
int num = name.IndexOf(' ');
if (num <= 0 || !SkinWords.Contains(name.Substring(0, num)))
{
return name;
}
return name.Substring(num + 1) + " " + name.Substring(0, num);
}
public static bool TryGetTable(string collection, out Dictionary<long, string> table)
{
return _tables.TryGetValue(collection, out table);
}
public static void Load()
{
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Expected O, but got Unknown
string text = null;
string text2 = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? "", "ar.json");
if (File.Exists(text2))
{
text = File.ReadAllText(text2);
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(23, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Using translation file ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text2);
}
logger.LogInfo(val);
}
else
{
using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("ar.json");
if (stream != null)
{
text = new StreamReader(stream).ReadToEnd();
}
}
if (text == null)
{
Plugin.Logger.LogError((object)"No translation found.");
return;
}
Dictionary<string, Dictionary<string, string>>? dictionary = JsonSerializer.Deserialize<Dictionary<string, Dictionary<string, string>>>(text);
Dictionary<string, Dictionary<long, string>> dictionary2 = new Dictionary<string, Dictionary<long, string>>();
int num = 0;
if (dictionary.TryGetValue("_exact", out var value))
{
_exact = new Dictionary<string, string>(value);
}
if (!Plugin.ReplaceMode)
{
_exact.Remove("English");
}
foreach (KeyValuePair<string, Dictionary<string, string>> item in dictionary)
{
item.Deconstruct(out var key, out var value2);
string text3 = key;
Dictionary<string, string> dictionary3 = value2;
if (text3.StartsWith("_"))
{
continue;
}
Dictionary<long, string> dictionary4 = new Dictionary<long, string>();
foreach (KeyValuePair<string, string> item2 in dictionary3)
{
item2.Deconstruct(out key, out var value3);
string s = key;
string value4 = value3;
if (long.TryParse(s, out var result) && !string.IsNullOrEmpty(value4))
{
dictionary4[result] = value4;
num++;
}
}
dictionary2[text3] = dictionary4;
}
_tables = dictionary2;
Count = num;
CharacterNames = (dictionary2.TryGetValue("Characters", out var value5) ? new HashSet<string>(value5.Values.Where((string v) => v.Length < 25)) : new HashSet<string>());
SkinWords = (dictionary2.TryGetValue("Skins", out var value6) ? new HashSet<string>(value6.Values.Where((string v) => !v.Contains(' '))) : new HashSet<string>());
}
}
internal static class TableSwapper
{
private static readonly HashSet<IntPtr> Done = new HashSet<IntPtr>();
public static void Tick()
{
//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
//IL_0101: Expected O, but got Unknown
bool flag = false;
string value = Plugin.ReplaceLocale.Value;
bool flag2 = default(bool);
foreach (Object item in (Il2CppArrayBase<Object>)(object)Resources.FindObjectsOfTypeAll(Il2CppType.Of<StringTable>()))
{
StringTable val = ((Il2CppObjectBase)item).TryCast<StringTable>();
if ((Object)(object)val == (Object)null || Done.Contains(((Il2CppObjectBase)val).Pointer) || !string.Equals(((LocalizationTable)val).LocaleIdentifier.Code, value, StringComparison.OrdinalIgnoreCase))
{
continue;
}
Done.Add(((Il2CppObjectBase)val).Pointer);
if (!Translations.TryGetTable(((LocalizationTable)val).TableCollectionName, out var table))
{
continue;
}
int num = 0;
foreach (KeyValuePair<long, string> item2 in table)
{
item2.Deconstruct(out var key, out var value2);
long num2 = key;
string value3 = value2;
StringTableEntry entry = ((DetailedLocalizationTable<StringTableEntry>)(object)val).GetEntry(num2);
if (entry != null)
{
entry.Value = value3;
num++;
}
}
if (num > 0)
{
flag = true;
ManualLogSource logger = Plugin.Logger;
BepInExDebugLogInterpolatedStringHandler val2 = new BepInExDebugLogInterpolatedStringHandler(17, 2, ref flag2);
if (flag2)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Arabic: ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((LocalizationTable)val).TableCollectionName);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" (");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(num);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" lines)");
}
logger.LogDebug(val2);
}
}
if (flag)
{
RefreshVisibleText();
}
}
public static void RefreshVisibleText()
{
foreach (Object item in (Il2CppArrayBase<Object>)(object)Resources.FindObjectsOfTypeAll(Il2CppType.Of<LocalizeStringEvent>()))
{
try
{
LocalizeStringEvent obj = ((Il2CppObjectBase)item).TryCast<LocalizeStringEvent>();
if (obj != null)
{
obj.RefreshString();
}
}
catch
{
}
}
FontInstaller.RefreshArabicLabels();
}
}
internal sealed class UpdateChecker
{
private const int MegabonkGameId = 7674;
private const string Api = "https://api.nexusmods.com/v2/graphql";
private readonly string _modName;
private readonly int _modId;
private readonly string _current;
private readonly int _slot;
private readonly Func<bool> _arabic;
private readonly Func<string, string> _visual;
private volatile string _latest;
private bool _dismissed;
private GUIStyle _style;
private GUIStyle _close;
private Texture2D _bg;
private string Url => $"https://www.nexusmods.com/megabonk/mods/{_modId}?tab=files";
public UpdateChecker(string modName, int modId, string currentVersion, int slot, Func<bool> arabic, Func<string, string> visual)
{
_modName = modName;
_modId = modId;
_current = currentVersion;
_slot = slot;
_arabic = arabic;
_visual = visual;
}
public void Start(Action<string> log)
{
Thread thread = new Thread((ThreadStart)delegate
{
try
{
using HttpClient httpClient = new HttpClient
{
Timeout = TimeSpan.FromSeconds(10.0)
};
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd(_modName.Replace(" ", "") + "/" + _current);
string content = "{\"query\":\"{ legacyMods(ids: [{gameId: " + 7674 + ", modId: " + _modId + "}]) { nodes { version } } }\"}";
using HttpResponseMessage httpResponseMessage = httpClient.PostAsync("https://api.nexusmods.com/v2/graphql", new StringContent(content, Encoding.UTF8, "application/json")).GetAwaiter().GetResult();
using JsonDocument jsonDocument = JsonDocument.Parse(httpResponseMessage.Content.ReadAsStringAsync().GetAwaiter().GetResult());
JsonElement property = jsonDocument.RootElement.GetProperty("data").GetProperty("legacyMods").GetProperty("nodes");
if (property.GetArrayLength() != 0)
{
string text = property[0].GetProperty("version").GetString();
if (IsNewer(text, _current))
{
_latest = text;
log($"{_modName} {text} is available on Nexus (you have {_current}).");
}
}
}
catch (Exception ex)
{
log("Update check skipped: " + ex.Message);
}
});
thread.IsBackground = true;
thread.Name = "UpdateChecker";
thread.Start();
}
private static bool IsNewer(string latest, string current)
{
Version version = Parse(latest);
Version version2 = Parse(current);
if (version != null && version2 != null)
{
return version > version2;
}
return false;
static Version Parse(string v)
{
v = (v ?? "").Trim().TrimStart('v', 'V');
int num = v.IndexOfAny(new char[3] { '-', '+', ' ' });
if (num > 0)
{
v = v.Substring(0, num);
}
if (!Version.TryParse(v, out Version result))
{
return null;
}
return result;
}
}
public void OnGUI(bool show)
{
//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_0147: Unknown result type (might be due to invalid IL or missing references)
//IL_0199: Unknown result type (might be due to invalid IL or missing references)
//IL_015b: Unknown result type (might be due to invalid IL or missing references)
//IL_0211: Unknown result type (might be due to invalid IL or missing references)
//IL_021b: Unknown result type (might be due to invalid IL or missing references)
//IL_016b: Unknown result type (might be due to invalid IL or missing references)
//IL_0254: Unknown result type (might be due to invalid IL or missing references)
//IL_027e: Unknown result type (might be due to invalid IL or missing references)
//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
if (_latest == null || _dismissed || !show)
{
return;
}
EnsureStyles();
float num = Mathf.Clamp((float)Screen.height / 1080f, 0.75f, 2.5f);
Matrix4x4 matrix = GUI.matrix;
GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(num, num, 1f));
try
{
float num2 = (float)Screen.width / num;
Rect val = default(Rect);
((Rect)(ref val))..ctor(num2 - 440f, 90f + (float)_slot * 70f, 420f, 60f);
bool flag = _arabic();
string text = (flag ? ("تحديث جديد: " + _modName + " " + _latest) : (_modName + " " + _latest + " is out on Nexus"));
string text2 = (flag ? ("عندك " + _current + ". اضغط هنا لفتح صفحة المود.") : ("You have " + _current + ". Click here to open the mod page."));
Event current = Event.current;
Rect val2 = default(Rect);
((Rect)(ref val2))..ctor(((Rect)(ref val)).xMax - 30f, ((Rect)(ref val)).y + 6f, 24f, 24f);
if ((int)current.type == 0 && current.button == 0 && ((Rect)(ref val)).Contains(current.mousePosition))
{
if (((Rect)(ref val2)).Contains(current.mousePosition))
{
_dismissed = true;
}
else
{
Application.OpenURL(Url);
_dismissed = true;
}
current.Use();
}
GUI.DrawTexture(val, (Texture)(object)_bg);
Rect val3 = default(Rect);
((Rect)(ref val3))..ctor(((Rect)(ref val)).x + 12f, ((Rect)(ref val)).y + 6f, ((Rect)(ref val)).width - 50f, 24f);
_style.alignment = (TextAnchor)(flag ? 2 : 0);
_style.fontStyle = (FontStyle)1;
_style.normal.textColor = new Color(1f, 0.82f, 0.25f);
GUI.Label(val3, flag ? _visual(text) : text, _style);
_style.fontStyle = (FontStyle)0;
_style.normal.textColor = Color.white;
GUI.Label(new Rect(((Rect)(ref val3)).x, ((Rect)(ref val3)).y + 24f, ((Rect)(ref val3)).width, 24f), flag ? _visual(text2) : text2, _style);
GUI.Label(val2, "x", _close);
}
finally
{
GUI.matrix = matrix;
}
}
private void EnsureStyles()
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Expected O, but got Unknown
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Expected O, but got Unknown
//IL_0093: Unknown result type (might be due to invalid IL or missing references)
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00ac: Expected O, but got Unknown
//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
if (_style == null || !((Object)(object)_bg != (Object)null))
{
_bg = new Texture2D(1, 1)
{
hideFlags = (HideFlags)61
};
_bg.SetPixel(0, 0, new Color(0.07f, 0.08f, 0.1f, 0.92f));
_bg.Apply();
_style = new GUIStyle(GUI.skin.label)
{
fontSize = 15,
wordWrap = false,
richText = false
};
_close = new GUIStyle(GUI.skin.label)
{
fontSize = 20,
alignment = (TextAnchor)4
};
_close.normal.textColor = new Color(0.8f, 0.8f, 0.85f);
}
}
}
}