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 PapysLand VSG QoL v0.3.6
PapysLandVSGQoL.dll
Decompiled 2 weeks agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [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("PapysLandVSGQoL")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("PapysLandVSGQoL")] [assembly: AssemblyTitle("PapysLandVSGQoL")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace PapysLandVSGQoL { [BepInPlugin("papysland.vsgqol", "PapysLand VSG QoL", "0.3.6")] public sealed class Plugin : BaseUnityPlugin { internal static ManualLogSource Log; internal static Plugin Instance; private Harmony _harmony; private int _reconcileFrames = -1; private bool _reconciling; private float _nextPeriodicReconcile; private static Type _playerType; private static Type _dispatcherType; private static Type _chainStateType; private static Type _itemAcquiredType; private static FieldInfo _indexedConfigField; private static MethodInfo _getStep; private static MethodInfo _getCounter; private static MethodInfo _setCounter; private static MethodInfo _isComplete; private static MethodInfo _advanceChain; private static MethodInfo _countInInventory; private static MethodInfo _getEffectiveGoals; private void Awake() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; _harmony = new Harmony("papysland.vsgqol"); Log.LogInfo((object)"PapysLand VSG QoL 0.3.6 LOOP GUARD chargé."); Log.LogInfo((object)"Mode: compteur = contenu REEL de l'inventaire; contrôle périodique 0,20 s; aucun faux item_acquired."); try { ResolveVsg(); PatchInventoryChanged(); PatchInventoryRemoveMethods(); PatchHumanoidDropItem(); PatchAdvanceChain(); ScheduleReconcile(3); Log.LogInfo((object)"PapysLand VSG QoL 0.3.6 prêt."); } catch (Exception ex) { Log.LogError((object)("Initialisation 0.3.0 impossible: " + ex)); } } private void OnDestroy() { try { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } catch { } Instance = null; } private void Update() { if (Time.unscaledTime >= _nextPeriodicReconcile) { _nextPeriodicReconcile = Time.unscaledTime + 0.2f; ReconcileAllActiveInventoryCounters(); } if (_reconcileFrames >= 0) { if (_reconcileFrames > 0) { _reconcileFrames--; return; } _reconcileFrames = -1; ReconcileAllActiveInventoryCounters(); } } internal static void ScheduleReconcile(int frames = 2) { if (!((Object)(object)Instance == (Object)null) && Instance._reconcileFrames < frames) { Instance._reconcileFrames = frames; } } private static void ResolveVsg() { _playerType = AccessTools.TypeByName("Player") ?? throw new Exception("Type Player introuvable."); _dispatcherType = AccessTools.TypeByName("ValheimServerGuide.Triggers.GuidanceDispatcher") ?? throw new Exception("GuidanceDispatcher introuvable."); _chainStateType = AccessTools.TypeByName("ValheimServerGuide.State.ChainState") ?? throw new Exception("ChainState introuvable."); _itemAcquiredType = AccessTools.TypeByName("ValheimServerGuide.Triggers.ItemAcquiredTrigger") ?? throw new Exception("ItemAcquiredTrigger introuvable."); _indexedConfigField = AccessTools.Field(_dispatcherType, "_indexedConfig") ?? throw new Exception("GuidanceDispatcher._indexedConfig introuvable."); _getStep = AccessTools.Method(_chainStateType, "GetStep", (Type[])null, (Type[])null) ?? throw new Exception("ChainState.GetStep introuvable."); _getCounter = AccessTools.Method(_chainStateType, "GetCounter", (Type[])null, (Type[])null) ?? throw new Exception("ChainState.GetCounter introuvable."); _setCounter = AccessTools.Method(_chainStateType, "SetCounter", (Type[])null, (Type[])null) ?? throw new Exception("ChainState.SetCounter introuvable."); _isComplete = AccessTools.Method(_chainStateType, "IsComplete", (Type[])null, (Type[])null) ?? throw new Exception("ChainState.IsComplete introuvable."); _advanceChain = AccessTools.Method(_dispatcherType, "AdvanceChain", (Type[])null, (Type[])null) ?? throw new Exception("GuidanceDispatcher.AdvanceChain introuvable."); _countInInventory = AccessTools.Method(_itemAcquiredType, "CountInInventory", (Type[])null, (Type[])null) ?? throw new Exception("ItemAcquiredTrigger.CountInInventory introuvable."); _getEffectiveGoals = AccessTools.Method(_itemAcquiredType, "GetEffectiveGoals", (Type[])null, (Type[])null) ?? throw new Exception("ItemAcquiredTrigger.GetEffectiveGoals introuvable."); Log.LogInfo((object)"VSG 0.16.1: méthodes LIVE INVENTORY + CHAIN GOALS résolues."); } private void PatchInventoryChanged() { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown Type type = AccessTools.TypeByName("Inventory"); MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "Changed", (Type[])null, (Type[])null)); if (methodInfo == null) { throw new Exception("Inventory.Changed introuvable."); } _harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "InventoryChangedPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)"Patch Inventory.Changed actif."); } private void PatchInventoryRemoveMethods() { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Expected O, but got Unknown Type type = AccessTools.TypeByName("Inventory"); if (type == null) { throw new Exception("Type Inventory introuvable."); } int num = 0; foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(type)) { if (!(declaredMethod == null) && (string.Equals(declaredMethod.Name, "RemoveItem", StringComparison.Ordinal) || string.Equals(declaredMethod.Name, "RemoveOneItem", StringComparison.Ordinal))) { _harmony.Patch((MethodBase)declaredMethod, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "InventoryMutationPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; } } Log.LogInfo((object)$"Patch Inventory.RemoveItem/RemoveOneItem actif ({num} surcharge(s))."); } private void PatchHumanoidDropItem() { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown Type type = AccessTools.TypeByName("Humanoid"); if (type == null) { throw new Exception("Type Humanoid introuvable."); } int num = 0; foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(type)) { if (!(declaredMethod == null) && string.Equals(declaredMethod.Name, "DropItem", StringComparison.Ordinal)) { _harmony.Patch((MethodBase)declaredMethod, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "DropItemPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; } } Log.LogInfo((object)$"Patch Humanoid.DropItem actif ({num} surcharge(s))."); } public static void InventoryMutationPostfix(object __instance) { try { object localInventory = GetLocalInventory(); if (localInventory != null && localInventory == __instance) { ScheduleReconcile(); } } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("InventoryMutationPostfix: " + ex.Message)); } } } public static void DropItemPostfix(object __instance) { try { object localPlayer = GetLocalPlayer(); if (localPlayer != null && localPlayer == __instance) { ScheduleReconcile(3); } } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("DropItemPostfix: " + ex.Message)); } } } private void PatchAdvanceChain() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown _harmony.Patch((MethodBase)_advanceChain, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "AdvanceChainPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)"Patch GuidanceDispatcher.AdvanceChain actif."); } public static void InventoryChangedPostfix(object __instance) { try { object localInventory = GetLocalInventory(); if (localInventory != null && localInventory == __instance) { ScheduleReconcile(); } } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("InventoryChangedPostfix: " + ex.Message)); } } } public static void AdvanceChainPostfix() { ScheduleReconcile(3); } private void ReconcileAllActiveInventoryCounters() { if (_reconciling) { return; } object localPlayer = GetLocalPlayer(); if (localPlayer == null) { return; } object value = _indexedConfigField.GetValue(null); if (value == null || !(GetMember(value, "Guidances") is IEnumerable enumerable)) { return; } _reconciling = true; try { for (int i = 0; i < 12; i++) { bool flag = false; foreach (object item in enumerable) { if (item == null) { continue; } string text = GetString(item, "Id"); if (string.IsNullOrWhiteSpace(text) || Convert.ToBoolean(_isComplete.Invoke(null, new object[2] { localPlayer, text })) || !(GetMember(item, "Steps") is IList { Count: not 0 } list)) { continue; } int num = Convert.ToInt32(_getStep.Invoke(null, new object[2] { localPlayer, text })); if (num < 0 || num >= list.Count) { continue; } object obj = list[num]; if (obj == null) { continue; } object member = GetMember(obj, "Trigger"); if (member != null && Eq(GetString(member, "Type"), "entry_finished")) { string text2 = GetString(member, "Entry"); if (!string.IsNullOrWhiteSpace(text2) && Convert.ToBoolean(_isComplete.Invoke(null, new object[2] { localPlayer, text2 }))) { List<string> list2 = new List<string>(); _advanceChain.Invoke(null, new object[4] { item, num, localPlayer, list2 }); Log.LogInfo((object)("[PREREQ] " + text + ": prérequis " + text2 + " déjà terminé -> étape avancée.")); string[] array = list2.ToArray(); for (int j = 0; j < array.Length; j++) { PropagateEntryFinished(array[j], localPlayer, enumerable); } flag = true; break; } } int num2 = GetInt(obj, "ProgressGoal", 0); object member2 = GetMember(obj, "ProgressTrigger"); if (num2 > 0 && member2 != null && Eq(GetString(member2, "Type"), "item_acquired")) { string text3 = GetString(member2, "Item"); if (string.IsNullOrWhiteSpace(text3)) { text3 = GetString(member2, "Prefab"); } if (!string.IsNullOrWhiteSpace(text3)) { int num3 = Convert.ToInt32(_countInInventory.Invoke(null, new object[2] { localPlayer, text3 })); int num4 = Convert.ToInt32(_getCounter.Invoke(null, new object[3] { localPlayer, text, num })); if (num4 != num3) { _setCounter.Invoke(null, new object[4] { localPlayer, text, num, num3 }); Log.LogInfo((object)$"[LIVE] {text} étape {num + 1}: {text3} = {num3}/{num2} (ancien {num4})"); } if (num3 >= num2) { List<string> list3 = new List<string>(); _advanceChain.Invoke(null, new object[4] { item, num, localPlayer, list3 }); Log.LogInfo((object)$"[LIVE] Objectif compteur satisfait: {text} {text3} {num3}/{num2} -> étape avancée."); string[] array = list3.ToArray(); for (int j = 0; j < array.Length; j++) { PropagateEntryFinished(array[j], localPlayer, enumerable); } flag = true; break; } } } object member3 = GetMember(obj, "Trigger"); if (member3 == null || !Eq(GetString(member3, "Type"), "item_acquired")) { continue; } object obj2 = null; try { obj2 = _getEffectiveGoals.Invoke(null, new object[1] { member3 }); } catch (Exception ex) { Log.LogWarning((object)("GetEffectiveGoals: " + ex.Message)); } if (!(obj2 is IEnumerable enumerable2)) { continue; } bool flag2 = false; bool flag3 = true; List<string> list4 = new List<string>(); foreach (object item2 in enumerable2) { if (item2 == null) { continue; } flag2 = true; string text4 = GetString(item2, "Item"); if (string.IsNullOrWhiteSpace(text4)) { text4 = GetString(item2, "Prefab"); } int num5 = GetInt(item2, "Count", 1); if (num5 <= 0) { num5 = 1; } if (string.IsNullOrWhiteSpace(text4)) { flag3 = false; continue; } int num6 = Convert.ToInt32(_countInInventory.Invoke(null, new object[2] { localPlayer, text4 })); list4.Add($"{text4} {num6}/{num5}"); if (num6 < num5) { flag3 = false; } } if (flag2 && flag3) { List<string> list5 = new List<string>(); _advanceChain.Invoke(null, new object[4] { item, num, localPlayer, list5 }); Log.LogInfo((object)string.Format("[LIVE-GOALS] {0} étape {1}: {2} -> étape avancée.", text, num + 1, string.Join(", ", list4))); string[] array = list5.ToArray(); for (int j = 0; j < array.Length; j++) { PropagateEntryFinished(array[j], localPlayer, enumerable); } flag = true; break; } } if (!flag) { break; } } } catch (TargetInvocationException ex2) { Log.LogError((object)("Réconciliation VSG: " + (ex2.InnerException ?? ex2))); } catch (Exception ex3) { Log.LogError((object)("Réconciliation VSG: " + ex3)); } finally { _reconciling = false; } } private static void PropagateEntryFinished(string completedId, object player, IEnumerable guidances) { if (string.IsNullOrWhiteSpace(completedId) || player == null || guidances == null) { return; } try { foreach (object guidance in guidances) { if (guidance == null) { continue; } string text = GetString(guidance, "Id"); if (string.IsNullOrWhiteSpace(text) || Convert.ToBoolean(_isComplete.Invoke(null, new object[2] { player, text })) || !(GetMember(guidance, "Steps") is IList { Count: not 0 } list)) { continue; } int num = Convert.ToInt32(_getStep.Invoke(null, new object[2] { player, text })); if (num < 0 || num >= list.Count) { continue; } object member = GetMember(list[num], "Trigger"); if (member != null && Eq(GetString(member, "Type"), "entry_finished") && string.Equals(GetString(member, "Entry")?.Trim(), completedId.Trim(), StringComparison.OrdinalIgnoreCase)) { List<string> list2 = new List<string>(); _advanceChain.Invoke(null, new object[4] { guidance, num, player, list2 }); Log.LogInfo((object)("[CHAIN] " + completedId + " terminé -> " + text + " déverrouillée.")); string[] array = list2.ToArray(); for (int i = 0; i < array.Length; i++) { PropagateEntryFinished(array[i], player, guidances); } } } } catch (Exception ex) { Log.LogError((object)("Propagation entry_finished: " + ex)); } } private static object GetLocalPlayer() { if (_playerType == null) { return null; } return AccessTools.Field(_playerType, "m_localPlayer")?.GetValue(null); } private static object GetLocalInventory() { object localPlayer = GetLocalPlayer(); if (localPlayer == null) { return null; } return AccessTools.Method(localPlayer.GetType(), "GetInventory", (Type[])null, (Type[])null)?.Invoke(localPlayer, null); } private static object GetMember(object obj, string name) { if (obj == null) { return null; } Type type = obj.GetType(); PropertyInfo propertyInfo = AccessTools.Property(type, name); if (propertyInfo != null) { try { return propertyInfo.GetValue(obj, null); } catch { } } FieldInfo fieldInfo = AccessTools.Field(type, name); if (fieldInfo != null) { try { return fieldInfo.GetValue(obj); } catch { } } return null; } private static string GetString(object obj, string name) { return GetMember(obj, name)?.ToString(); } private static int GetInt(object obj, string name, int fallback) { object member = GetMember(obj, name); if (member == null) { return fallback; } try { return Convert.ToInt32(member); } catch { return fallback; } } private static bool Eq(string a, string b) { return string.Equals(a?.Trim(), b, StringComparison.OrdinalIgnoreCase); } } }