Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Runeheim Online Modpack v1.0.13
plugins/RUNEHEIM MODS-RuneheimLoadingScreen/RuneheimLoadingScreen.dll
Decompiled 3 days agousing System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Logging; using HarmonyLib; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyVersion("0.0.0.0")] namespace RuneheimLoadingScreen; [BepInPlugin("runeheim.online.loadingscreen", "Runeheim Loading Screen", "0.7.3")] public sealed class RuneheimLoadingScreenPlugin : BaseUnityPlugin { private sealed class ReferenceEqualityComparer : IEqualityComparer<object> { public static readonly ReferenceEqualityComparer Instance = new ReferenceEqualityComparer(); public new bool Equals(object x, object y) { return object.ReferenceEquals(x, y); } public int GetHashCode(object obj) { return RuntimeHelpers.GetHashCode(obj); } } public const string PluginGuid = "runeheim.online.loadingscreen"; public const string PluginName = "Runeheim Loading Screen"; public const string PluginVersion = "0.7.3"; private const string RuneheimIp = "185.216.147.166"; private const string RuneheimPort = "5914"; private const string RuneheimName = "Runeheim Online"; private const string LoadingImageFile = "RuneheimLoading.png"; private const string LoadingLogoFile = "RuneheimLogo.png"; private static ManualLogSource _log; private static bool _destinationKnown; private static bool _destinationIsRuneheim; private static bool _runeheimLoadActive; private static Texture2D _loadingTexture; private static Sprite _loadingSprite; private static Texture2D _logoTexture; private static Sprite _logoSprite; private static Image _swappedLogoImage; private static Sprite _originalLogoSprite; private static bool _logoApplied; private Harmony _harmony; private void Awake() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown _log = ((BaseUnityPlugin)this).Logger; LoadRuneheimAssets(); _harmony = new Harmony("runeheim.online.loadingscreen"); PatchFejdMethod("SetServerToJoin", null, "SetServerToJoinPostfix", 0); PatchFejdMethod("JoinServer", "JoinServerPrefix", null, 800); PatchFejdMethod("OnWorldStart", "OnWorldStartPrefix", null, 800); PatchPlayerMethod("OnSpawned", null, "PlayerOnSpawnedPostfix", 0); PatchHudUpdateBlackScreen(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Runeheim Loading Screen v0.7.3 loaded."); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Runeheim background + loading-logo test enabled."); } private void OnDestroy() { RestoreLoadingLogo(); if (_harmony != null) { _harmony.UnpatchSelf(); } } private void LoadRuneheimAssets() { string location = Assembly.GetExecutingAssembly().Location; string directoryName = Path.GetDirectoryName(location); if (string.IsNullOrEmpty(directoryName)) { ((BaseUnityPlugin)this).Logger.LogError((object)"Could not determine the Runeheim Loading Screen mod folder."); return; } ((BaseUnityPlugin)this).Logger.LogInfo((object)("Runeheim asset folder: " + directoryName)); _loadingSprite = LoadPngAsSprite(Path.Combine(directoryName, "RuneheimLoading.png"), "RuneheimLoadingTexture", "RuneheimLoadingSprite", out _loadingTexture); _logoSprite = LoadPngAsSprite(Path.Combine(directoryName, "RuneheimLogo.png"), "RuneheimLogoTexture", "RuneheimLogoSprite", out _logoTexture); } private Sprite LoadPngAsSprite(string path, string textureName, string spriteName, out Texture2D texture) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) texture = null; try { if (!File.Exists(path)) { ((BaseUnityPlugin)this).Logger.LogError((object)("Runeheim PNG was not found: " + path)); return null; } byte[] bytes = File.ReadAllBytes(path); texture = new Texture2D(2, 2, (TextureFormat)4, false); ((Object)texture).name = textureName; ((Texture)texture).wrapMode = (TextureWrapMode)1; if (!LoadImageCompat(texture, bytes)) { ((BaseUnityPlugin)this).Logger.LogError((object)("Could not decode Runeheim PNG: " + Path.GetFileName(path))); return null; } Sprite val = Sprite.Create(texture, new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), new Vector2(0.5f, 0.5f), 100f); ((Object)val).name = spriteName; ((BaseUnityPlugin)this).Logger.LogInfo((object)("Loaded Runeheim asset: " + Path.GetFileName(path))); return val; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Could not load Runeheim PNG " + Path.GetFileName(path) + ": " + ex)); return null; } } private static bool LoadImageCompat(Texture2D texture, byte[] bytes) { try { Type typeFromHandle = typeof(ImageConversion); MethodInfo[] methods = typeFromHandle.GetMethods(BindingFlags.Static | BindingFlags.Public); foreach (MethodInfo methodInfo in methods) { if (string.Equals(methodInfo.Name, "LoadImage", StringComparison.Ordinal)) { ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == 2 && parameters[0].ParameterType == typeof(Texture2D) && parameters[1].ParameterType == typeof(byte[])) { object obj = methodInfo.Invoke(null, new object[2] { texture, bytes }); return obj is bool && (bool)obj; } if (parameters.Length == 3 && parameters[0].ParameterType == typeof(Texture2D) && parameters[1].ParameterType == typeof(byte[]) && parameters[2].ParameterType == typeof(bool)) { object obj2 = methodInfo.Invoke(null, new object[3] { texture, bytes, false }); return obj2 is bool && (bool)obj2; } } } _log.LogError((object)"Could not find a compatible Unity ImageConversion.LoadImage(byte[]) overload."); return false; } catch (TargetInvocationException ex) { Exception ex2 = ex.InnerException ?? ex; _log.LogError((object)("Runeheim PNG decode failed: " + ex2)); return false; } catch (Exception ex3) { _log.LogError((object)("Runeheim PNG decode failed: " + ex3)); return false; } } private void PatchHudUpdateBlackScreen() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(typeof(Hud), "UpdateBlackScreen", (Type[])null, (Type[])null); if (methodInfo == null) { ((BaseUnityPlugin)this).Logger.LogError((object)"Could not find Hud.UpdateBlackScreen()."); return; } HarmonyMethod val = new HarmonyMethod(typeof(RuneheimLoadingScreenPlugin), "HudUpdateBlackScreenPrefix", (Type[])null); val.priority = 800; HarmonyMethod val2 = new HarmonyMethod(typeof(RuneheimLoadingScreenPlugin), "HudUpdateBlackScreenPostfix", (Type[])null); val2.priority = 0; _harmony.Patch((MethodBase)methodInfo, val, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } private void PatchFejdMethod(string methodName, string prefixName, string postfixName, int priority) { MethodInfo methodInfo = AccessTools.Method(typeof(FejdStartup), methodName, (Type[])null, (Type[])null); if (methodInfo == null) { ((BaseUnityPlugin)this).Logger.LogError((object)("Could not find FejdStartup." + methodName + "().")); return; } HarmonyMethod val = CreateHarmonyMethod(prefixName, priority); HarmonyMethod val2 = CreateHarmonyMethod(postfixName, priority); _harmony.Patch((MethodBase)methodInfo, val, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } private void PatchPlayerMethod(string methodName, string prefixName, string postfixName, int priority) { MethodInfo methodInfo = AccessTools.Method(typeof(Player), methodName, (Type[])null, (Type[])null); if (methodInfo == null) { ((BaseUnityPlugin)this).Logger.LogError((object)("Could not find Player." + methodName + "().")); return; } HarmonyMethod val = CreateHarmonyMethod(prefixName, priority); HarmonyMethod val2 = CreateHarmonyMethod(postfixName, priority); _harmony.Patch((MethodBase)methodInfo, val, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } private static HarmonyMethod CreateHarmonyMethod(string methodName, int priority) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown if (string.IsNullOrEmpty(methodName)) { return null; } HarmonyMethod val = new HarmonyMethod(typeof(RuneheimLoadingScreenPlugin), methodName, (Type[])null); val.priority = priority; return val; } public static void SetServerToJoinPostfix(object[] __args) { RestoreLoadingLogo(); _destinationKnown = false; _destinationIsRuneheim = false; _runeheimLoadActive = false; try { List<string> list = new List<string>(); HashSet<object> visited = new HashSet<object>(ReferenceEqualityComparer.Instance); if (__args != null) { for (int i = 0; i < __args.Length; i++) { CollectScalarValues(__args[i], list, 0, visited); } } string text = string.Join(" | ", list.ToArray()); bool flag = text.IndexOf("185.216.147.166", StringComparison.OrdinalIgnoreCase) >= 0; bool flag2 = text.IndexOf("5914", StringComparison.OrdinalIgnoreCase) >= 0; bool flag3 = text.IndexOf("Runeheim Online", StringComparison.OrdinalIgnoreCase) >= 0; _destinationKnown = true; _destinationIsRuneheim = flag3 || (flag && flag2); if (_destinationIsRuneheim) { _log.LogInfo((object)"Runeheim destination detected."); } else { _log.LogInfo((object)"Non-Runeheim destination detected."); } } catch (Exception ex) { _destinationKnown = false; _destinationIsRuneheim = false; _runeheimLoadActive = false; _log.LogWarning((object)("Server detection failed; defaulting to vanilla: " + ex.Message)); } } public static void JoinServerPrefix() { RestoreLoadingLogo(); _runeheimLoadActive = _destinationKnown && _destinationIsRuneheim; if (_runeheimLoadActive) { _log.LogInfo((object)"Runeheim join armed."); } else { _log.LogInfo((object)"Non-Runeheim join; loading screen stays vanilla."); } } public static void OnWorldStartPrefix() { RestoreLoadingLogo(); _destinationKnown = false; _destinationIsRuneheim = false; _runeheimLoadActive = false; _log.LogInfo((object)"Solo/local world selected; loading screen stays vanilla."); } public static void PlayerOnSpawnedPostfix() { if (_runeheimLoadActive) { _log.LogInfo((object)"Runeheim player spawned; clearing loading-screen state."); } RestoreLoadingLogo(); _runeheimLoadActive = false; } public static void HudUpdateBlackScreenPrefix(bool ___m_haveSetupLoadScreen, ref bool __state) { __state = !___m_haveSetupLoadScreen; } public static void HudUpdateBlackScreenPostfix(Hud __instance, bool ___m_haveSetupLoadScreen, bool __state) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) if (!_runeheimLoadActive || (Object)(object)__instance == (Object)null || !__state || !___m_haveSetupLoadScreen) { return; } try { if ((Object)(object)_loadingSprite != (Object)null) { Image loadingImage = __instance.m_loadingImage; if ((Object)(object)loadingImage == (Object)null) { _log.LogWarning((object)"Hud.m_loadingImage was null."); } else { loadingImage.sprite = _loadingSprite; loadingImage.type = (Type)0; loadingImage.preserveAspect = true; ((Graphic)loadingImage).color = Color.white; ((Component)loadingImage).gameObject.SetActive(true); _log.LogInfo((object)"Runeheim custom HUD loading image applied."); } } TryApplyRuneheimLogo(__instance); } catch (Exception ex) { _log.LogError((object)("Failed to apply Runeheim loading UI: " + ex)); } } private static void TryApplyRuneheimLogo(Hud hud) { //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0148: 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_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) if (_logoApplied || (Object)(object)_logoSprite == (Object)null || (Object)(object)hud == (Object)null) { return; } try { Image[] componentsInChildren = ((Component)hud).GetComponentsInChildren<Image>(true); Image val = null; int num = 0; foreach (Image val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2 == (Object)(object)hud.m_loadingImage)) { string objectName = (((Object)(object)((Component)val2).gameObject != (Object)null) ? ((Object)((Component)val2).gameObject).name : string.Empty); string spriteName = (((Object)(object)val2.sprite != (Object)null) ? ((Object)val2.sprite).name : string.Empty); int num2 = ScoreLogoCandidate(objectName, spriteName); if (num2 > num) { num = num2; val = val2; } } } if ((Object)(object)val == (Object)null || num < 10) { _log.LogWarning((object)"Could not confidently identify the Valheim loading logo; leaving it unchanged."); LogLikelyImageNames(componentsInChildren); return; } _swappedLogoImage = val; _originalLogoSprite = val.sprite; val.sprite = _logoSprite; val.type = (Type)0; val.preserveAspect = true; ((Graphic)val).color = Color.white; ((Component)val).gameObject.SetActive(true); RectTransform rectTransform = ((Graphic)val).rectTransform; if ((Object)(object)rectTransform != (Object)null) { rectTransform.anchorMin = new Vector2(0.5f, rectTransform.anchorMin.y); rectTransform.anchorMax = new Vector2(0.5f, rectTransform.anchorMax.y); rectTransform.pivot = new Vector2(0.5f, rectTransform.pivot.y); rectTransform.anchoredPosition = new Vector2(0f, rectTransform.anchoredPosition.y); } _logoApplied = true; _log.LogInfo((object)("Runeheim loading logo applied to UI object '" + ((Object)((Component)val).gameObject).name + "'.")); } catch (Exception ex) { _log.LogWarning((object)("Runeheim logo swap failed safely; Valheim logo left unchanged: " + ex.Message)); } } private static int ScoreLogoCandidate(string objectName, string spriteName) { int num = 0; if (!string.IsNullOrEmpty(objectName)) { if (objectName.IndexOf("valheim", StringComparison.OrdinalIgnoreCase) >= 0) { num += 40; } if (objectName.IndexOf("logo", StringComparison.OrdinalIgnoreCase) >= 0) { num += 20; } } if (!string.IsNullOrEmpty(spriteName)) { if (spriteName.IndexOf("valheim", StringComparison.OrdinalIgnoreCase) >= 0) { num += 40; } if (spriteName.IndexOf("logo", StringComparison.OrdinalIgnoreCase) >= 0) { num += 20; } } return num; } private static void LogLikelyImageNames(Image[] images) { if (images == null) { return; } int num = 0; for (int i = 0; i < images.Length; i++) { if (num >= 20) { break; } Image val = images[i]; if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)Hud.instance.m_loadingImage)) { string text = (((Object)(object)((Component)val).gameObject != (Object)null) ? ((Object)((Component)val).gameObject).name : "<null>"); string text2 = (((Object)(object)val.sprite != (Object)null) ? ((Object)val.sprite).name : "<none>"); if (text.IndexOf("logo", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("valheim", StringComparison.OrdinalIgnoreCase) >= 0 || text2.IndexOf("logo", StringComparison.OrdinalIgnoreCase) >= 0 || text2.IndexOf("valheim", StringComparison.OrdinalIgnoreCase) >= 0) { _log.LogInfo((object)("Logo candidate: object='" + text + "', sprite='" + text2 + "'.")); num++; } } } } private static void RestoreLoadingLogo() { try { if ((Object)(object)_swappedLogoImage != (Object)null) { _swappedLogoImage.sprite = _originalLogoSprite; } } catch { } _swappedLogoImage = null; _originalLogoSprite = null; _logoApplied = false; } private static void CollectScalarValues(object value, List<string> output, int depth, HashSet<object> visited) { if (value == null || depth > 5) { return; } Type type = value.GetType(); if (type == typeof(string) || type.IsPrimitive || type.IsEnum || type == typeof(decimal)) { output.Add(Convert.ToString(value)); return; } if (!type.IsValueType) { if (visited.Contains(value)) { return; } visited.Add(value); } if (value is IEnumerable enumerable && !(value is string)) { int num = 0; { foreach (object item in enumerable) { CollectScalarValues(item, output, depth + 1, visited); num++; if (num >= 32) { break; } } return; } } BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; FieldInfo[] fields = type.GetFields(bindingAttr); for (int i = 0; i < fields.Length; i++) { try { CollectScalarValues(fields[i].GetValue(value), output, depth + 1, visited); } catch { } } PropertyInfo[] properties = type.GetProperties(bindingAttr); foreach (PropertyInfo propertyInfo in properties) { if (propertyInfo.CanRead && propertyInfo.GetIndexParameters().Length == 0) { try { CollectScalarValues(propertyInfo.GetValue(value, null), output, depth + 1, visited); } catch { } } } } }