using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using HarmonyLib.Public.Patching;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("LocalizationCache")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("LocalizationCache")]
[assembly: AssemblyCopyright("Copyright © 2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("FE8B42E3-7082-4DFF-A5CC-6B62B0315ACA")]
[assembly: AssemblyFileVersion("0.3.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.3.0.0")]
[module: UnverifiableCode]
namespace LocalizationCache;
public static class DebugTimingPatch
{
[HarmonyPatch(typeof(Localization), "SetupLanguage")]
[HarmonyPrefix]
[HarmonyPriority(800)]
public static void SetupLanguage_Prefix(Localization __instance, ref Stopwatch __state)
{
__state = Stopwatch.StartNew();
}
[HarmonyPatch(typeof(Localization), "SetupLanguage")]
[HarmonyPostfix]
[HarmonyPriority(0)]
public static void SetupLanguage_Postfix(Localization __instance, ref Stopwatch __state)
{
__state.Stop();
if (Plugin.DebugTiming.Value)
{
Plugin.Log.LogInfo((object)$"Localization.SetupLanguage took {__state.ElapsedMilliseconds}ms");
}
if (Plugin.DebugStacktrace.Value)
{
Plugin.Log.LogInfo((object)$"Localization.SetupLanguage was called\n{new StackTrace()}");
}
}
}
[HarmonyPatch]
public static class LocalizationPatches
{
private static Dictionary<Tuple<string, string>, Dictionary<string, string>> languageTranslations = new Dictionary<Tuple<string, string>, Dictionary<string, string>>();
private static List<Patch> patchedMods = new List<Patch>();
private static MethodInfo LoadCSVMethod { get; } = AccessTools.Method(typeof(Localization), "LoadCSV", (Type[])null, (Type[])null);
[HarmonyPatch(typeof(Localization), "LoadCSV")]
[HarmonyPrefix]
[HarmonyPriority(800)]
public static bool SetupLanguage_Prefix(Localization __instance, TextAsset file, string language, ref bool __result)
{
if (!Object.op_Implicit((Object)(object)file))
{
return true;
}
Tuple<string, string> key = new Tuple<string, string>(((Object)file).name, language);
if (!languageTranslations.TryGetValue(key, out var value))
{
return true;
}
__instance.m_translations = value;
__result = true;
return false;
}
[HarmonyPatch(typeof(Localization), "LoadCSV")]
[HarmonyPostfix]
[HarmonyPriority(0)]
public static void SetupLanguage_Postfix(Localization __instance, TextAsset file, string language, bool __result)
{
if (__result && Object.op_Implicit((Object)(object)file))
{
Tuple<string, string> key = new Tuple<string, string>(((Object)file).name, language);
languageTranslations[key] = __instance.m_translations;
CacheOtherMods();
}
}
private static void CacheOtherMods()
{
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Expected O, but got Unknown
if (!Plugin.CacheMods.Value)
{
return;
}
Patch[] postfixes = PatchManager.ToPatchInfo((MethodBase)LoadCSVMethod).postfixes;
foreach (Patch val in postfixes)
{
if (!(val.owner == "com.maxsch.valheim.LocalizationCache") && !patchedMods.Contains(val))
{
Plugin.harmony.Patch((MethodBase)val.PatchMethod, new HarmonyMethod(typeof(LocalizationPatches), "SkipLoad", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
patchedMods.Add(val);
}
}
}
private static bool SkipLoad()
{
return false;
}
}
[BepInPlugin("com.maxsch.valheim.LocalizationCache", "LocalizationCache", "0.3.0")]
public class Plugin : BaseUnityPlugin
{
public const string ModName = "LocalizationCache";
public const string ModGuid = "com.maxsch.valheim.LocalizationCache";
public const string ModVersion = "0.3.0";
public static ConfigEntry<bool> EnableCache;
public static ConfigEntry<bool> CacheMods;
public static ConfigEntry<bool> DebugTiming;
public static ConfigEntry<bool> DebugStacktrace;
internal static Harmony harmony;
internal static ManualLogSource Log { get; private set; }
private void Awake()
{
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
EnableCache = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Enable Cache", true, "Enable caching of localization files. Disable to compare loading times. Requires a restart to take effect");
CacheMods = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Cache Mods", true, "Cache localization calls from some mods. Breaks switching the language at runtime but can drastically improve loading time. Requires a restart to take effect");
DebugTiming = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Debug", "Log Timing", false, "Log timing information for Localization.SetupLanguage. Requires a restart to take effect");
DebugStacktrace = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Debug", "Log Stacktrace", false, "Log stacktrace for each Localization.SetupLanguage call. Requires a restart to take effect");
harmony = new Harmony("com.maxsch.valheim.LocalizationCache");
if (EnableCache.Value)
{
harmony.PatchAll(typeof(LocalizationPatches));
}
if (DebugTiming.Value || DebugStacktrace.Value)
{
harmony.PatchAll(typeof(DebugTimingPatch));
}
}
}