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 CheatCleanup v1.0.0
plugins/CheatCleanup/CheatCleanup.dll
Decompiled a month agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Logging; using Jotunn.Entities; using Jotunn.Managers; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyCompany("CheatCleanup")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("CheatCleanup")] [assembly: AssemblyTitle("CheatCleanup")] [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 CheatCleanup { internal sealed class CheatCleanupCommand : ConsoleCommand { public override string Name => "cheatcleanup"; public override string Help => "Limpa permanentemente flags de cheat do personagem/mundo. Use: cheatcleanup scan | clean | clean confirm | verify"; public override bool IsCheat => false; public override bool IsNetwork => false; public override bool IsSecret => false; public override List<string> CommandOptionList() { return new List<string> { "scan", "clean", "verify", "help" }; } public override void Run(string[] args, Terminal context) { string text = ((args != null && args.Length != 0) ? args[0].ToLowerInvariant() : "help"); switch (text) { case "help": case "status": Print(context, "CheatCleanup v1.0.0\nNada e alterado automaticamente.\ncheatcleanup scan - varredura sem alterar o save\ncheatcleanup clean - mostra a confirmacao\ncheatcleanup clean confirm - executa a limpeza e salva\ncheatcleanup verify - nova varredura para conferir\nSeguranca: limpeza bloqueada em servidor de terceiros."); return; case "clean": if (args.Length < 2 || !string.Equals(args[1], "confirm", StringComparison.OrdinalIgnoreCase)) { Print(context, "ATENCAO: a limpeza modifica permanentemente o personagem e o mundo atualmente carregados.\nFaca um backup do mundo/personagem antes do primeiro teste.\nPrimeiro recomendo: cheatcleanup scan\nPara executar: cheatcleanup clean confirm"); return; } break; } if (text != "scan" && text != "verify" && text != "clean") { Print(context, "Subcomando desconhecido. Use: cheatcleanup help"); return; } if (!CleanupService.ValidateEnvironment(out var reason)) { Print(context, "[CheatCleanup] " + reason); return; } bool flag = text == "clean"; Print(context, "[CheatCleanup] " + (flag ? "Limpando" : "Analisando") + " mundo '" + ValheimAccess.GetWorldName() + "'..."); CleanupReport cleanupReport = CleanupService.Run(flag); string heading = ((text == "verify") ? "VERIFICACAO" : (flag ? "LIMPEZA" : "SCAN")); Print(context, cleanupReport.ToConsoleText(heading)); if (text == "verify") { Print(context, cleanupReport.PersistentDataLooksClean ? "[CheatCleanup] DADOS PERSISTENTES LIMPOS. Game.isModded ainda sera true nesta sessao; feche e abra o Valheim sem mods para a verificacao vanilla." : "[CheatCleanup] Ainda existem marcadores persistentes de cheat ou itens que nao puderam ser confirmados como limpos."); } } private static void Print(Terminal context, string text) { if ((Object)(object)context != (Object)null) { context.AddString(text); } ManualLogSource modLog = CheatCleanupPlugin.ModLog; if (modLog != null) { modLog.LogInfo((object)text); } } } [BepInPlugin("br.cheatcleanup.valheim", "CheatCleanup", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class CheatCleanupPlugin : BaseUnityPlugin { public const string PluginGuid = "br.cheatcleanup.valheim"; public const string PluginName = "CheatCleanup"; public const string PluginVersion = "1.0.0"; internal static ManualLogSource ModLog { get; private set; } private void Awake() { ModLog = ((BaseUnityPlugin)this).Logger; CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new CheatCleanupCommand()); ((BaseUnityPlugin)this).Logger.LogInfo((object)"CheatCleanup 1.0.0 carregado. Nenhuma limpeza e executada automaticamente."); } } internal sealed class CleanupReport { public bool ApplyMode; public bool CharacterFlagFound; public bool CharacterFlagChanged; public bool WorldWasCheated; public bool WorldStillCheated; public bool SaveRequested; public int PlayerItemsScanned; public int PlayerItemsCheated; public int PlayerItemsChanged; public int ZdosScanned; public int ZdoCheatedFlags; public int ZdoCheatedQueuedFlags; public int ZdoFlagsChanged; public int InventoryPayloadsScanned; public int InventoryItemsScanned; public int InventoryItemsCheated; public int InventoryPayloadsChanged; public int ItemPayloadsScanned; public int ItemPayloadsCheated; public int ItemPayloadsChanged; public int RuntimeContainersScanned; public int RuntimeDropsScanned; public int RuntimeObjectsChanged; public int WorldKeysScanned; public readonly List<string> InvalidWorldKeys = new List<string>(); public readonly List<string> CheatedItemDetails = new List<string>(); public int WorldKeysChanged; public readonly List<string> Warnings = new List<string>(); public readonly List<string> Errors = new List<string>(); public int TotalCheatMarkersFound => (CharacterFlagFound ? 1 : 0) + PlayerItemsCheated + ZdoCheatedFlags + ZdoCheatedQueuedFlags + InventoryItemsCheated + ItemPayloadsCheated + InvalidWorldKeys.Count; public bool PersistentDataLooksClean { get { if (!CharacterFlagFound && PlayerItemsCheated == 0 && ZdoCheatedFlags == 0 && ZdoCheatedQueuedFlags == 0 && InventoryItemsCheated == 0 && ItemPayloadsCheated == 0 && InvalidWorldKeys.Count == 0) { return !WorldWasCheated; } return false; } } public string ToConsoleText(string heading) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("=== CheatCleanup: " + heading + " ==="); stringBuilder.AppendLine("Personagem marcado: " + (CharacterFlagFound ? "SIM" : "NAO") + ((!ApplyMode || !CharacterFlagFound) ? string.Empty : (CharacterFlagChanged ? " -> LIMPO" : " -> NAO ALTERADO"))); stringBuilder.AppendLine($"Inventario do personagem: {PlayerItemsScanned} itens, {PlayerItemsCheated} marcados" + (ApplyMode ? $", {PlayerItemsChanged} limpos" : string.Empty)); stringBuilder.AppendLine($"ZDOs do mundo: {ZdosScanned} verificados; flags cheated={ZdoCheatedFlags}, queued={ZdoCheatedQueuedFlags}" + (ApplyMode ? $", {ZdoFlagsChanged} removidas" : string.Empty)); stringBuilder.AppendLine($"Inventarios persistentes (baus/tumulos/navios/etc.): {InventoryPayloadsScanned} payloads, {InventoryItemsScanned} itens, {InventoryItemsCheated} marcados" + (ApplyMode ? $", {InventoryPayloadsChanged} payloads regravados" : string.Empty)); stringBuilder.AppendLine($"Itens persistentes do mapa/stands: {ItemPayloadsScanned} payloads, {ItemPayloadsCheated} marcados" + (ApplyMode ? $", {ItemPayloadsChanged} regravados" : string.Empty)); stringBuilder.AppendLine($"World keys: {WorldKeysScanned} verificadas, {InvalidWorldKeys.Count} consideradas cheat pelo criterio do proprio Valheim" + (ApplyMode ? $", {WorldKeysChanged} removidas" : string.Empty)); stringBuilder.AppendLine("WorldContainsCheatedModifiers: antes=" + (WorldWasCheated ? "SIM" : "NAO") + (ApplyMode ? (", depois=" + (WorldStillCheated ? "SIM" : "NAO")) : string.Empty)); if (CheatedItemDetails.Count > 0) { stringBuilder.AppendLine("Detalhes dos itens marcados:"); foreach (string cheatedItemDetail in CheatedItemDetails) { stringBuilder.AppendLine(" - " + cheatedItemDetail); } } if (InvalidWorldKeys.Count > 0) { stringBuilder.AppendLine("Keys suspeitas: " + string.Join(", ", InvalidWorldKeys)); } if (Warnings.Count > 0) { stringBuilder.AppendLine("Avisos:"); foreach (string warning in Warnings) { stringBuilder.AppendLine(" - " + warning); } } if (Errors.Count > 0) { stringBuilder.AppendLine("Erros:"); foreach (string error in Errors) { stringBuilder.AppendLine(" - " + error); } } if (ApplyMode) { stringBuilder.AppendLine(SaveRequested ? "Salvamento do mundo e perfis solicitado ao Valheim." : "ATENCAO: nao foi possivel solicitar o salvamento automaticamente."); } return stringBuilder.ToString().TrimEnd(Array.Empty<char>()); } } internal static class CleanupService { private const int IndexedItemDataSlotsToCheck = 32; internal static bool ValidateEnvironment(out string reason) { if (!ValheimAccess.IsReady(out reason)) { return false; } if (!ValheimAccess.IsServer()) { reason = "Seguranca: CheatCleanup so pode alterar single-player ou um mundo que voce esteja hospedando. Em servidor de terceiros o comando e bloqueado."; return false; } return true; } internal static CleanupReport Run(bool apply) { CleanupReport cleanupReport = new CleanupReport { ApplyMode = apply }; try { ScanCharacter(cleanupReport, apply); } catch (Exception ex) { cleanupReport.Errors.Add("Personagem: " + RootMessage(ex)); } try { ScanPlayerInventory(cleanupReport, apply); } catch (Exception ex2) { cleanupReport.Errors.Add("Inventario do personagem: " + RootMessage(ex2)); } try { ScanWorldZdos(cleanupReport, apply); } catch (Exception ex3) { cleanupReport.Errors.Add("ZDOs persistentes: " + RootMessage(ex3)); } try { SynchronizeLoadedRuntimeObjects(cleanupReport, apply); } catch (Exception ex4) { cleanupReport.Errors.Add("Objetos carregados: " + RootMessage(ex4)); } try { ScanWorldKeys(cleanupReport, apply); } catch (Exception ex5) { cleanupReport.Errors.Add("World keys: " + RootMessage(ex5)); } if (apply && cleanupReport.Errors.Count == 0) { try { cleanupReport.SaveRequested = ValheimAccess.RequestNativeSave(); } catch (Exception ex6) { cleanupReport.Errors.Add("Salvamento: " + RootMessage(ex6)); } } return cleanupReport; } private static void ScanCharacter(CleanupReport report, bool apply) { object profile = ValheimAccess.GetProfile(); if (profile == null) { report.Warnings.Add("PlayerProfile nao encontrado."); } else if (apply & (report.CharacterFlagFound = ValheimAccess.ProfileUsedCheats(profile))) { report.CharacterFlagChanged = ValheimAccess.SetProfileUsedCheats(profile, value: false); ValheimAccess.ResetCheatStat(profile); } } private static void ScanPlayerInventory(CleanupReport report, bool apply) { foreach (object item in ValheimAccess.InventoryItems(ValheimAccess.GetLocalPlayerInventory())) { report.PlayerItemsScanned++; if (ValheimAccess.ItemIsCheated(item)) { report.PlayerItemsCheated++; AddCheatedItemDetail(report, "Inventario do personagem", null, item); if (apply && ValheimAccess.SetItemCheated(item, value: false)) { report.PlayerItemsChanged++; } } } } private static void ScanWorldZdos(CleanupReport report, bool apply) { List<object> allZdos = ValheimAccess.GetAllZdos(); if (allZdos.Count == 0) { report.Warnings.Add("Nenhum ZDO foi enumerado. A varredura do mapa nao pode ser considerada completa."); return; } int cheatedHash = ValheimAccess.CheatedHash; int cheatedQueuedHash = ValheimAccess.CheatedQueuedHash; int itemsHash = ValheimAccess.ItemsHash; int itemDataHash = ValheimAccess.ItemDataHash; int[] array = (from i in Enumerable.Range(0, 32) select ValheimAccess.StableHash(i + "_itemData")).ToArray(); for (int num = 0; num < allZdos.Count; num++) { object zdo = allZdos[num]; report.ZdosScanned++; if (ValheimAccess.GetZdoBool(zdo, cheatedHash)) { report.ZdoCheatedFlags++; if (apply) { ValheimAccess.RemoveZdoBool(zdo, cheatedHash); report.ZdoFlagsChanged++; } } if (ValheimAccess.GetZdoBool(zdo, cheatedQueuedHash)) { report.ZdoCheatedQueuedFlags++; if (apply) { ValheimAccess.RemoveZdoBool(zdo, cheatedQueuedHash); report.ZdoFlagsChanged++; } } byte[] zdoBytes = ValheimAccess.GetZdoBytes(zdo, itemsHash); if (zdoBytes != null && zdoBytes.Length != 0) { ScanInventoryPayload(zdo, itemsHash, zdoBytes, report, apply); } byte[] zdoBytes2 = ValheimAccess.GetZdoBytes(zdo, itemDataHash); if (zdoBytes2 != null && zdoBytes2.Length != 0) { ScanItemPayload(zdo, itemDataHash, zdoBytes2, report, apply); } foreach (int hash in array) { byte[] zdoBytes3 = ValheimAccess.GetZdoBytes(zdo, hash); if (zdoBytes3 != null && zdoBytes3.Length != 0) { ScanItemPayload(zdo, hash, zdoBytes3, report, apply); } } } } private static void ScanInventoryPayload(object zdo, int hash, byte[] bytes, CleanupReport report, bool apply) { report.InventoryPayloadsScanned++; object inventory = ValheimAccess.NewTemporaryInventory(); object package = ValheimAccess.NewPackage(bytes); ValheimAccess.InventoryLoad(inventory, package); bool flag = false; foreach (object item in ValheimAccess.InventoryItems(inventory)) { report.InventoryItemsScanned++; if (ValheimAccess.ItemIsCheated(item)) { report.InventoryItemsCheated++; AddCheatedItemDetail(report, "Inventario persistente", zdo, item); if (apply && ValheimAccess.SetItemCheated(item, value: false)) { flag = true; } } } if (apply && flag) { object package2 = ValheimAccess.NewPackage(); ValheimAccess.InventorySave(inventory, package2); ValheimAccess.SetZdoBytes(zdo, hash, ValheimAccess.PackageGetArray(package2)); report.InventoryPayloadsChanged++; } } private static void ScanItemPayload(object zdo, int hash, byte[] bytes, CleanupReport report, bool apply) { report.ItemPayloadsScanned++; object obj; try { obj = ValheimAccess.LoadDirectItemData(bytes, out var _); } catch { return; } if (obj != null && ValheimAccess.ItemIsCheated(obj)) { report.ItemPayloadsCheated++; AddCheatedItemDetail(report, "Item persistente/stand", zdo, obj); if (apply && ValheimAccess.SetItemCheated(obj, value: false)) { byte[] bytes2 = ValheimAccess.SaveDirectItemData(obj); ValheimAccess.SetZdoBytes(zdo, hash, bytes2); report.ItemPayloadsChanged++; } } } private static void SynchronizeLoadedRuntimeObjects(CleanupReport report, bool apply) { foreach (object item in ValheimAccess.FindLoadedObjects("Container")) { object obj = ReflectionUtil.Method(item.GetType(), "GetInventory", 0, false)?.Invoke(item, null) ?? ReflectionUtil.GetField(item, "m_inventory"); if (obj != null) { report.RuntimeContainersScanned++; bool flag = CleanRuntimeInventory(obj, apply); if (apply && flag) { report.RuntimeObjectsChanged++; TryInvokeNoArg(item, "Save"); } } } foreach (object item2 in ValheimAccess.FindLoadedObjects("ItemDrop")) { object field = ReflectionUtil.GetField(item2, "m_itemData"); if (field != null) { report.RuntimeDropsScanned++; if (ValheimAccess.ItemIsCheated(field) && apply && ValheimAccess.SetItemCheated(field, value: false)) { report.RuntimeObjectsChanged++; TryInvokeNoArg(item2, "Save"); } } } bool flag2 = default(bool); foreach (object item3 in ValheimAccess.FindLoadedObjects("Fermenter")) { if (apply) { object field2 = ReflectionUtil.GetField(item3, "m_delayedTapItemCheated"); int num; if (field2 is bool) { flag2 = (bool)field2; num = 1; } else { num = 0; } if (((uint)num & (flag2 ? 1u : 0u)) != 0 && ReflectionUtil.SetField(item3, "m_delayedTapItemCheated", false)) { report.RuntimeObjectsChanged++; } } } bool flag3 = default(bool); foreach (object item4 in ValheimAccess.FindLoadedObjects("CharacterDrop")) { if (apply) { object field3 = ReflectionUtil.GetField(item4, "m_cheated"); int num2; if (field3 is bool) { flag3 = (bool)field3; num2 = 1; } else { num2 = 0; } if (((uint)num2 & (flag3 ? 1u : 0u)) != 0 && ReflectionUtil.SetField(item4, "m_cheated", false)) { report.RuntimeObjectsChanged++; } } } } private static bool CleanRuntimeInventory(object inventory, bool apply) { bool result = false; foreach (object item in ValheimAccess.InventoryItems(inventory)) { if (ValheimAccess.ItemIsCheated(item)) { result = true; if (apply) { ValheimAccess.SetItemCheated(item, value: false); } } } return result; } private static void ScanWorldKeys(CleanupReport report, bool apply) { object world = ValheimAccess.GetWorld(); if (world == null) { return; } report.WorldWasCheated = ValheimAccess.WorldContainsCheatedModifiers(world); object startingWorldKeys = ValheimAccess.GetStartingWorldKeys(world); IReadOnlyCollection<string> allowedWorldKeys = ValheimAccess.GetAllowedWorldKeys(); if (startingWorldKeys == null) { report.Warnings.Add("m_startingGlobalKeys nao encontrado; world modifiers nao foram alterados."); return; } if (allowedWorldKeys == null) { report.Warnings.Add("GetPossibleGlobalKeyValues nao encontrado; world modifiers nao foram alterados para evitar falsos positivos."); return; } HashSet<string> hashSet = new HashSet<string>(allowedWorldKeys, StringComparer.Ordinal); List<object> list = new List<object>(); foreach (object item in ReflectionUtil.Enumerate(startingWorldKeys)) { string text = Convert.ToString(item); report.WorldKeysScanned++; if (!string.IsNullOrEmpty(text) && !text.StartsWith("preset", StringComparison.Ordinal) && !hashSet.Contains(text)) { report.InvalidWorldKeys.Add(text); list.Add(item); } } if (!apply) { return; } foreach (object item2 in list) { if (ValheimAccess.RemoveWorldKey(startingWorldKeys, item2)) { report.WorldKeysChanged++; } } report.WorldStillCheated = ValheimAccess.WorldContainsCheatedModifiers(world); } private static void AddCheatedItemDetail(CleanupReport report, string source, object zdo, object item) { if (report.CheatedItemDetails.Count < 100) { string itemDisplayName = GetItemDisplayName(item); string itemStack = GetItemStack(item); string text = ((zdo == null) ? string.Empty : (" | " + DescribeZdo(zdo))); report.CheatedItemDetails.Add(source + ": " + itemDisplayName + itemStack + text); } } private static string GetItemDisplayName(object item) { if (item == null) { return "<item desconhecido>"; } try { object field = ReflectionUtil.GetField(item, "m_shared"); if (field != null) { string text = Convert.ToString(ReflectionUtil.GetField(field, "m_name")); if (!string.IsNullOrWhiteSpace(text)) { return text; } } object field2 = ReflectionUtil.GetField(item, "m_dropPrefab"); if (field2 != null) { string text2 = Convert.ToString(ReflectionUtil.GetProperty(field2, "name") ?? ReflectionUtil.GetField(field2, "name")); if (!string.IsNullOrWhiteSpace(text2)) { return text2; } } } catch { } return "<item sem nome>"; } private static string GetItemStack(object item) { try { object field = ReflectionUtil.GetField(item, "m_stack"); if (field != null) { return " x" + Convert.ToInt32(field); } } catch { } return string.Empty; } private static string DescribeZdo(object zdo) { if (zdo == null) { return "ZDO desconhecido"; } string text = "?"; string text2 = "?"; try { object obj = ReflectionUtil.Method(zdo.GetType(), "GetPosition", 0, false)?.Invoke(zdo, null); if (obj != null) { text = Convert.ToString(obj); } } catch { } try { object obj3 = ReflectionUtil.Method(zdo.GetType(), "GetPrefab", 0, false)?.Invoke(zdo, null); if (obj3 != null) { text2 = Convert.ToString(obj3); } } catch { } return "ZDO prefab=" + text2 + ", pos=" + text; } private static void TryInvokeNoArg(object instance, string methodName) { try { ReflectionUtil.Method(instance?.GetType(), methodName, 0, false)?.Invoke(instance, null); } catch { } } private static string RootMessage(Exception ex) { while (ex is TargetInvocationException { InnerException: not null } ex2) { ex = ex2.InnerException; } return ex.GetType().Name + ": " + ex.Message; } } internal static class ReflectionUtil { internal const BindingFlags AnyInstance = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; internal const BindingFlags AnyStatic = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; internal const BindingFlags Any = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; internal static Type FindType(string simpleOrFullName) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { Type type = assembly.GetType(simpleOrFullName, throwOnError: false); if (type != null) { return type; } try { Type type2 = assembly.GetTypes().FirstOrDefault((Type t) => string.Equals(t.Name, simpleOrFullName, StringComparison.Ordinal) || string.Equals(t.FullName, simpleOrFullName, StringComparison.Ordinal)); if (type2 != null) { return type2; } } catch (ReflectionTypeLoadException ex) { Type type3 = ex.Types?.FirstOrDefault((Type t) => t != null && (string.Equals(t.Name, simpleOrFullName, StringComparison.Ordinal) || string.Equals(t.FullName, simpleOrFullName, StringComparison.Ordinal))); if (type3 != null) { return type3; } } } return null; } internal static FieldInfo Field(Type type, string name) { return type?.GetField(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } internal static PropertyInfo Property(Type type, string name) { return type?.GetProperty(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } internal static object GetStaticField(Type type, string name) { return Field(type, name)?.GetValue(null); } internal static object GetField(object instance, string name) { if (instance != null) { return Field(instance.GetType(), name)?.GetValue(instance); } return null; } internal static object GetProperty(object instance, string name) { if (instance == null) { return null; } return Property(instance.GetType(), name)?.GetValue(instance, null); } internal static bool SetField(object instance, string name, object value) { if (instance == null) { return false; } FieldInfo fieldInfo = Field(instance.GetType(), name); if (fieldInfo == null) { return false; } fieldInfo.SetValue(instance, value); return true; } internal static int GetStaticInt(Type type, string name) { object staticField = GetStaticField(type, name); if (staticField is int) { return (int)staticField; } return 0; } internal static MethodInfo Method(Type type, string name, int parameterCount = -1, bool? isStatic = null) { if (type == null) { return null; } return type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => m.Name == name && (parameterCount < 0 || m.GetParameters().Length == parameterCount) && (!isStatic.HasValue || m.IsStatic == isStatic.Value)); } internal static MethodInfo Method(Type type, string name, params Type[] parameterTypes) { if (type == null) { return null; } return type.GetMethod(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, parameterTypes, null); } internal static IEnumerable<object> Enumerate(object sequence) { if (!(sequence is IEnumerable enumerable)) { yield break; } foreach (object item in enumerable) { yield return item; } } internal static object DictionaryValue(object entry) { if (entry == null) { return null; } if (entry is DictionaryEntry dictionaryEntry) { return dictionaryEntry.Value; } return entry.GetType().GetProperty("Value", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(entry, null); } } internal static class ValheimAccess { private static readonly Type GameType = ReflectionUtil.FindType("Game"); private static readonly Type PlayerType = ReflectionUtil.FindType("Player"); private static readonly Type ZNetType = ReflectionUtil.FindType("ZNet"); private static readonly Type ZdoManType = ReflectionUtil.FindType("ZDOMan"); private static readonly Type ZdoType = ReflectionUtil.FindType("ZDO"); private static readonly Type ZdoVarsType = ReflectionUtil.FindType("ZDOVars"); private static readonly Type ZPackageType = ReflectionUtil.FindType("ZPackage"); private static readonly Type InventoryType = ReflectionUtil.FindType("Inventory"); private static readonly Type ItemDataType = FindItemDataType(); private static readonly Type WorldOptionsType = ReflectionUtil.FindType("ServerOptionsGUI"); private static readonly Type PlayerStatType = ReflectionUtil.FindType("PlayerStatType"); private static readonly MethodInfo ZdoGetBoolMethod = FindZdoMethod("GetBool", typeof(int), typeof(bool)); private static readonly MethodInfo ZdoGetBytesMethod = FindZdoMethod("GetByteArray", typeof(int), typeof(byte[])); private static readonly MethodInfo ZdoSetBytesMethod = FindZdoMethod("Set", typeof(int), typeof(byte[])); private static readonly MethodInfo ZdoRemoveBoolMethod = FindZdoMethod("RemoveBool", typeof(int)); private static MethodInfo _stableHashMethod; internal static object GameInstance => GetStaticMember(GameType, "instance") ?? GetStaticMember(GameType, "m_instance") ?? GetStaticMember(GameType, "Instance"); internal static object ZNetInstance => GetStaticMember(ZNetType, "instance") ?? GetStaticMember(ZNetType, "m_instance") ?? GetStaticMember(ZNetType, "Instance"); internal static object ZdoManInstance => GetStaticMember(ZdoManType, "instance") ?? GetStaticMember(ZdoManType, "m_instance") ?? GetStaticMember(ZdoManType, "Instance"); internal static object LocalPlayer => GetStaticMember(PlayerType, "m_localPlayer") ?? GetStaticMember(PlayerType, "localPlayer") ?? GetStaticMember(PlayerType, "LocalPlayer"); internal static int CheatedHash => ReflectionUtil.GetStaticInt(ZdoVarsType, "s_cheated"); internal static int CheatedQueuedHash => ReflectionUtil.GetStaticInt(ZdoVarsType, "s_cheatedQueued"); internal static int ItemsHash => ReflectionUtil.GetStaticInt(ZdoVarsType, "s_items"); internal static int ItemDataHash => ReflectionUtil.GetStaticInt(ZdoVarsType, "s_itemData"); internal static bool IsReady(out string reason) { if (ZNetInstance == null) { reason = "ZNet.instance ainda nao esta disponivel."; return false; } if (ZdoManInstance == null) { reason = "ZDOMan.instance ainda nao esta disponivel."; return false; } if (LocalPlayer == null) { reason = "Nenhum personagem local esta carregado."; return false; } if (GetWorld() == null) { reason = "Nenhum mundo esta carregado."; return false; } if (GetProfile() == null) { reason = "PlayerProfile do personagem atual nao foi encontrado."; return false; } reason = null; return true; } internal static bool IsServer() { object zNetInstance = ZNetInstance; MethodInfo methodInfo = ReflectionUtil.Method(ZNetType, "IsServer", 0, false); bool flag = default(bool); int num; if (zNetInstance != null && methodInfo != null) { object obj = methodInfo.Invoke(zNetInstance, null); if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } internal static object GetWorld() { object zNetInstance = ZNetInstance; MethodInfo methodInfo = ReflectionUtil.Method(ZNetType, "GetWorld", 0, false); if (zNetInstance != null && !(methodInfo == null)) { return methodInfo.Invoke(zNetInstance, null); } return null; } internal static string GetWorldName() { object zNetInstance = ZNetInstance; MethodInfo methodInfo = ReflectionUtil.Method(ZNetType, "GetWorldName", 0, false); if (zNetInstance != null && !(methodInfo == null)) { return Convert.ToString(methodInfo.Invoke(zNetInstance, null)); } return "?"; } internal static object GetProfile() { object gameInstance = GameInstance; if (gameInstance != null) { MethodInfo methodInfo = ReflectionUtil.Method(gameInstance.GetType(), "GetPlayerProfile", 0, false); if (methodInfo != null) { object obj = methodInfo.Invoke(gameInstance, null); if (obj != null) { return obj; } } object obj2 = ReflectionUtil.GetField(gameInstance, "m_playerProfile") ?? ReflectionUtil.GetField(gameInstance, "m_profile"); if (obj2 != null) { return obj2; } } object localPlayer = LocalPlayer; if (localPlayer != null) { object obj3 = ReflectionUtil.GetField(localPlayer, "m_playerProfile") ?? ReflectionUtil.GetField(localPlayer, "m_profile"); if (obj3 != null) { return obj3; } } foreach (object item in FindLoadedObjects("Game")) { if (item == null) { continue; } MethodInfo methodInfo2 = ReflectionUtil.Method(item.GetType(), "GetPlayerProfile", 0, false); if (methodInfo2 != null) { object obj4 = methodInfo2.Invoke(item, null); if (obj4 != null) { return obj4; } } object obj5 = ReflectionUtil.GetField(item, "m_playerProfile") ?? ReflectionUtil.GetField(item, "m_profile"); if (obj5 != null) { return obj5; } } return null; } internal static bool ProfileUsedCheats(object profile) { object field = ReflectionUtil.GetField(profile, "m_usedCheats"); bool flag = default(bool); int num; if (field is bool) { flag = (bool)field; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } internal static bool SetProfileUsedCheats(object profile, bool value) { return ReflectionUtil.SetField(profile, "m_usedCheats", value); } internal static void ResetCheatStat(object profile) { if (profile == null || PlayerStatType == null) { return; } try { object obj = Enum.Parse(PlayerStatType, "Cheats"); profile.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => m.Name == "SetStat" && m.GetParameters().Length == 3)?.Invoke(profile, new object[3] { obj, 0f, false }); } catch (Exception ex) { ManualLogSource modLog = CheatCleanupPlugin.ModLog; if (modLog != null) { modLog.LogWarning((object)("Nao foi possivel zerar a estatistica historica Cheats: " + ex.Message)); } } } internal static object GetLocalPlayerInventory() { object localPlayer = LocalPlayer; return ((localPlayer == null) ? null : ReflectionUtil.Method(localPlayer.GetType(), "GetInventory", 0, false))?.Invoke(localPlayer, null); } internal static List<object> GetAllZdos() { List<object> list = new List<object>(); object field = ReflectionUtil.GetField(ZdoManInstance, "m_objectsByID"); if (field == null) { return list; } foreach (object item in ReflectionUtil.Enumerate(field)) { object obj = ReflectionUtil.DictionaryValue(item); if (obj != null) { list.Add(obj); } } return list; } internal static bool GetZdoBool(object zdo, int hash) { if (zdo == null || hash == 0 || ZdoGetBoolMethod == null) { return false; } object obj = ZdoGetBoolMethod.Invoke(zdo, new object[2] { hash, false }); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } internal static void RemoveZdoBool(object zdo, int hash) { if (zdo != null && hash != 0) { ZdoRemoveBoolMethod?.Invoke(zdo, new object[1] { hash }); } } internal static byte[] GetZdoBytes(object zdo, int hash) { if (zdo == null || hash == 0 || ZdoGetBytesMethod == null) { return null; } return ZdoGetBytesMethod.Invoke(zdo, new object[2] { hash, null }) as byte[]; } internal static void SetZdoBytes(object zdo, int hash, byte[] bytes) { if (zdo != null && hash != 0 && bytes != null) { ZdoSetBytesMethod?.Invoke(zdo, new object[2] { hash, bytes }); } } internal static int StableHash(string value) { if (_stableHashMethod == null) { _stableHashMethod = FindStableHashMethod(); } if (_stableHashMethod == null) { throw new MissingMethodException("GetStableHashCode(string) nao encontrado."); } return (int)_stableHashMethod.Invoke(null, new object[1] { value }); } internal static object NewPackage(byte[] bytes = null) { if (ZPackageType == null) { throw new InvalidOperationException("Tipo ZPackage nao encontrado."); } if (bytes != null) { return Activator.CreateInstance(ZPackageType, bytes); } return Activator.CreateInstance(ZPackageType); } internal static int PackageReadInt(object package) { return (int)ReflectionUtil.Method(ZPackageType, "ReadInt", 0, false).Invoke(package, null); } internal static void PackageWriteInt(object package, int value) { ReflectionUtil.Method(ZPackageType, "Write", typeof(int)).Invoke(package, new object[1] { value }); } internal static byte[] PackageGetArray(object package) { return ReflectionUtil.Method(ZPackageType, "GetArray", 0, false).Invoke(package, null) as byte[]; } internal static object NewTemporaryInventory() { if (InventoryType == null) { throw new InvalidOperationException("Tipo Inventory nao encontrado."); } ConstructorInfo? constructorInfo = InventoryType.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault(delegate(ConstructorInfo c) { ParameterInfo[] parameters = c.GetParameters(); return parameters.Length == 4 && parameters[0].ParameterType == typeof(string) && parameters[2].ParameterType == typeof(int) && parameters[3].ParameterType == typeof(int); }); if (constructorInfo == null) { throw new MissingMethodException("Construtor Inventory(string, Sprite, int, int) nao encontrado."); } return constructorInfo.Invoke(new object[4] { "CheatCleanup.Temp", null, 1024, 1024 }); } internal static void InventoryLoad(object inventory, object package) { ReflectionUtil.Method(InventoryType, "Load", ZPackageType).Invoke(inventory, new object[1] { package }); } internal static void InventorySave(object inventory, object package) { ReflectionUtil.Method(InventoryType, "Save", ZPackageType).Invoke(inventory, new object[1] { package }); } internal static IEnumerable<object> InventoryItems(object inventory) { if (inventory == null) { yield break; } object sequence = ReflectionUtil.Method(inventory.GetType(), "GetAllItems", 0, false)?.Invoke(inventory, null); foreach (object item in ReflectionUtil.Enumerate(sequence)) { yield return item; } } internal static bool ItemIsCheated(object item) { object field = ReflectionUtil.GetField(item, "m_cheated"); bool flag = default(bool); int num; if (field is bool) { flag = (bool)field; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } internal static bool SetItemCheated(object item, bool value) { return ReflectionUtil.SetField(item, "m_cheated", value); } internal static object LoadDirectItemData(byte[] bytes, out int sourceVersion) { sourceVersion = 0; if (bytes == null || bytes.Length == 0 || ItemDataType == null) { return null; } object obj = NewPackage(bytes); sourceVersion = PackageReadInt(obj); MethodInfo? methodInfo = ItemDataType.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault(delegate(MethodInfo m) { ParameterInfo[] parameters = m.GetParameters(); return m.Name == "Load" && parameters.Length == 2 && parameters[0].ParameterType == ZPackageType && parameters[1].ParameterType == typeof(int); }); if (methodInfo == null) { throw new MissingMethodException("ItemData.Load(ZPackage,int) nao encontrado."); } object obj2 = methodInfo.Invoke(null, new object[2] { obj, sourceVersion }); if (obj2 == null) { return null; } if (ItemDataType.IsInstanceOfType(obj2)) { return obj2; } return obj2.GetType().GetField("Item1", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj2); } internal static byte[] SaveDirectItemData(object item) { if (item == null) { return null; } object obj = NewPackage(); PackageWriteInt(obj, 109); MethodInfo methodInfo = ReflectionUtil.Method(item.GetType(), "Save", ZPackageType); if (methodInfo == null) { throw new MissingMethodException("ItemData.Save(ZPackage) nao encontrado."); } methodInfo.Invoke(item, new object[1] { obj }); return PackageGetArray(obj); } internal static bool WorldContainsCheatedModifiers(object world) { if (world == null || WorldOptionsType == null) { return false; } MethodInfo methodInfo = ReflectionUtil.Method(WorldOptionsType, "WorldContainsCheatedModifiers", 1, true); bool flag = default(bool); int num; if (methodInfo != null) { object obj = methodInfo.Invoke(null, new object[1] { world }); if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } internal static IReadOnlyCollection<string> GetAllowedWorldKeys() { if (WorldOptionsType == null) { return null; } MethodInfo methodInfo = ReflectionUtil.Method(WorldOptionsType, "GetPossibleGlobalKeyValues", 0, true); if (methodInfo == null) { return null; } return (from s in ReflectionUtil.Enumerate(methodInfo.Invoke(null, null)).Select(Convert.ToString) where !string.IsNullOrEmpty(s) select s).ToList(); } internal static object GetStartingWorldKeys(object world) { return ReflectionUtil.GetField(world, "m_startingGlobalKeys"); } internal static bool RemoveWorldKey(object keyCollection, object key) { if (keyCollection == null) { return false; } MethodInfo methodInfo = keyCollection.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => m.Name == "Remove" && m.GetParameters().Length == 1); if (methodInfo == null) { return false; } object obj = methodInfo.Invoke(keyCollection, new object[1] { key }); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = ((1 == 0) ? 1 : 0); } else { num = 1; } return (byte)((uint)num | (flag ? 1u : 0u)) != 0; } internal static bool RequestNativeSave() { object zNetInstance = ZNetInstance; MethodInfo methodInfo = ReflectionUtil.Method(ZNetType, "SaveWorldAndPlayerProfiles", 0, false); if (zNetInstance == null || methodInfo == null) { return false; } methodInfo.Invoke(zNetInstance, null); return true; } internal static IEnumerable<object> FindLoadedObjects(string typeName) { Type type = ReflectionUtil.FindType(typeName); if (type == null) { yield break; } Type type2 = ReflectionUtil.FindType("UnityEngine.Object"); if (type2 == null || !type2.IsAssignableFrom(type)) { yield break; } Type type3 = ReflectionUtil.FindType("UnityEngine.Resources") ?? ReflectionUtil.FindType("Resources"); if (type3 == null) { yield break; } MethodInfo methodInfo = type3.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault(delegate(MethodInfo m) { ParameterInfo[] parameters = m.GetParameters(); return m.Name == "FindObjectsOfTypeAll" && !m.IsGenericMethod && parameters.Length == 1 && parameters[0].ParameterType == typeof(Type); }); if (methodInfo == null) { yield break; } object sequence = methodInfo.Invoke(null, new object[1] { type }); foreach (object item in ReflectionUtil.Enumerate(sequence)) { yield return item; } } private static object GetStaticMember(Type type, string name) { if (type == null) { return null; } FieldInfo field = type.GetField(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { return field.GetValue(null); } PropertyInfo property = type.GetProperty(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.GetIndexParameters().Length == 0) { return property.GetValue(null, null); } return null; } private static MethodInfo FindZdoMethod(string name, params Type[] parameterTypes) { return ZdoType?.GetMethod(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, parameterTypes, null); } private static MethodInfo FindStableHashMethod() { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { Type[] array; try { array = assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { array = ex.Types?.Where((Type t) => t != null).ToArray() ?? Array.Empty<Type>(); } catch { continue; } Type[] array2 = array; for (int num = 0; num < array2.Length; num++) { MethodInfo methodInfo = array2[num].GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault(delegate(MethodInfo m) { ParameterInfo[] parameters = m.GetParameters(); return m.Name == "GetStableHashCode" && m.ReturnType == typeof(int) && parameters.Length == 1 && parameters[0].ParameterType == typeof(string); }); if (methodInfo != null) { return methodInfo; } } } return null; } private static Type FindItemDataType() { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { Type type = assemblies[i].GetType("ItemDrop+ItemData", throwOnError: false); if (type != null) { return type; } } return ReflectionUtil.FindType("ItemData"); } } }