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 ExtraFoodSlot v1.0.8
BepInEx/plugins/nick008extrafood.dll
Decompiled 2 weeks agousing System; using System.Collections.Generic; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Logging; using HarmonyLib; using UnityEngine; [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: CompilationRelaxations(8)] [assembly: AssemblyVersion("0.0.0.0")] namespace Nick008ExtraFood; [BepInPlugin("nick008.extrafood", "nick008extrafood", "1.0.8")] [BepInProcess("valheim.exe")] public sealed class Nick008ExtraFoodPlugin : BaseUnityPlugin { [HarmonyPatch(typeof(Player), "CanEat")] private static class PlayerCanEatPatch { [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { return ReplaceSingleFoodLimit(instructions, "Player.CanEat"); } } [HarmonyPatch(typeof(Player), "EatFood")] private static class PlayerEatFoodPatch { [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { return ReplaceSingleFoodLimit(instructions, "Player.EatFood"); } } [HarmonyPatch(typeof(Hud), "UpdateFood")] private static class HudUpdateFoodBackgroundPatch { [HarmonyPostfix] private static void Postfix() { if (!((Object)(object)fourthFoodBackgroundObject == (Object)null) && !((Object)(object)fourthFoodIconObject == (Object)null)) { bool activeSelf = fourthFoodIconObject.activeSelf; if (fourthFoodBackgroundObject.activeSelf != activeSelf) { fourthFoodBackgroundObject.SetActive(activeSelf); } } } } [HarmonyPatch(typeof(Hud), "Awake")] private static class HudAwakePatch { [HarmonyPostfix] private static void Postfix(Hud __instance) { TryAddFourthHudSlot(__instance); } } public const string PluginGuid = "nick008.extrafood"; public const string PluginName = "nick008extrafood"; public const string PluginVersion = "1.0.8"; internal static ManualLogSource Log; private Harmony harmony; private static GameObject fourthFoodBackgroundObject; private static GameObject fourthFoodIconObject; private void Awake() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; harmony = new Harmony("nick008.extrafood"); harmony.PatchAll(); Log.LogInfo((object)"[nick008extrafood] Loaded. Fixed food limit: 4."); } private void OnDestroy() { if (harmony != null) { harmony.UnpatchSelf(); } } internal static IEnumerable<CodeInstruction> ReplaceSingleFoodLimit(IEnumerable<CodeInstruction> instructions, string methodName) { List<CodeInstruction> list = new List<CodeInstruction>(instructions); int num = 0; int index = -1; for (int i = 0; i < list.Count; i++) { if (list[i].opcode == OpCodes.Ldc_I4_3) { num++; index = i; } } if (num != 1) { if (Log != null) { Log.LogWarning((object)("[nick008extrafood] " + methodName + " changed (expected one ldc.i4.3, found " + num + "). Gameplay patch skipped for safety.")); } return list; } list[index].opcode = OpCodes.Ldc_I4_4; list[index].operand = null; if (Log != null) { Log.LogInfo((object)("[nick008extrafood] Patched " + methodName + " food limit 3 -> 4.")); } return list; } internal static void TryAddFourthHudSlot(Hud hud) { GameObject cloneObject = null; GameObject cloneObject2 = null; GameObject cloneObject3 = null; GameObject val = null; try { if ((Object)(object)hud == (Object)null) { return; } BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; FieldInfo field = typeof(Hud).GetField("m_foodBars", bindingAttr); FieldInfo field2 = typeof(Hud).GetField("m_foodIcons", bindingAttr); FieldInfo field3 = typeof(Hud).GetField("m_foodTime", bindingAttr); if (field == null || field2 == null || field3 == null) { Log.LogWarning((object)"[nick008extrafood] HUD fields were not found. HUD patch skipped safely."); return; } Array array = field.GetValue(hud) as Array; Array array2 = field2.GetValue(hud) as Array; Array array3 = field3.GetValue(hud) as Array; if (array == null || array2 == null || array3 == null) { Log.LogWarning((object)"[nick008extrafood] HUD arrays are unavailable. HUD patch skipped safely."); return; } if (array.Length >= 4 && array2.Length >= 4 && array3.Length >= 4) { Log.LogInfo((object)"[nick008extrafood] HUD already has at least 4 food slots; no clone needed."); return; } if (array.Length != 3 || array2.Length != 3 || array3.Length != 3) { Log.LogWarning((object)("[nick008extrafood] Unexpected HUD array sizes (" + array.Length + "/" + array2.Length + "/" + array3.Length + "). HUD patch skipped safely.")); return; } object? value = array.GetValue(0); Component val2 = (Component)((value is Component) ? value : null); object? value2 = array.GetValue(1); Component val3 = (Component)((value2 is Component) ? value2 : null); object? value3 = array.GetValue(2); Component val4 = (Component)((value3 is Component) ? value3 : null); object? value4 = array2.GetValue(0); Component val5 = (Component)((value4 is Component) ? value4 : null); object? value5 = array2.GetValue(1); Component val6 = (Component)((value5 is Component) ? value5 : null); object? value6 = array2.GetValue(2); Component val7 = (Component)((value6 is Component) ? value6 : null); object? value7 = array3.GetValue(0); Component val8 = (Component)((value7 is Component) ? value7 : null); object? value8 = array3.GetValue(1); Component val9 = (Component)((value8 is Component) ? value8 : null); object? value9 = array3.GetValue(2); Component val10 = (Component)((value9 is Component) ? value9 : null); if ((Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null || (Object)(object)val4 == (Object)null || (Object)(object)val5 == (Object)null || (Object)(object)val6 == (Object)null || (Object)(object)val7 == (Object)null || (Object)(object)val8 == (Object)null || (Object)(object)val9 == (Object)null || (Object)(object)val10 == (Object)null) { Log.LogWarning((object)"[nick008extrafood] Vanilla food HUD components are missing. HUD patch skipped safely."); return; } Component val11 = CloneFourthAboveTop(val2, val3, val4, "nick008extrafood_foodBar4", out cloneObject); Component val12 = CloneFourthAboveTop(val5, val6, val7, "nick008extrafood_foodIcon4", out cloneObject2); Component val13 = CloneFourthAboveTop(val8, val9, val10, "nick008extrafood_foodTime4", out cloneObject3); if ((Object)(object)val11 == (Object)null || (Object)(object)val12 == (Object)null || (Object)(object)val13 == (Object)null) { DestroyIfCreated(cloneObject); DestroyIfCreated(cloneObject2); DestroyIfCreated(cloneObject3); Log.LogWarning((object)"[nick008extrafood] Could not clone all three HUD components. HUD patch skipped safely."); return; } Array value10 = GrowArrayToFour(array, val11); Array value11 = GrowArrayToFour(array2, val12); Array value12 = GrowArrayToFour(array3, val13); field.SetValue(hud, value10); field2.SetValue(hud, value11); field3.SetValue(hud, value12); Component visuallyTop = GetVisuallyTop(val5, val6, val7); val = CloneBackgroundOnly(visuallyTop, cloneObject2); cloneObject.SetActive(false); cloneObject2.SetActive(false); cloneObject3.SetActive(false); if ((Object)(object)val != (Object)null) { val.SetActive(false); fourthFoodBackgroundObject = val; fourthFoodIconObject = cloneObject2; Log.LogInfo((object)"[nick008extrafood] Fourth food background cloned without foreground children."); } else { fourthFoodBackgroundObject = null; fourthFoodIconObject = cloneObject2; Log.LogWarning((object)"[nick008extrafood] Fourth slot works, but cosmetic background could not be cloned."); } Log.LogInfo((object)"[nick008extrafood] HUD expanded from 3 to 4 food slots (Valheim 1.0 layout)."); } catch (Exception ex) { DestroyIfCreated(cloneObject); DestroyIfCreated(cloneObject2); DestroyIfCreated(cloneObject3); DestroyIfCreated(val); fourthFoodBackgroundObject = null; fourthFoodIconObject = null; if (Log != null) { Log.LogError((object)("[nick008extrafood] HUD patch failed safely: " + ex)); } } } private static Component GetVisuallyTop(Component first, Component second, Component third) { //IL_001a: 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_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) Component val = first; if ((Object)(object)second != (Object)null && ((Object)(object)val == (Object)null || second.transform.position.y > val.transform.position.y)) { val = second; } if ((Object)(object)third != (Object)null && ((Object)(object)val == (Object)null || third.transform.position.y > val.transform.position.y)) { val = third; } return val; } private static GameObject CloneBackgroundOnly(Component topIcon, GameObject fourthIconObject) { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)topIcon == (Object)null || (Object)(object)fourthIconObject == (Object)null || (Object)(object)topIcon.transform.parent == (Object)null) { return null; } Transform parent = topIcon.transform.parent; if ((Object)(object)parent.parent == (Object)null) { return null; } int siblingIndex = parent.GetSiblingIndex(); GameObject val = Object.Instantiate<GameObject>(((Component)parent).gameObject, parent.parent, false); ((Object)val).name = "nick008extrafood_foodBackground4"; Vector3 val2 = fourthIconObject.transform.position - topIcon.transform.position; val.transform.position = parent.position + val2; for (int i = 0; i < val.transform.childCount; i++) { Transform child = val.transform.GetChild(i); if ((Object)(object)child != (Object)null) { ((Component)child).gameObject.SetActive(false); } } val.transform.SetSiblingIndex(siblingIndex); return val; } catch (Exception ex) { if (Log != null) { Log.LogWarning((object)("[nick008extrafood] Background-only clone skipped safely: " + ex.Message)); } return null; } } private static Component CloneFourthAboveTop(Component first, Component second, Component third, string cloneName, out GameObject cloneObject) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) cloneObject = null; if ((Object)(object)first == (Object)null || (Object)(object)second == (Object)null || (Object)(object)third == (Object)null) { return null; } Component val = first; float num = first.transform.position.y; float num2 = num; float y = second.transform.position.y; if (y < num) { num = y; } if (y > num2) { num2 = y; val = second; } float y2 = third.transform.position.y; if (y2 < num) { num = y2; } if (y2 > num2) { num2 = y2; val = third; } float num3 = (num2 - num) * 0.5f; if (num3 <= 0.01f || (Object)(object)val.gameObject == (Object)null) { return null; } Transform parent = val.transform.parent; cloneObject = Object.Instantiate<GameObject>(val.gameObject, parent, false); ((Object)cloneObject).name = cloneName; Component component = cloneObject.GetComponent(((object)val).GetType()); if ((Object)(object)component == (Object)null) { Object.Destroy((Object)(object)cloneObject); cloneObject = null; return null; } Vector3 position = val.transform.position; position.y = num2 + num3; cloneObject.transform.position = position; cloneObject.transform.SetAsLastSibling(); if (Log != null) { Log.LogInfo((object)("[nick008extrafood] " + cloneName + " Y min/max/spacing/target = " + num.ToString("F2") + "/" + num2.ToString("F2") + "/" + num3.ToString("F2") + "/" + position.y.ToString("F2"))); } return component; } private static void DestroyIfCreated(GameObject gameObject) { if ((Object)(object)gameObject != (Object)null) { Object.Destroy((Object)(object)gameObject); } } private static Array GrowArrayToFour(Array original, object fourth) { Type elementType = original.GetType().GetElementType(); Array array = Array.CreateInstance(elementType, 4); Array.Copy(original, array, 3); array.SetValue(fourth, 3); return array; } private static Component GetMatchingComponent(Transform cloneRoot, string relativePath, Type componentType) { Transform val = cloneRoot; if (!string.IsNullOrEmpty(relativePath)) { val = cloneRoot.Find(relativePath); } if ((Object)(object)val == (Object)null) { return null; } return ((Component)val).GetComponent(componentType); } private static string GetRelativePath(Transform root, Transform child) { if ((Object)(object)root == (Object)null || (Object)(object)child == (Object)null) { return null; } if ((Object)(object)root == (Object)(object)child) { return string.Empty; } List<string> list = new List<string>(); Transform val = child; while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)root) { list.Add(((Object)val).name); val = val.parent; } if ((Object)(object)val != (Object)(object)root) { return null; } list.Reverse(); return string.Join("/", list.ToArray()); } }