using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Collections.Generic;
using MonoMod.Cil;
using MonoMod.Utils;
using Newtonsoft.Json;
using RTLC.API;
using RTLC.API.LethalExpansion;
using RTLC.Extensions;
using RTLC.Helpers;
using RTLC.SmartFormat;
using SmartFormat;
using SmartFormat.Core.Extensions;
using SmartFormat.Core.Parsing;
using SmartFormat.Core.Settings;
using SmartFormat.Extensions;
using SmartFormat.ZString;
using Steamworks.Data;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("RTLC")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.0.14.0")]
[assembly: AssemblyInformationalVersion("0.0.14+3c4897e2d7da14b6cd0bf57e46b3ec36b73519af")]
[assembly: AssemblyProduct("RTLC")]
[assembly: AssemblyTitle("RTLC")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.14.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.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 RTLC
{
public class RTLCConfiguration
{
public ConfigEntry<bool> AutoClearUntranslatedOnAwake { get; private set; }
internal RTLCConfiguration()
{
ConfigFile config = ((BaseUnityPlugin)RTLCPlugin.Instance).Config;
AutoClearUntranslatedOnAwake = config.Bind<bool>("General", "ClearUntranslatedOnAwake", true, (ConfigDescription)null);
}
}
[BepInPlugin("RTLC", "RTLC", "0.0.14")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class RTLCPlugin : BaseUnityPlugin
{
public static RTLCPlugin Instance { get; private set; }
public RTLCConfiguration Config { get; private set; }
internal ManualLogSource Logger { get; private set; }
internal string WorkingDirectory { get; private set; }
internal Harmony Harmony { get; private set; }
private void Awake()
{
//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
//IL_00eb: Expected O, but got Unknown
Instance = this;
Logger = ((BaseUnityPlugin)this).Logger;
WorkingDirectory = new FileInfo(((BaseUnityPlugin)this).Info.Location).DirectoryName;
Config = new RTLCConfiguration();
foreach (MethodInfo item in from m in typeof(RTLCPlugin).Assembly.GetTypes().SelectMany((Type t) => t.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
where m.GetCustomAttribute<InitializeOnAwakeAttribute>() != null
select m)
{
item.Invoke(null, null);
Logger.LogInfo((object)("Initialized " + item.GetReadableString()));
}
Harmony = new Harmony("RTLC");
Harmony.PatchAll(typeof(RTLCPlugin).Assembly);
LethalExpansionTranslation.TryAddScrapsToUntranslated();
Logger.LogInfo((object)"Plugin RTLC is loaded!");
}
}
internal static class KnownPluginDependency
{
public const string c_HDLethalCompany = "HDLethalCompany";
public const string c_ShipLoot = "com.github.tinyhoot.ShipLoot";
public const string c_LethalExpansionCore = "com.github.lethalmods.lethalexpansioncore";
public const string c_LethalExpansion = "LethalExpansion";
public const string c_LethalThings = "evaisa.lethalthings";
public const string c_FacilityMeltdown = "me.loaforc.facilitymeltdown";
}
internal static class Translation
{
private const char c_LineFeedChar = '\n';
private const char c_CarriageReturnChar = '\r';
private const char c_EmptySpaceChar = '\u200b';
private const char c_SpaceChar = ' ';
private static readonly Dictionary<string, string> s_Translations;
private static readonly Dictionary<Regex, string> s_RegexTranslations;
private static readonly CultureInfo s_RussianCultureInfo;
private static readonly SmartFormatter s_SmartFormatter;
private static Dictionary<string, string> s_UntranslatedCache;
private static string s_UntranslatedFilePath;
private static readonly ZStringBuilder s_ZStringBuilder;
public static string Concat(string str0, string str1)
{
ZStringBuilder stringBuilder = GetStringBuilder();
stringBuilder.Append(str0);
stringBuilder.Append(str1);
return GetLocalizedText(((object)stringBuilder).ToString(), shouldIgnoreKey: true);
}
public static string Concat(string str0, string str1, string str2)
{
ZStringBuilder stringBuilder = GetStringBuilder();
stringBuilder.Append(str0);
stringBuilder.Append(str1);
stringBuilder.Append(str2);
return GetLocalizedText(((object)stringBuilder).ToString(), shouldIgnoreKey: true);
}
public static string Concat(string str0, string str1, string str2, string str3)
{
ZStringBuilder stringBuilder = GetStringBuilder();
stringBuilder.Append(str0);
stringBuilder.Append(str1);
stringBuilder.Append(str2);
stringBuilder.Append(str3);
return GetLocalizedText(((object)stringBuilder).ToString(), shouldIgnoreKey: true);
}
public static string Concat(params string[] values)
{
ZStringBuilder stringBuilder = GetStringBuilder();
foreach (string text in values)
{
stringBuilder.Append(text);
}
return GetLocalizedText(((object)stringBuilder).ToString(), shouldIgnoreKey: true);
}
static Translation()
{
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Expected O, but got Unknown
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Expected O, but got Unknown
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Expected O, but got Unknown
s_Translations = new Dictionary<string, string>();
s_RegexTranslations = new Dictionary<Regex, string>();
s_RussianCultureInfo = new CultureInfo("ru-RU");
s_UntranslatedCache = new Dictionary<string, string>();
s_UntranslatedFilePath = string.Empty;
s_ZStringBuilder = new ZStringBuilder(false);
SmartSettings.IsThreadSafeMode = false;
ParserSettings val = new ParserSettings();
val.AddCustomSelectorChars((IList<char>)new List<char>(1) { '"' });
SmartSettings val2 = new SmartSettings
{
Parser = val
};
s_SmartFormatter = Smart.CreateDefaultSmartFormat(val2).AddExtensions((ISource[])(object)new ISource[6]
{
(ISource)new StringToNumberSource(),
(ISource)new TranslationSource(),
(ISource)new SelectorTextToStringSource(),
(ISource)new ReplaceNewLinesSource(),
(ISource)new AppendStringSource(),
(ISource)new CollectionCountSource()
});
s_SmartFormatter.RemoveFormatterExtension<IsMatchFormatter>();
s_SmartFormatter.AddExtensions((IFormatter[])(object)new IFormatter[2]
{
new IsMatchFormatterEx(),
new IsMatchesFormatterEx()
});
}
[InitializeOnAwake]
public static void LoadTranslation()
{
string text = Path.Combine(RTLCPlugin.Instance.WorkingDirectory, "Translations");
s_UntranslatedFilePath = Path.Combine(text, "Untranslated.json");
CreateUntranslatedFile();
foreach (string item in Directory.EnumerateFiles(text, "*.json", SearchOption.AllDirectories))
{
string fileName = Path.GetFileName(item);
if (!(fileName == "Untranslated.json"))
{
ReadTranslationFile(item);
}
}
}
private static void ReadTranslationFile(string? translationFile)
{
IDictionary<string, string> dictionary = JsonConvert.DeserializeObject<IDictionary<string, string>>(File.ReadAllText(translationFile));
foreach (KeyValuePair<string, string> item in dictionary)
{
if (item.Key.StartsWith("__"))
{
continue;
}
if (item.Key.StartsWith("r:"))
{
Dictionary<Regex, string> dictionary2 = s_RegexTranslations;
string key = item.Key;
dictionary2.Add(new Regex(key.Substring(2, key.Length - 2), RegexOptions.Multiline | RegexOptions.Compiled, TimeSpan.FromMilliseconds(500.0)), item.Value);
continue;
}
string text = item.Key;
if (text.StartsWith("key:"))
{
ReadOnlySpan<char> readOnlySpan = text.AsSpan();
ReadOnlySpan<char> span = readOnlySpan.Slice(4);
int num = span.IndexOf(':');
if (num == -1)
{
RTLCPlugin.Instance.Logger.LogWarning((object)(item.Key + " has invalid key reference. Check the file: " + Path.GetFileName(translationFile)));
continue;
}
readOnlySpan = span.Slice(num + 1);
text = readOnlySpan.ToString();
readOnlySpan = span.Slice(0, num);
string key2 = readOnlySpan.ToString();
AddTranslation(key2, item.Value);
}
AddTranslation(text, item.Value);
}
}
private static void CreateUntranslatedFile()
{
if (File.Exists(s_UntranslatedFilePath))
{
if (RTLCPlugin.Instance.Config.AutoClearUntranslatedOnAwake.Value)
{
File.Delete(s_UntranslatedFilePath);
s_UntranslatedCache = new Dictionary<string, string>();
}
else
{
s_UntranslatedCache = JsonConvert.DeserializeObject<Dictionary<string, string>>(File.ReadAllText(s_UntranslatedFilePath)) ?? new Dictionary<string, string>();
}
}
}
private static void AddTranslation(string key, string translation)
{
if (s_Translations.ContainsKey(key))
{
RTLCPlugin.Instance.Logger.LogWarning((object)(key + " already exists."));
}
else
{
s_Translations[key] = translation;
}
}
private static void AddUntranslatedText(string? key, string? originalTranslation = null)
{
if (!s_UntranslatedCache.ContainsKey(key))
{
s_UntranslatedCache[key] = originalTranslation ?? key;
File.WriteAllText(s_UntranslatedFilePath, JsonConvert.SerializeObject((object)s_UntranslatedCache, (Formatting)1));
}
}
private static bool ShouldIgnoreTranslation(string? text)
{
if (string.IsNullOrWhiteSpace(text) || text.Length < 3)
{
return true;
}
if (Regex.IsMatch(text, "^\\[\\w*\\]\\n*$"))
{
return true;
}
char c = text[0];
int num = -1;
ReadOnlySpan<char> readOnlySpan = text.AsSpan();
for (int i = 0; i < readOnlySpan.Length; i++)
{
char c2 = readOnlySpan[i];
if (c2 == '\n' || c2 == '\r' || c2 == '\u200b' || c2 == ' ' || c2 == c || (c2 >= '\0' && c2 <= '?') || (c2 >= '[' && c2 <= '`') || (c2 >= '{' && c2 <= '\u007f') || (c2 >= 'Ѐ' && c2 <= 'ӿ'))
{
num++;
}
}
return text.Length - num < 3;
}
internal static string Format(string format, object arg0)
{
format = GetLocalizedText(format, shouldIgnoreKey: true);
ZStringBuilder stringBuilder = GetStringBuilder();
stringBuilder.AppendFormat<object>(format, arg0);
return GetLocalizedText(((object)stringBuilder).ToString(), shouldIgnoreKey: true);
}
internal static string Format(string format, object arg0, object arg1)
{
format = GetLocalizedText(format, shouldIgnoreKey: true);
ZStringBuilder stringBuilder = GetStringBuilder();
stringBuilder.AppendFormat<object, object>(format, arg0, arg1);
return GetLocalizedText(((object)stringBuilder).ToString(), shouldIgnoreKey: true);
}
internal static string Format(string format, object arg0, object arg1, object arg2)
{
format = GetLocalizedText(format, shouldIgnoreKey: true);
ZStringBuilder stringBuilder = GetStringBuilder();
stringBuilder.AppendFormat<object, object, object>(format, arg0, arg1, arg2);
return GetLocalizedText(((object)stringBuilder).ToString(), shouldIgnoreKey: true);
}
internal static string Format(string format, params object[] args)
{
format = GetLocalizedText(format, shouldIgnoreKey: true);
ZStringBuilder stringBuilder = GetStringBuilder();
stringBuilder.AppendFormat<object[]>(format, args);
return GetLocalizedText(((object)stringBuilder).ToString(), shouldIgnoreKey: true);
}
private static ZStringBuilder GetStringBuilder()
{
s_ZStringBuilder.Clear();
return s_ZStringBuilder;
}
internal static string GetLocalizedText(string? key)
{
return GetLocalizedText(key, key, shouldIgnoreKey: false);
}
internal static string GetLocalizedText(string? key, bool shouldIgnoreKey)
{
return GetLocalizedText(key, key, shouldIgnoreKey);
}
internal static string GetLocalizedText(string? key, string? originalTranslation)
{
return GetLocalizedText(key, originalTranslation, shouldIgnoreKey: false);
}
internal static string GetLocalizedText(string? key, string? originalTranslation, bool shouldIgnoreKey)
{
if (ShouldIgnoreTranslation(originalTranslation) || s_Translations.ContainsValue(key))
{
return originalTranslation;
}
if (s_Translations.TryGetValue(key, out string value))
{
return s_SmartFormatter.Format((IFormatProvider)s_RussianCultureInfo, value, new object[1]
{
new
{
Original = originalTranslation
}
});
}
if (s_UntranslatedCache.ContainsKey(key))
{
return originalTranslation;
}
foreach (KeyValuePair<Regex, string> s_RegexTranslation in s_RegexTranslations)
{
Match match = s_RegexTranslation.Key.Match(originalTranslation);
if (match.Success)
{
List<string> matches = (from Group grp in match.Groups
select grp.Value).Skip(1).ToList();
return s_SmartFormatter.Format((IFormatProvider)s_RussianCultureInfo, s_RegexTranslation.Value, new object[1]
{
new
{
Original = originalTranslation,
Matches = matches
}
});
}
}
if (!shouldIgnoreKey)
{
AddUntranslatedText(key, originalTranslation);
}
return originalTranslation;
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "RTLC";
public const string PLUGIN_NAME = "RTLC";
public const string PLUGIN_VERSION = "0.0.14";
}
}
namespace RTLC.Textures
{
[HarmonyPatch]
internal static class ReplaceTexturesHandler
{
private static AssetBundle s_AssetBundle;
[InitializeOnAwake]
public static void LoadTextures()
{
s_AssetBundle = AssetBundle.LoadFromFile(Path.Combine(RTLCPlugin.Instance.WorkingDirectory, "Bundles", "rtlc.main"));
_ = (Object)(object)s_AssetBundle == (Object)null;
}
[HarmonyPatch(typeof(StartOfRound), "Start")]
[HarmonyPostfix]
[HarmonyPriority(0)]
private static void StartOfRoundLoaded()
{
ReplaceTextures();
}
private static void ReplaceTextures()
{
Texture2D[] array = Resources.FindObjectsOfTypeAll<Texture2D>();
foreach (Texture2D val in array)
{
string name = ((Object)val).name;
if (!string.IsNullOrEmpty(name))
{
Texture2D val2 = s_AssetBundle.LoadAsset<Texture2D>(name);
if (!((Object)(object)val2 == (Object)null))
{
ImageConversion.LoadImage(val, ImageConversion.EncodeToPNG(val2));
}
}
}
}
}
}
namespace RTLC.Texts
{
[HarmonyPatch]
internal static class LoadCyrillicFonts
{
private static TMP_FontAsset? s_TransmitFontAsset;
private static TMP_FontAsset? s_MainFontAsset;
private static TMP_FontAsset? s_MainBigFontAsset;
private static Shader s_FontShader;
private static bool s_IgnoreAwake;
[InitializeOnAwake]
public static void LoadFonts()
{
AssetBundle val = AssetBundle.LoadFromFile(Path.Combine(RTLCPlugin.Instance.WorkingDirectory, "Bundles", "rtlcfont.assetbundle"));
s_MainFontAsset = val.LoadAsset<TMP_FontAsset>("Assets/Fonts/3270-Regular.asset");
s_MainBigFontAsset = val.LoadAsset<TMP_FontAsset>("Assets/Fonts/3270-Big.asset");
s_TransmitFontAsset = val.LoadAsset<TMP_FontAsset>("Assets/Fonts/3716-font.asset");
s_FontShader = val.LoadAsset<Shader>("Assets/TextMesh Pro/Shaders/TMP_SDF SSD.shader");
TMP_Settings.fallbackFontAssets.Add(s_MainFontAsset);
}
[HarmonyPatch(typeof(TMP_FontAsset), "Awake")]
[HarmonyPrefix]
private static void LoadFontAsset(TMP_FontAsset __instance)
{
if (!s_IgnoreAwake)
{
__instance.atlasPopulationMode = (AtlasPopulationMode)0;
if (((Object)__instance).name.StartsWith("edunline"))
{
__instance.fallbackFontAssetTable.Add(CreateVariant(__instance, s_TransmitFontAsset));
}
else
{
__instance.fallbackFontAssetTable.Add(CreateVariant(__instance, s_MainFontAsset));
}
}
}
private static TMP_FontAsset CreateVariant(TMP_FontAsset original, TMP_FontAsset dst)
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Expected O, but got Unknown
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)dst == (Object)(object)s_MainFontAsset && original.creationSettings.pointSize > 110)
{
dst = s_MainBigFontAsset;
}
Material val = new Material(s_FontShader);
val.CopyMatchingPropertiesFromMaterial(((TMP_Asset)original).material);
val.shaderKeywords = ((TMP_Asset)original).material.shaderKeywords;
val.mainTexture = (Texture)(object)dst.atlasTexture;
val.SetFloat("_TextureWidth", (float)dst.atlasWidth);
val.SetFloat("_TextureHeight", (float)dst.atlasHeight);
s_IgnoreAwake = true;
dst = Object.Instantiate<TMP_FontAsset>(dst);
((TMP_Asset)dst).material = val;
s_IgnoreAwake = false;
return dst;
}
}
internal static class ReplaceTextOnSceneLoaded
{
[InitializeOnAwake]
private static void Init()
{
SceneManager.sceneLoaded += SceneManager_sceneLoaded;
}
private static void SceneManager_sceneLoaded(Scene scene, LoadSceneMode mode)
{
string name = ((Scene)(ref scene)).name;
if (!name.Equals("InitScene") && !name.Equals("InitSceneLaunchOptions") && !name.Equals("MainMenu") && !name.Equals("SampleSceneRelay"))
{
return;
}
UIBehaviour[] array = Object.FindObjectsOfType<UIBehaviour>(true);
foreach (UIBehaviour val in array)
{
TextMeshProUGUI val2 = (TextMeshProUGUI)(object)((val is TextMeshProUGUI) ? val : null);
if (val2 != null)
{
((TMP_Text)val2).text = Translation.GetLocalizedText(((TMP_Text)val2).text);
continue;
}
TMP_Dropdown val3 = (TMP_Dropdown)(object)((val is TMP_Dropdown) ? val : null);
if (val3 == null || val3.options == null)
{
continue;
}
foreach (OptionData option in val3.options)
{
option.text = Translation.GetLocalizedText(option.text);
}
}
}
}
}
namespace RTLC.SmartFormat
{
internal class AppendStringSource : Source
{
public override bool TryEvaluateSelector(ISelectorInfo selectorInfo)
{
if (selectorInfo.CurrentValue is string text && selectorInfo.SelectorText.StartsWith("Append_"))
{
string selectorText = selectorInfo.SelectorText;
selectorInfo.Result = text + selectorText.Substring(7, selectorText.Length - 7);
return true;
}
return false;
}
}
internal class CollectionCountSource : Source
{
public override bool TryEvaluateSelector(ISelectorInfo selectorInfo)
{
if (selectorInfo.CurrentValue is ICollection collection && selectorInfo.SelectorText.Equals("Count"))
{
selectorInfo.Result = collection.Count;
return true;
}
return false;
}
}
internal class IsMatchesFormatterEx : IFormatter
{
private const char c_SplitChar = '|';
public string Name { get; set; } = "ismatches";
public bool CanAutoDetect { get; set; }
public bool TryEvaluateFormat(IFormattingInfo formattingInfo)
{
//IL_0178: Unknown result type (might be due to invalid IL or missing references)
//IL_017f: Expected O, but got Unknown
if (formattingInfo.CurrentValue == null)
{
return false;
}
string pattern = formattingInfo.FormatterOptions.Replace("\n", "\\n");
Format format = formattingInfo.Format;
IList<Format> list = ((format != null) ? format.Split('|') : null);
if (list == null || list.Count != 2)
{
if (list != null && list.Count == 0)
{
return true;
}
Placeholder placeholder = formattingInfo.Placeholder;
if (string.IsNullOrEmpty((placeholder != null) ? placeholder.FormatterName : null))
{
return false;
}
Placeholder placeholder2 = formattingInfo.Placeholder;
throw new FormatException("Formatter named '" + ((placeholder2 != null) ? placeholder2.FormatterName : null) + "' requires at least 2 format options.");
}
MatchCollection matchCollection = Regex.Matches(formattingInfo.CurrentValue.ToString(), pattern, RegexOptions.Multiline, TimeSpan.FromMilliseconds(500.0));
if (matchCollection.Count == 0)
{
formattingInfo.FormatAsChild(list[1], formattingInfo.CurrentValue);
return true;
}
List<string> list2 = matchCollection.SelectMany((Match m) => m.Groups.Select((Group g) => g.Value)).ToList();
int num = list2.Count / matchCollection.Count;
for (int num2 = list2.Count - num; num2 >= 0; num2 -= num)
{
list2.RemoveAt(num2);
}
foreach (FormatItem item in list[0].Items)
{
Placeholder val = (Placeholder)(object)((item is Placeholder) ? item : null);
if (val != null)
{
KeyValuePair<string, object> keyValuePair = new KeyValuePair<string, object>("m", list2);
Format(formattingInfo, val, keyValuePair);
continue;
}
LiteralText val2 = (LiteralText)item;
Format format2 = formattingInfo.Format;
Format val3 = ((format2 != null) ? format2.Substring(((FormatItem)val2).StartIndex - ((FormatItem)formattingInfo.Format).StartIndex, ((FormatItem)val2).Length) : null);
try
{
if (val3 != null)
{
formattingInfo.FormatAsChild(val3, formattingInfo.CurrentValue);
}
}
finally
{
((IDisposable)val3)?.Dispose();
}
}
return true;
}
private void Format(IFormattingInfo formattingInfo, Placeholder placeholder, object matchingGroupValues)
{
Format format = formattingInfo.Format;
Format val = ((format != null) ? format.Substring(((FormatItem)placeholder).StartIndex - ((FormatItem)formattingInfo.Format).StartIndex, ((FormatItem)placeholder).Length) : null);
try
{
if (val == null)
{
return;
}
if (placeholder.GetSelectors().Count > 0)
{
Selector obj = placeholder.GetSelectors()[0];
if (((obj != null) ? ((FormatItem)obj).RawText : null) == "m")
{
formattingInfo.FormatAsChild(val, matchingGroupValues);
return;
}
}
formattingInfo.FormatAsChild(val, formattingInfo.CurrentValue);
}
finally
{
((IDisposable)val)?.Dispose();
}
}
}
internal class IsMatchFormatterEx : IFormatter
{
private const char c_SplitChar = '|';
public string Name { get; set; } = "ismatch";
public bool CanAutoDetect { get; set; }
public bool TryEvaluateFormat(IFormattingInfo formattingInfo)
{
//IL_0159: Unknown result type (might be due to invalid IL or missing references)
//IL_0160: Expected O, but got Unknown
if (formattingInfo.CurrentValue == null)
{
return false;
}
string pattern = formattingInfo.FormatterOptions.Replace("\n", "\\n");
Format format = formattingInfo.Format;
IList<Format> list = ((format != null) ? format.Split('|') : null);
if (list == null || list.Count != 2)
{
if (list != null && list.Count == 0)
{
return true;
}
Placeholder placeholder = formattingInfo.Placeholder;
if (string.IsNullOrEmpty((placeholder != null) ? placeholder.FormatterName : null))
{
return false;
}
Placeholder placeholder2 = formattingInfo.Placeholder;
throw new FormatException("Formatter named '" + ((placeholder2 != null) ? placeholder2.FormatterName : null) + "' requires at least 2 format options.");
}
Match match = Regex.Match(formattingInfo.CurrentValue.ToString(), pattern, RegexOptions.Multiline, TimeSpan.FromMilliseconds(500.0));
if (!match.Success)
{
formattingInfo.FormatAsChild(list[1], formattingInfo.CurrentValue);
return true;
}
List<string> list2 = (from Group grp in match.Groups
select grp.Value).ToList();
list2.RemoveAt(0);
foreach (FormatItem item in list[0].Items)
{
Placeholder val = (Placeholder)(object)((item is Placeholder) ? item : null);
if (val != null)
{
KeyValuePair<string, object> keyValuePair = new KeyValuePair<string, object>("m", list2);
Format(formattingInfo, val, keyValuePair);
continue;
}
LiteralText val2 = (LiteralText)item;
Format format2 = formattingInfo.Format;
Format val3 = ((format2 != null) ? format2.Substring(((FormatItem)val2).StartIndex - ((FormatItem)formattingInfo.Format).StartIndex, ((FormatItem)val2).Length) : null);
try
{
if (val3 != null)
{
formattingInfo.FormatAsChild(val3, formattingInfo.CurrentValue);
}
}
finally
{
((IDisposable)val3)?.Dispose();
}
}
return true;
}
private void Format(IFormattingInfo formattingInfo, Placeholder placeholder, object matchingGroupValues)
{
Format format = formattingInfo.Format;
Format val = ((format != null) ? format.Substring(((FormatItem)placeholder).StartIndex - ((FormatItem)formattingInfo.Format).StartIndex, ((FormatItem)placeholder).Length) : null);
try
{
if (val == null)
{
return;
}
if (placeholder.GetSelectors().Count > 0)
{
Selector obj = placeholder.GetSelectors()[0];
if (((obj != null) ? ((FormatItem)obj).RawText : null) == "m")
{
formattingInfo.FormatAsChild(val, matchingGroupValues);
return;
}
}
formattingInfo.FormatAsChild(val, formattingInfo.CurrentValue);
}
finally
{
((IDisposable)val)?.Dispose();
}
}
}
internal class ReplaceNewLinesSource : Source
{
public override bool TryEvaluateSelector(ISelectorInfo selectorInfo)
{
if (selectorInfo.CurrentValue is string text && selectorInfo.SelectorText.Equals("NewLines"))
{
selectorInfo.Result = text.Replace("\\n", "\n");
return true;
}
return false;
}
}
internal class SelectorTextToStringSource : Source
{
public override bool TryEvaluateSelector(ISelectorInfo selectorInfo)
{
if (selectorInfo.SelectorText.StartsWith('"') && selectorInfo.SelectorText.EndsWith('"'))
{
string selectorText = selectorInfo.SelectorText;
selectorInfo.Result = selectorText.Substring(1, selectorText.Length - 1 - 1);
return true;
}
return false;
}
}
internal class StringToNumberSource : Source
{
public override bool TryEvaluateSelector(ISelectorInfo selectorInfo)
{
if (!(selectorInfo.CurrentValue is string value))
{
return false;
}
if (!selectorInfo.SelectorText.Equals("ToNumber"))
{
return false;
}
selectorInfo.Result = Convert.ToInt64(value);
return true;
}
}
internal class TranslationSource : Source
{
public override bool TryEvaluateSelector(ISelectorInfo selectorInfo)
{
if (selectorInfo.CurrentValue is string key && selectorInfo.SelectorText.Equals("Translate"))
{
selectorInfo.Result = Translation.GetLocalizedText(key);
return true;
}
return false;
}
}
}
namespace RTLC.Translations
{
[HarmonyPatch]
[HarmonyPriority(300)]
internal static class Patch_LoadStringBasic
{
[HarmonyTargetMethods]
public static IEnumerable<MethodBase> EnumeratePatchingMethods()
{
yield return AccessTools.Method(typeof(SteamValveHazard), "Update", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(ShipTeleporter), "Update", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(ElevatorAnimationEvents), "ElevatorFullyRunning", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(PlayerControllerB), "ConnectClientToPlayerObject", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(Terminal), "TextPostProcess", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(ChallengeLeaderboardSlot), "SetSlotValues", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(DeleteFileButton), "SetFileToDelete", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(SettingsOption), "ToggleEnabledImage", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(KepRemapPanel), "LoadKeybindsUI", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(SaveFileUISlot), "OnEnable", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(ShipBuildModeManager), "CreateGhostObjectAndHighlight", (Type[])null, (Type[])null);
yield return AccessTools.EnumeratorMoveNext((MethodBase)AccessTools.Method(typeof(ManualCameraRenderer), "updateMapTarget", (Type[])null, (Type[])null));
yield return AccessTools.Method(typeof(IngamePlayerSettings), "RefreshAndDisplayCurrentMicrophone", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(IngamePlayerSettings), "SetMicPushToTalk", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(IngamePlayerSettings), "SwitchMicrophoneSetting", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(IngamePlayerSettings), "UpdateMicPushToTalkButton", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(IngamePlayerSettings), "SetChangesNotAppliedTextVisible", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(HUDManager), "ChangeControlTipMultiple", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(HUDManager), "ScanNewCreatureServerRpc", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(HUDManager), "ScanNewCreatureClientRpc", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(HUDManager), "GetNewStoryLogServerRpc", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(HUDManager), "GetNewStoryLogClientRpc", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(HUDManager), "ApplyPenalty", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(HUDManager), "DisplayNewScrapFound", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(HUDManager), "DisplayNewDeadline", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(HUDManager), "FillEndGameStats", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(HUDManager), "SetShipLeaveEarlyVotesText", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(HUDManager), "Update", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(HUDManager), "SetSpectatingTextToPlayer", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(HUDManager), "DisplayCreditsEarning", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(StartOfRound), "SetMapScreenInfoToCurrentLevel", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(StartOfRound), "EndGameClientRpc", (Type[])null, (Type[])null);
yield return AccessTools.EnumeratorMoveNext((MethodBase)AccessTools.Method(typeof(StartOfRound), "openingDoorsSequence", (Type[])null, (Type[])null));
yield return AccessTools.Method(typeof(StartOfRound), "SceneManager_OnLoad", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(StartOfRound), "SceneManager_OnLoadComplete1", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(PreInitSceneScript), "PressContinueButton", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(PreInitSceneScript), "SkipToFinalSetting", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(MenuManager), "StartAClient", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(MenuManager), "ConfirmHostButton", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(MenuManager), "HostSetLobbyPublic", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(MenuManager), "DisplayLeaderboardSlots", (Type[])null, (Type[])null);
yield return AccessToolsHelper.AsyncMoveNext(typeof(MenuManager), "GetLeaderboardForChallenge");
yield return AccessToolsHelper.AsyncMoveNext(typeof(SteamLobbyManager), "LoadServerList");
yield return AccessTools.Method(typeof(TimeOfDay), "UpdateProfitQuotaCurrentTime", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(RoundManager), "GenerateNewLevelClientRpc", (Type[])null, (Type[])null);
}
[HarmonyILManipulator]
public static void ReplaceText(ILContext context, MethodBase? originalMethod)
{
ILContextHelper.PatchModsPrefixesAndPostfixes(originalMethod, LoadStringPatch.ReplaceLoadStringWithTranslatedMethod);
LoadStringPatch.ReplaceLoadStringWithTranslated(context);
}
}
[HarmonyPatch]
[HarmonyPriority(299)]
internal static class Patch_ReplaceStringFormat
{
[HarmonyTargetMethods]
public static IEnumerable<MethodBase> GetPatchingMethods()
{
yield return AccessTools.Method(typeof(HUDManager), "DisplayDaysLeft", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(TimeOfDay), "UpdateProfitQuotaCurrentTime", (Type[])null, (Type[])null);
}
[HarmonyILManipulator]
public static void ReplaceFormat(ILContext context, MethodBase originalMethod)
{
ILContextHelper.PatchModsPrefixesAndPostfixes(originalMethod, LoadStringPatch.ReplaceLoadStringWithTranslatedMethod);
ReplaceStringFormatPatch.ReplaceStringFormatToTranslationFormat(context);
}
}
}
namespace RTLC.Translations.Specific
{
[HarmonyPatch(typeof(HUDManager))]
internal static class Patch_HUDManager_Tips
{
[HarmonyPatch("ChangeControlTip")]
[HarmonyPrefix]
public static void ChangeControlTip(ref string changeTo)
{
changeTo = Translation.GetLocalizedText(changeTo);
}
[HarmonyPatch("ChangeControlTipMultiple")]
[HarmonyPrefix]
public static void ChangeControlTipMultiple(string[] allLines)
{
if (allLines != null)
{
for (int i = 0; i < allLines.Length; i++)
{
allLines[i] = Translation.GetLocalizedText(allLines[i]);
}
}
}
[HarmonyPatch("ChangeControlTipMultiple")]
[HarmonyTranspiler]
public static IEnumerable<CodeInstruction> RemoveItemNameInDrop(IEnumerable<CodeInstruction> instructions)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Expected O, but got Unknown
CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null);
FieldInfo itemNameField = AccessTools.Field(typeof(Item), "itemName");
val.SearchForward((Func<CodeInstruction, bool>)((CodeInstruction c) => CodeInstructionExtensions.LoadsField(c, itemNameField, false))).SetOperandAndAdvance((object)AccessTools.Field(typeof(string), "Empty"));
return val.InstructionEnumeration();
}
[HarmonyPatch("DisplayTip")]
[HarmonyPrefix]
public static void DisplayTip(ref string headerText, ref string bodyText)
{
headerText = Translation.GetLocalizedText(headerText);
bodyText = Translation.GetLocalizedText(bodyText);
}
}
[HarmonyPatch]
internal static class Patch_HUDManager_UpdateScanNodes
{
[HarmonyTargetMethod]
public static MethodBase GetPatchingMethod()
{
if (Chainloader.PluginInfos.TryGetValue("HDLethalCompany", out var _))
{
MethodInfo methodInfo = AccessTools.Method("HDLethalCompany.Patch.GraphicsPatch:UpdateScanNodesPostfix", (Type[])null, (Type[])null);
if (methodInfo != null)
{
return methodInfo;
}
}
return AccessTools.Method(typeof(HUDManager), "UpdateScanNodes", (Type[])null, (Type[])null);
}
[HarmonyILManipulator]
public static void ReplaceText(ILContext ctx)
{
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Expected O, but got Unknown
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
FieldInfo headerTextField = AccessTools.Field(typeof(ScanNodeProperties), "headerText");
FieldInfo subTextField = AccessTools.Field(typeof(ScanNodeProperties), "subText");
ILCursor val = new ILCursor(ctx);
while (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
{
(Instruction c) => ILPatternMatchingExt.MatchLdfld(c, headerTextField) || ILPatternMatchingExt.MatchLdfld(c, subTextField)
}))
{
val.Emit(OpCodes.Call, (MethodBase)SymbolExtensions.GetMethodInfo((Expression<Action>)(() => Translation.GetLocalizedText(null))));
int index = val.Index;
val.Index = index + 1;
}
}
}
[HarmonyPatch(typeof(KepRemapPanel), "OnEnable")]
internal static class Patch_KepRemapPanel_OnEnable
{
[HarmonyPrefix]
public static void TranslateKeybinds(KepRemapPanel __instance)
{
if (__instance.remappableKeys == null)
{
return;
}
foreach (RemappableKey remappableKey in __instance.remappableKeys)
{
if (remappableKey != null)
{
remappableKey.ControlName = Translation.GetLocalizedText(remappableKey.ControlName);
}
}
}
}
[HarmonyPatch(typeof(LobbySlot), "Awake")]
internal static class Patch_LobbySlot_Awake
{
[HarmonyPrefix]
public static void ReplaceText(LobbySlot __instance)
{
Transform val = ((Component)__instance).transform.Find("JoinButton");
if (!((Object)(object)val == (Object)null))
{
TextMeshProUGUI componentInChildren = ((Component)val).GetComponentInChildren<TextMeshProUGUI>();
if ((Object)(object)componentInChildren != (Object)null)
{
((TMP_Text)componentInChildren).text = Translation.GetLocalizedText(((TMP_Text)componentInChildren).text);
}
}
}
}
[HarmonyPatch(typeof(PlayerControllerB), "SetHoverTipAndCurrentInteractTrigger")]
internal static class Patch_PlayerControllerB_SetHoverTipAndCurrentInteractTrigger
{
[HarmonyTranspiler]
public static IEnumerable<CodeInstruction> ReplaceText(IEnumerable<CodeInstruction> instructions)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Expected O, but got Unknown
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Expected O, but got Unknown
CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null);
FieldInfo cursorTipField = AccessTools.Field(typeof(PlayerControllerB), "cursorTip");
MethodInfo getTextProperty = AccessTools.PropertyGetter(typeof(TMP_Text), "text");
val.MatchForward(false, (CodeMatch[])(object)new CodeMatch[1]
{
new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction c) => CodeInstructionExtensions.LoadsField(c, cursorTipField, false)), (string)null)
}).Repeat((Action<CodeMatcher>)delegate(CodeMatcher m)
{
CodeInstruction val2 = m.InstructionAt(1);
if (val2.opcode == OpCodes.Ldstr)
{
val2.operand = Translation.GetLocalizedText((string)val2.operand);
m.Advance(1);
}
else if (CodeInstructionExtensions.Calls(val2, getTextProperty) || val2.opcode == OpCodes.Ldloc || val2.opcode == OpCodes.Ldloc_S)
{
m.Advance(1);
}
else
{
CodeInstruction val3 = m.InstructionAt(2);
if (CodeInstructionExtensions.LoadsField(val3, cursorTipField, false))
{
m.Advance(4);
}
else
{
m.Advance(3).Insert((CodeInstruction[])(object)new CodeInstruction[1] { CodeInstruction.Call((Expression<Action>)(() => Translation.GetLocalizedText(string.Empty))) });
}
}
}, (Action<string>)null);
return val.InstructionEnumeration();
}
}
[HarmonyPatch(typeof(StartOfRound), "Awake")]
internal static class Patch_StartOfRound_Awake
{
[HarmonyPostfix]
[HarmonyPriority(0)]
public static void TranslateLevelDescription(StartOfRound __instance)
{
SelectableLevel[] levels = __instance.levels;
if (levels == null)
{
return;
}
SelectableLevel[] array = levels;
foreach (SelectableLevel val in array)
{
if (!((Object)(object)val == (Object)null))
{
val.LevelDescription = Translation.GetLocalizedText(val.LevelDescription);
}
}
}
}
[HarmonyPatch(typeof(Terminal))]
[HarmonyPriority(0)]
internal static class Patch_Terminal_Awake
{
private static bool s_Initialized;
[HarmonyPatch("Awake")]
[HarmonyPostfix]
[HarmonyWrapSafe]
public static void TranslateNodes(Terminal __instance)
{
if (s_Initialized)
{
return;
}
HashSet<TerminalNode> hashSet = new HashSet<TerminalNode>();
IEnumerable<TerminalNode> enumerable = __instance.terminalNodes.allKeywords.SelectMany(delegate(TerminalKeyword tk)
{
IEnumerable<TerminalNode> source = tk.compatibleNouns?.Select((CompatibleNoun c) => c.result) ?? Array.Empty<TerminalNode>();
return source.Append(tk.specialKeywordResult);
}).Concat(__instance.terminalNodes.specialNodes).Concat(__instance.terminalNodes.terminalNodes);
foreach (TerminalNode item in enumerable)
{
if ((Object)(object)item == (Object)null || !hashSet.Add(item))
{
continue;
}
item.displayText = Translation.GetLocalizedText(GetTerminalNodeName(item), item.displayText, shouldIgnoreKey: false);
CompatibleNoun[] terminalOptions = item.terminalOptions;
if (terminalOptions == null)
{
continue;
}
CompatibleNoun[] array = terminalOptions;
foreach (CompatibleNoun val in array)
{
if (val != null && !((Object)(object)val.result == (Object)null) && hashSet.Add(val.result))
{
val.result.displayText = Translation.GetLocalizedText(GetTerminalNodeName(val.result), val.result.displayText, shouldIgnoreKey: false);
}
}
}
s_Initialized = true;
}
private static string GetTerminalNodeName(TerminalNode node)
{
string name = ((Object)node).name;
if (!string.IsNullOrWhiteSpace(name))
{
return name;
}
return node.displayText;
}
[HarmonyPatch("TextPostProcess")]
[HarmonyPostfix]
public static void ReplaceTimeOfDay(ref string __result)
{
string newValue = DateTime.Now.DayOfWeek switch
{
DayOfWeek.Monday => "Счастливого понедельника",
DayOfWeek.Tuesday => "Счастливого вторника",
DayOfWeek.Wednesday => "Счастливой среды",
DayOfWeek.Thursday => "Счастливого четверга",
DayOfWeek.Friday => "Счастливой пятницы",
DayOfWeek.Saturday => "Счастливой субботы",
DayOfWeek.Sunday => "Счастливого воскресенья",
_ => string.Empty,
};
__result = __result.Replace("[currentDayRussian]", newValue);
}
}
}
namespace RTLC.Patches
{
[HarmonyPatch(typeof(HUDManager))]
internal static class Patch_HUDManager
{
[HarmonyPatch("SetClock")]
[HarmonyPrefix]
private static bool ShowClockIn24Hour(float timeNormalized, float numberOfHours, out string __result)
{
int num = (int)(timeNormalized * (60f * numberOfHours)) + 360;
string text = $"{num / 60:00}:{num % 60:00}";
((TMP_Text)HUDManager.Instance.clockNumber).text = (__result = text);
return false;
}
[HarmonyPatch("Update")]
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> ShowKilograms(IEnumerable<CodeInstruction> instructions)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Expected O, but got Unknown
CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null);
val.Start().SearchForward((Func<CodeInstruction, bool>)((CodeInstruction c) => c.opcode == OpCodes.Ldc_R4 && (float)c.operand == 105f)).Operand = 47.627197f;
val.SearchForward((Func<CodeInstruction, bool>)((CodeInstruction c) => c.opcode == OpCodes.Ldstr && (string)c.operand == "{0} lb")).Operand = "{0} кг";
val.SearchForward((Func<CodeInstruction, bool>)((CodeInstruction c) => c.opcode == OpCodes.Ldc_R4 && (float)c.operand == 130f)).Operand = 58.967007f;
return val.InstructionEnumeration();
}
}
}
namespace RTLC.Patches.Translations
{
internal static class Patch_ReplaceStringConcat
{
[HarmonyTargetMethods]
public static IEnumerable<MethodBase> GetPatchingMethods()
{
yield break;
}
[HarmonyILManipulator]
public static void ReplaceFormat(ILContext context, MethodBase originalMethod)
{
ILContextHelper.PatchModsPrefixesAndPostfixes(originalMethod, LoadStringPatch.ReplaceLoadStringWithTranslatedMethod);
ReplaceStringConcatPatch.ReplaceStringConcatToTranslationFormat(context);
}
}
}
namespace RTLC.Patches.Translations.Specific
{
[HarmonyPatch(typeof(HUDManager), "DisplayStatusEffect")]
[HarmonyPriority(0)]
internal static class Patch_HUDManager_DisplayStatusEffect
{
[HarmonyPatch]
[HarmonyPrefix]
public static void DisplayStatusEffect(ref string statusEffect)
{
statusEffect = Translation.GetLocalizedText(statusEffect);
}
}
[HarmonyPatch(typeof(HUDManager), "Start")]
[HarmonyPriority(0)]
internal static class Patch_HUDManager_PlayerLevels
{
[HarmonyPatch]
[HarmonyPostfix]
public static void TranslatePlayerLevels(HUDManager __instance)
{
PlayerLevel[] playerLevels = __instance.playerLevels;
foreach (PlayerLevel val in playerLevels)
{
if (val != null)
{
val.levelName = Translation.GetLocalizedText(val.levelName);
}
}
}
}
[HarmonyPatch(typeof(HUDManager))]
internal static class Patch_HUDManager_ReadOutDialogue
{
[HarmonyPatch("ReadDialogue")]
[HarmonyPrefix]
public static void ReadDialogue(DialogueSegment[] dialogueArray)
{
if (dialogueArray == null)
{
return;
}
foreach (DialogueSegment val in dialogueArray)
{
if (val == null)
{
break;
}
val.bodyText = Translation.GetLocalizedText(val.bodyText);
val.speakerText = Translation.GetLocalizedText(val.speakerText);
}
}
}
}
namespace RTLC.Mods.ShipLoot
{
[HarmonyPatch]
internal class Patch_ShipLoot_OnScan
{
[HarmonyPrepare]
public static bool CheckModLoaded()
{
return ModHelper.TryFindMethod("com.github.tinyhoot.ShipLoot", "ShipLoot.Patches.HudManagerPatcher", "OnScan");
}
[HarmonyTargetMethod]
public static MethodBase GetMethodPatch()
{
return ModHelper.GetMethod();
}
[HarmonyILManipulator]
public static void ReplaceString(ILContext context)
{
LoadStringPatch.ReplaceLoadStringWithTranslated(context);
}
}
}
namespace RTLC.Helpers
{
internal static class AccessToolsHelper
{
public static MethodInfo AsyncMoveNext(Type type, string name)
{
MethodInfo methodInfo = AccessTools.Method(type, name, (Type[])null, (Type[])null);
if ((object)methodInfo == null)
{
return null;
}
AsyncStateMachineAttribute customAttribute = methodInfo.GetCustomAttribute<AsyncStateMachineAttribute>();
if (customAttribute == null)
{
return null;
}
Type stateMachineType = customAttribute.StateMachineType;
MethodInfo methodInfo2 = AccessTools.DeclaredMethod(stateMachineType, "MoveNext", (Type[])null, (Type[])null);
if ((object)methodInfo2 == null)
{
return null;
}
return methodInfo2;
}
}
internal static class ILContextHelper
{
private static readonly HashSet<Type> s_IgnoredTypes = new HashSet<Type>
{
typeof(Debug),
typeof(Animation),
typeof(Animator),
typeof(Regex),
typeof(CustomMessagingManager),
typeof(ManualLogSource),
typeof(AssetBundle),
typeof(GameObject),
typeof(Transform),
typeof(Path),
typeof(Directory),
typeof(File),
typeof(FileStream),
typeof(ConfigFile),
typeof(ConfigDescription),
typeof(ES3),
typeof(LobbyQuery)
};
private static readonly HashSet<string> s_IgnoredTypeNames = s_IgnoredTypes.Select((Type t) => t.FullName).ToHashSet();
private static readonly HashSet<MethodInfo> s_IgnoredMethods = new HashSet<MethodInfo> { AccessTools.PropertySetter(typeof(Object), "name") };
private static readonly string[] s_IgnoredMethodsNames = s_IgnoredMethods.Select((MethodInfo t) => t.GetFullName()).Concat(new <>z__ReadOnlyArray<string>(new string[4] { "Log", "SpawnPrefab", "System.Boolean System.String::Equals(System.String", "System.Boolean System.String::Contains(System.String" })).ToArray();
public static bool TestIgnore(ILCursor cursor)
{
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: 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_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: Expected O, but got Unknown
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
int index = cursor.Index;
bool result = false;
int num = 0;
for (int i = index; i < cursor.Instrs.Count; i++)
{
Instruction val = cursor.Instrs[i];
if (val.OpCode == OpCodes.Ldstr)
{
num++;
continue;
}
if (val.OpCode == OpCodes.Stfld)
{
result = true;
break;
}
if (val.OpCode == OpCodes.Call || val.OpCode == OpCodes.Callvirt)
{
MethodReference val2 = (MethodReference)val.Operand;
if (s_IgnoredTypeNames.Contains(((MemberReference)((MemberReference)val2).DeclaringType).FullName))
{
result = true;
break;
}
if (IsMethodIgnored(val2))
{
result = true;
break;
}
int num2 = (((IEnumerable<ParameterDefinition>)val2.Parameters).Any((ParameterDefinition p) => Extensions.Is((MemberReference)(object)((ParameterReference)p).ParameterType, "System.String[]")) ? 99 : ((IEnumerable<ParameterDefinition>)val2.Parameters).Count((ParameterDefinition p) => Extensions.Is((MemberReference)(object)((ParameterReference)p).ParameterType, "System.String")));
TypeReference returnType = val2.ReturnType;
bool flag = returnType != null && Extensions.Is((MemberReference)(object)returnType, "System.String");
num = Mathf.Clamp(num - num2, 0, 10);
if (flag)
{
num++;
}
if (num == 0)
{
break;
}
}
}
cursor.Index = index;
return result;
}
public static void PatchModsPrefixesAndPostfixes(MethodBase? originalMethod, MethodInfo ilManipulatorPatch)
{
if (originalMethod == null || originalMethod.DeclaringType.Assembly == typeof(ILContextHelper).Assembly)
{
return;
}
Patches patchInfo = Harmony.GetPatchInfo(originalMethod);
if (patchInfo == null)
{
return;
}
foreach (Patch item in patchInfo.Prefixes.Concat(patchInfo.Postfixes))
{
if (!(item.PatchMethod.DeclaringType.Assembly == typeof(ILContextHelper).Assembly) && !(item.PatchMethod.ReturnType != typeof(bool)))
{
Patches patchInfo2 = Harmony.GetPatchInfo((MethodBase)item.PatchMethod);
if (patchInfo2 != null && patchInfo2.Owners.Contains("RTLC"))
{
RTLCPlugin.Instance.Logger.LogInfo((object)("Ignored patching of " + item.PatchMethod.GetReadableString() + " due to already patched"));
continue;
}
RTLCPlugin.Instance.Logger.LogInfo((object)("Patching " + item.PatchMethod.GetReadableString()));
RTLCPlugin.Instance.Harmony.CreateProcessor((MethodBase)item.PatchMethod).AddILManipulator(ilManipulatorPatch).Patch();
}
}
}
private static bool IsMethodIgnored(MethodReference method)
{
string fullName = ((MemberReference)method).FullName;
if ((fullName == "System.Boolean System.String::op_Inequality(System.String,System.String)" || fullName == "System.Boolean System.String::op_Equality(System.String,System.String)") ? true : false)
{
return true;
}
string name = ((MemberReference)method).Name;
for (int i = 0; i < s_IgnoredMethodsNames.Length; i++)
{
if (name.StartsWith(s_IgnoredMethodsNames[i], StringComparison.OrdinalIgnoreCase) || fullName.StartsWith(s_IgnoredMethodsNames[i], StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
return false;
}
}
internal static class ModHelper
{
private static MethodInfo? s_MethodToPatch;
public static bool TryFindMethod(string modId, string type, string method)
{
if (!Chainloader.PluginInfos.TryGetValue(modId, out var value))
{
return false;
}
Assembly assembly = ((object)value.Instance).GetType().Assembly;
Type type2 = assembly.GetType(type, throwOnError: false);
s_MethodToPatch = AccessTools.Method(type2, method, (Type[])null, (Type[])null);
return s_MethodToPatch != null;
}
public static MethodBase GetMethod()
{
return s_MethodToPatch;
}
}
}
namespace RTLC.Extensions
{
internal static class MethodBaseExtensions
{
public static string GetReadableString(this MethodBase method)
{
Type declaringType = method.DeclaringType;
string text = ((declaringType.Namespace == null) ? string.Empty : (declaringType.Namespace + "."));
return text + declaringType.Name + "::" + method.Name;
}
public static string GetFullName(this MethodInfo method)
{
Type returnType = method.ReturnType;
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(returnType.FullName);
stringBuilder.Append(' ');
stringBuilder.Append(method.GetReadableString());
stringBuilder.Append('(');
ParameterInfo[] parameters = method.GetParameters();
for (int i = 0; i < parameters.Length; i++)
{
ParameterInfo parameterInfo = parameters[i];
if (i > 0)
{
stringBuilder.Append(",");
}
stringBuilder.Append(parameterInfo.ParameterType.FullName);
}
stringBuilder.Append(')');
return stringBuilder.ToString();
}
}
}
namespace RTLC.API
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
internal class InitializeOnAwakeAttribute : Attribute
{
}
internal static class LoadStringPatch
{
public static readonly MethodInfo ReplaceLoadStringWithTranslatedMethod = typeof(LoadStringPatch).GetMethod("ReplaceLoadStringWithTranslated", AccessTools.all);
public static void ReplaceLoadStringWithTranslated(ILContext context)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Expected O, but got Unknown
ILCursor val = new ILCursor(context);
while (val.TryGotoNext(new Func<Instruction, bool>[1]
{
(Instruction i) => i.OpCode == OpCodes.Ldstr
}))
{
if (ILContextHelper.TestIgnore(val))
{
int index = val.Index;
val.Index = index + 1;
}
else
{
val.Next.Operand = Translation.GetLocalizedText((string)val.Next.Operand);
int index = val.Index;
val.Index = index + 1;
}
}
}
}
internal static class ReplaceStringConcatPatch
{
public static readonly MethodInfo ReplaceLoadStringWithTranslatedMethod = typeof(ReplaceStringConcatPatch).GetMethod("ReplaceStringConcatPatch", AccessTools.all);
public static void ReplaceStringConcatToTranslationFormat(ILContext context)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Expected O, but got Unknown
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Expected O, but got Unknown
ILCursor val = new ILCursor(context);
string corLibStringTypeFullName = typeof(string).FullName;
while (val.TryGotoNext(new Func<Instruction, bool>[1]
{
delegate(Instruction i)
{
object operand = i.Operand;
MethodReference val4 = (MethodReference)((operand is MethodReference) ? operand : null);
return val4 != null && ((MemberReference)((MemberReference)val4).DeclaringType).FullName == corLibStringTypeFullName && ((MemberReference)val4).Name.Equals("Concat");
}
}))
{
int index;
if (ILContextHelper.TestIgnore(val))
{
index = val.Index;
val.Index = index + 1;
continue;
}
MethodReference val2 = (MethodReference)val.Next.Operand;
Collection<ParameterDefinition> parameters = val2.Parameters;
Collection<ParameterDefinition> val3 = parameters;
if (val3 == null)
{
goto IL_01be;
}
MethodInfo methodInfo;
if (parameters.Count == 2)
{
methodInfo = SymbolExtensions.GetMethodInfo((Expression<Action>)(() => Translation.Concat(null, null)));
}
else if (parameters.Count == 3)
{
methodInfo = SymbolExtensions.GetMethodInfo((Expression<Action>)(() => Translation.Concat(null, null, null)));
}
else
{
if (parameters.Count != 4)
{
goto IL_01be;
}
methodInfo = SymbolExtensions.GetMethodInfo((Expression<Action>)(() => Translation.Concat(null, null, null, null)));
}
goto IL_0207;
IL_0207:
MethodInfo methodInfo2 = methodInfo;
val.Next.Operand = context.Import((MethodBase)methodInfo2);
index = val.Index;
val.Index = index + 1;
continue;
IL_01be:
methodInfo = SymbolExtensions.GetMethodInfo((Expression<Action>)(() => Translation.Concat()));
goto IL_0207;
}
}
}
internal static class ReplaceStringFormatPatch
{
public static readonly MethodInfo ReplaceLoadStringWithTranslatedMethod = typeof(ReplaceStringFormatPatch).GetMethod("ReplaceStringFormatToTranslationFormat", AccessTools.all);
public static void ReplaceStringFormatToTranslationFormat(ILContext context)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Expected O, but got Unknown
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Expected O, but got Unknown
ILCursor cursor = new ILCursor(context);
string corLibStringTypeFullName = typeof(string).FullName;
while (cursor.TryGotoNext(new Func<Instruction, bool>[1]
{
delegate(Instruction i)
{
object operand = i.Operand;
MethodReference val3 = (MethodReference)((operand is MethodReference) ? operand : null);
return val3 != null && ((MemberReference)((MemberReference)val3).DeclaringType).FullName == corLibStringTypeFullName && ((MemberReference)val3).Name.Equals("Format");
}
}))
{
int index;
if (ILContextHelper.TestIgnore(cursor))
{
ILCursor obj = cursor;
index = obj.Index;
obj.Index = index + 1;
continue;
}
MethodReference val = (MethodReference)cursor.Next.Operand;
Collection<ParameterDefinition> parameters = val.Parameters;
Collection<ParameterDefinition> val2 = parameters;
if (val2 == null)
{
goto IL_01fb;
}
MethodInfo methodInfo;
if (parameters.Count == 3)
{
methodInfo = SymbolExtensions.GetMethodInfo((Expression<Action>)(() => Translation.Format(null, null, null)));
}
else if (parameters.Count == 4)
{
methodInfo = SymbolExtensions.GetMethodInfo((Expression<Action>)(() => Translation.Format(null, null, null, null)));
}
else
{
if (!((IEnumerable<CustomAttribute>)parameters[1].CustomAttributes).Any((CustomAttribute a) => ((MemberReference)((MemberReference)a.Constructor).DeclaringType).FullName == typeof(ParamArrayAttribute).FullName))
{
goto IL_01fb;
}
methodInfo = SymbolExtensions.GetMethodInfo((Expression<Action>)(() => Translation.Format(null, null)));
}
goto IL_025c;
IL_01fb:
methodInfo = SymbolExtensions.GetMethodInfo((Expression<Action>)(() => Translation.Format(null, cursor)));
goto IL_025c;
IL_025c:
MethodInfo methodInfo2 = methodInfo;
cursor.Next.Operand = context.Import((MethodBase)methodInfo2);
ILCursor obj2 = cursor;
index = obj2.Index;
obj2.Index = index + 1;
}
}
}
}
namespace RTLC.API.LethalExpansion
{
internal static class LethalExpansionTranslation
{
public static void TryAddScrapsToUntranslated()
{
if (!Chainloader.PluginInfos.ContainsKey("LethalExpansion") && !Chainloader.PluginInfos.ContainsKey("com.github.lethalmods.lethalexpansioncore"))
{
return;
}
try
{
Type type = AccessTools.TypeByName("LethalExpansionCore.Utils.AssetBundlesManager");
object obj = AccessTools.PropertyGetter(type, "Instance").Invoke(null, null);
IDictionary dictionary = (IDictionary)AccessTools.Field(obj.GetType(), "assetBundles").GetValue(obj);
foreach (DictionaryEntry item in dictionary)
{
ITuple tuple = (ITuple)item.Value;
object obj2 = tuple[1];
Console.WriteLine($"Got mod manifest: {item.Key}");
Array array = (Array)AccessTools.Field(obj2.GetType(), "scraps").GetValue(obj2);
foreach (object item2 in array)
{
string key = (string)AccessTools.Field(item2.GetType(), "itemName").GetValue(item2);
key = Translation.GetLocalizedText(key);
Console.WriteLine("Found " + key);
}
}
}
catch (Exception ex)
{
RTLCPlugin.Instance.Logger.LogError((object)ex);
}
}
}
}
internal sealed class <>z__ReadOnlyArray<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T>
{
int ICollection.Count => _items.Length;
bool ICollection.IsSynchronized => false;
object ICollection.SyncRoot => this;
object IList.this[int index]
{
get
{
return _items[index];
}
set
{
throw new NotSupportedException();
}
}
bool IList.IsFixedSize => true;
bool IList.IsReadOnly => true;
int IReadOnlyCollection<T>.Count => _items.Length;
T IReadOnlyList<T>.this[int index] => _items[index];
int ICollection<T>.Count => _items.Length;
bool ICollection<T>.IsReadOnly => true;
T IList<T>.this[int index]
{
get
{
return _items[index];
}
set
{
throw new NotSupportedException();
}
}
public <>z__ReadOnlyArray(T[] items)
{
_items = items;
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)_items).GetEnumerator();
}
void ICollection.CopyTo(Array array, int index)
{
((ICollection)_items).CopyTo(array, index);
}
int IList.Add(object value)
{
throw new NotSupportedException();
}
void IList.Clear()
{
throw new NotSupportedException();
}
bool IList.Contains(object value)
{
return ((IList)_items).Contains(value);
}
int IList.IndexOf(object value)
{
return ((IList)_items).IndexOf(value);
}
void IList.Insert(int index, object value)
{
throw new NotSupportedException();
}
void IList.Remove(object value)
{
throw new NotSupportedException();
}
void IList.RemoveAt(int index)
{
throw new NotSupportedException();
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return ((IEnumerable<T>)_items).GetEnumerator();
}
void ICollection<T>.Add(T item)
{
throw new NotSupportedException();
}
void ICollection<T>.Clear()
{
throw new NotSupportedException();
}
bool ICollection<T>.Contains(T item)
{
return ((ICollection<T>)_items).Contains(item);
}
void ICollection<T>.CopyTo(T[] array, int arrayIndex)
{
((ICollection<T>)_items).CopyTo(array, arrayIndex);
}
bool ICollection<T>.Remove(T item)
{
throw new NotSupportedException();
}
int IList<T>.IndexOf(T item)
{
return ((IList<T>)_items).IndexOf(item);
}
void IList<T>.Insert(int index, T item)
{
throw new NotSupportedException();
}
void IList<T>.RemoveAt(int index)
{
throw new NotSupportedException();
}
}