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 CantTouchThis v0.0.1
plugins\CantTouchThis.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.InteropServices; using System.Runtime.Versioning; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("CantTouchThis")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("CantTouchThis")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")] [assembly: AssemblyFileVersion("0.0.1")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.1.0")] namespace CantTouchThis; [BepInPlugin("de.sirskunkalot.CantTouchThis", "CantTouchThis", "0.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] internal class CantTouchThis : BaseUnityPlugin { [CompilerGenerated] private sealed class <DelayedMessage>d__33 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public string message; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DelayedMessage>d__33(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: { <>1__state = -1; Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, message, 0, (Sprite)null); } return false; } } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public const string PluginGUID = "de.sirskunkalot.CantTouchThis"; public const string PluginName = "CantTouchThis"; public const string PluginVersion = "0.0.1"; private static CantTouchThis _instance; private static readonly CustomLocalization Localization = LocalizationManager.Instance.GetLocalization(); private static readonly string[] MessageKeys = (from i in Enumerable.Range(1, 14) select $"message{i}").ToArray(); private static ConfigEntry<string> _forbiddenItemsConfig; private static ConfigEntry<bool> _removeRecipesFromUIConfig; private static HashSet<string> _forbiddenItemsSet; private static HashSet<string> _forbiddenItemsCache; private static HashSet<string> _allowedItemsCache; private void Awake() { //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Expected O, but got Unknown //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Expected O, but got Unknown //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Expected O, but got Unknown //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Expected O, but got Unknown _instance = this; CustomLocalization localization = Localization; string text = "English"; localization.AddTranslation(ref text, new Dictionary<string, string> { { "message1", "Odin forbids {item_name}" }, { "message2", "Even Loki wouldn't touch {item_name}" }, { "message3", "The gods frown upon your desire for {item_name}" }, { "message4", "{item_name}? Not in this realm" }, { "message5", "Valhalla has {item_name}. You do not" }, { "message6", "A raven whispers: {item_name} is not for you" }, { "message7", "The Allfather says no to {item_name}" }, { "message8", "You stare at {item_name}. It stares back. You walk away" }, { "message9", "You can look at {item_name} but you can't touch" }, { "message10", "Can't touch this" }, { "message11", "Stop! {item_name} time. Oh wait..." }, { "message12", "You shall not {item_name}" }, { "message13", "Imagine using {item_name}" }, { "message14", "{item_name}? In this economy?" } }); _forbiddenItemsConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Config", "Forbidden Items", (string)null, new ConfigDescription("Comma separated list of forbidden items. Syncs from server. Evaluated at runtime when changed.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); _forbiddenItemsConfig.SettingChanged += delegate { ResetForbiddenItems(); }; ResetForbiddenItems(); _removeRecipesFromUIConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Config", "Hide Forbidden Items in UI", false, new ConfigDescription("Forbidden items will not show up in the crafting and building menu when enabled. Client side only.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = false } })); Harmony.CreateAndPatchAll(typeof(CantTouchThis), "de.sirskunkalot.CantTouchThis"); } [HarmonyPatch(typeof(Game), "Start")] [HarmonyPostfix] private static void PostfixGameStart() { CraftingDataCache.Build(); } [HarmonyPatch(typeof(Game), "OnDestroy")] [HarmonyPostfix] private static void PostfixGameDestroy() { CraftingDataCache.Invalidate(); } [HarmonyPatch(typeof(Player), "CanConsumeItem")] [HarmonyPrefix] private static bool PrefixPlayerCanConsumeItem(Player __instance, ItemData item) { return CheckConsumption(__instance, item); } [HarmonyPatch(typeof(Player), "ConsumeItem")] [HarmonyPrefix] private static bool PrefixPlayerConsumeItem(Player __instance, ItemData item) { return CheckConsumption(__instance, item); } private static bool CheckConsumption(Player player, ItemData item) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Invalid comparison between Unknown and I4 if (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || (Object)(object)Player.m_localPlayer != (Object)(object)player) { return true; } if ((int)item.m_shared.m_itemType != 2) { return true; } if (IsForbidden(item.m_shared.m_name)) { Message(item.m_shared.m_name); return false; } return true; } [HarmonyPatch(typeof(InventoryGui), "OnCraftPressed")] [HarmonyPrefix] private static bool PrefixOnCraftPressed(InventoryGui __instance) { Recipe recipe = ((RecipeDataPair)(ref __instance.m_selectedRecipe)).Recipe; if ((Object)(object)recipe?.m_item == (Object)null) { return true; } string name = recipe.m_item.m_itemData.m_shared.m_name; if (IsForbidden(name)) { Message(name); return false; } return true; } [HarmonyPatch(typeof(Player), "GetAvailableRecipes")] [HarmonyPostfix] private static void PostfixGetAvailableRecipes(ref List<Recipe> available) { if (_removeRecipesFromUIConfig.Value) { available.RemoveAll((Recipe recipe) => !((Object)(object)recipe?.m_item == (Object)null) && IsForbidden(recipe.m_item.m_itemData.m_shared.m_name)); } } [HarmonyPatch(typeof(Player), "TryPlacePiece")] [HarmonyPrefix] private static bool PrefixTryPlacePiece(Player __instance, Piece piece) { if (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || (Object)(object)Player.m_localPlayer != (Object)(object)__instance) { return true; } if ((Object)(object)piece == (Object)null) { return true; } if (IsPieceForbidden(piece)) { Message(piece.m_name); return false; } return true; } [HarmonyPatch(typeof(PieceTable), "UpdateAvailable")] [HarmonyPostfix] private static void PostfixUpdateAvailable(PieceTable __instance) { if (!_removeRecipesFromUIConfig.Value) { return; } foreach (List<Piece> availablePiece in __instance.m_availablePieces) { availablePiece.RemoveAll((Piece piece) => IsPieceForbidden(piece)); } } private static bool IsPieceForbidden(Piece piece) { if ((Object)(object)piece == (Object)null) { return false; } if (IsForbidden(piece.m_name)) { return true; } foreach (string pieceRequirement in CraftingDataCache.Get().GetPieceRequirements(piece.m_name)) { if (IsForbidden(pieceRequirement)) { return true; } } return false; } [HarmonyPatch(typeof(CookingStation), "OnUseItem")] [HarmonyPrefix] private static bool PrefixCookingStationUseItem(Humanoid user, ItemData item) { return CheckStationInput((Player)(object)((user is Player) ? user : null), item); } [HarmonyPatch(typeof(CookingStation), "OnAddFuelSwitch")] [HarmonyPrefix] private static bool PrefixCookingStationAddFuel(CookingStation __instance, Humanoid user) { Player val = (Player)(object)((user is Player) ? user : null); if (val == null) { return true; } if (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || (Object)(object)Player.m_localPlayer != (Object)(object)val) { return true; } if ((Object)(object)__instance.m_fuelItem == (Object)null) { return true; } if (!IsForbidden(__instance.m_fuelItem.m_itemData.m_shared.m_name)) { return true; } Message(__instance.m_fuelItem.m_itemData.m_shared.m_name, delayed: true); return false; } [HarmonyPatch(typeof(Fermenter), "AddItem")] [HarmonyPrefix] private static bool PrefixFermenterAddItem(Humanoid user, ItemData item) { return CheckStationInput((Player)(object)((user is Player) ? user : null), item); } [HarmonyPatch(typeof(Smelter), "OnAddOre")] [HarmonyPrefix] private static bool PrefixSmelterAddOre(Humanoid user, ItemData item) { if (item == null) { return true; } return CheckStationInput((Player)(object)((user is Player) ? user : null), item); } [HarmonyPatch(typeof(Smelter), "FindCookableItem")] [HarmonyPostfix] private static void PostfixFindCookableItem(Smelter __instance, Inventory inventory, ref ItemData __result) { if (__result == null || !IsForbidden(__result.m_shared.m_name)) { return; } string name = __result.m_shared.m_name; foreach (ItemData allItem in inventory.GetAllItems()) { if (allItem != __result && !(allItem.m_shared.m_name == __result.m_shared.m_name) && __instance.IsItemAllowed(((Object)allItem.m_dropPrefab).name) && !IsForbidden(allItem.m_shared.m_name)) { __result = allItem; return; } } __result = null; Message(name, delayed: true); } [HarmonyPatch(typeof(Smelter), "OnAddFuel")] [HarmonyPrefix] private static bool PrefixSmelterAddFuel(Smelter __instance, Humanoid user) { Player val = (Player)(object)((user is Player) ? user : null); if (val == null) { return true; } if (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || (Object)(object)Player.m_localPlayer != (Object)(object)val) { return true; } if ((Object)(object)__instance.m_fuelItem == (Object)null) { return true; } if (!IsForbidden(__instance.m_fuelItem.m_itemData.m_shared.m_name)) { return true; } Message(__instance.m_fuelItem.m_itemData.m_shared.m_name, delayed: true); return false; } private static bool CheckStationInput(Player player, ItemData item) { if ((Object)(object)player == (Object)null || !Object.op_Implicit((Object)(object)Player.m_localPlayer) || (Object)(object)Player.m_localPlayer != (Object)(object)player) { return true; } if (item == null) { return true; } if (IsForbidden(item.m_shared.m_name)) { Message(item.m_shared.m_name); return false; } return true; } private static void ResetForbiddenItems() { _forbiddenItemsCache = new HashSet<string>(); _allowedItemsCache = new HashSet<string>(); if (string.IsNullOrEmpty(_forbiddenItemsConfig.Value)) { _forbiddenItemsSet = new HashSet<string>(); } else { _forbiddenItemsSet = (from s in _forbiddenItemsConfig.Value.Split(new char[1] { ',' }) select s.Trim() into s where !string.IsNullOrEmpty(s) select s).ToHashSet<string>(StringComparer.Ordinal); } Logger.LogDebug((object)$"Forbidden items: {_forbiddenItemsSet.Count}"); } private static bool IsForbidden(string itemName) { if (_forbiddenItemsCache.Contains(itemName)) { return true; } if (_allowedItemsCache.Contains(itemName)) { return false; } bool num = ResolveItemForbidden(itemName, new HashSet<string>()); if (num) { _forbiddenItemsCache.Add(itemName); return num; } _allowedItemsCache.Add(itemName); return num; } private static bool ResolveItemForbidden(string itemName, HashSet<string> visited) { if (!visited.Add(itemName)) { return false; } if (_forbiddenItemsSet.Contains(itemName)) { return true; } CraftingDataCache craftingDataCache = CraftingDataCache.Get(); foreach (string recipeIngredient in craftingDataCache.GetRecipeIngredients(itemName)) { if (ResolveItemForbidden(recipeIngredient, visited)) { return true; } } foreach (string conversionSource in craftingDataCache.GetConversionSources(itemName)) { if (ResolveItemForbidden(conversionSource, visited)) { return true; } } return false; } private static void Message(string itemName, bool delayed = false) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { string message = GetMessage(itemName); if (delayed) { ((MonoBehaviour)_instance).StartCoroutine(DelayedMessage(message)); } else { ((Character)localPlayer).Message((MessageType)2, message, 0, (Sprite)null); } } } [IteratorStateMachine(typeof(<DelayedMessage>d__33))] private static IEnumerator DelayedMessage(string message) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DelayedMessage>d__33(0) { message = message }; } private static string GetMessage(string itemName) { string text = MessageKeys[Random.Range(0, MessageKeys.Length)]; return Localization.TryTranslate("$" + text).Replace("{item_name}", itemName); } } internal class CraftingDataCache { private static CraftingDataCache _instance; private readonly Dictionary<string, List<string>> _recipeIngredients; private readonly Dictionary<string, List<string>> _conversionSources; private readonly Dictionary<string, List<string>> _pieceRequirements; private CraftingDataCache() { _recipeIngredients = BuildRecipeCache(); _conversionSources = BuildConversionCache(); _pieceRequirements = BuildPieceCache(); } public static void Build() { _instance = new CraftingDataCache(); } public static CraftingDataCache Get() { if (_instance == null) { _instance = new CraftingDataCache(); } return _instance; } public static void Invalidate() { _instance = null; } public IEnumerable<string> GetRecipeIngredients(string outputItemName) { if (_recipeIngredients.TryGetValue(outputItemName, out var value)) { return value; } return Enumerable.Empty<string>(); } public IEnumerable<string> GetConversionSources(string outputItemName) { if (_conversionSources.TryGetValue(outputItemName, out var value)) { return value; } return Enumerable.Empty<string>(); } public IEnumerable<string> GetPieceRequirements(string pieceName) { if (_pieceRequirements.TryGetValue(pieceName, out var value)) { return value; } return Enumerable.Empty<string>(); } private static Dictionary<string, List<string>> BuildRecipeCache() { Logger.LogDebug((object)"Creating RecipeCache"); Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>(StringComparer.Ordinal); if ((Object)(object)ObjectDB.instance == (Object)null) { return dictionary; } foreach (Recipe recipe in ObjectDB.instance.m_recipes) { if ((Object)(object)recipe.m_item == (Object)null) { continue; } string name = recipe.m_item.m_itemData.m_shared.m_name; Requirement[] resources = recipe.m_resources; foreach (Requirement val in resources) { if (!((Object)(object)val.m_resItem == (Object)null)) { string name2 = val.m_resItem.m_itemData.m_shared.m_name; AddEntry(dictionary, name, name2); } } } return dictionary; } private static Dictionary<string, List<string>> BuildConversionCache() { Logger.LogDebug((object)"Creating ConversionDataCache"); Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>(StringComparer.Ordinal); if ((Object)(object)ZNetScene.instance == (Object)null) { return dictionary; } CookingStation val = default(CookingStation); Fermenter val2 = default(Fermenter); Smelter val3 = default(Smelter); foreach (GameObject value in ZNetScene.instance.m_namedPrefabs.Values) { if (!Object.op_Implicit((Object)(object)value)) { continue; } if (value.TryGetComponent<CookingStation>(ref val)) { foreach (ItemConversion item in val.m_conversion) { if (!((Object)(object)item.m_from == (Object)null) && !((Object)(object)item.m_to == (Object)null)) { AddEntry(dictionary, item.m_to.m_itemData.m_shared.m_name, item.m_from.m_itemData.m_shared.m_name); } } } if (value.TryGetComponent<Fermenter>(ref val2)) { foreach (ItemConversion item2 in val2.m_conversion) { if (!((Object)(object)item2.m_from == (Object)null) && !((Object)(object)item2.m_to == (Object)null)) { AddEntry(dictionary, item2.m_to.m_itemData.m_shared.m_name, item2.m_from.m_itemData.m_shared.m_name); } } } if (!value.TryGetComponent<Smelter>(ref val3)) { continue; } foreach (ItemConversion item3 in val3.m_conversion) { if (!((Object)(object)item3.m_from == (Object)null) && !((Object)(object)item3.m_to == (Object)null)) { AddEntry(dictionary, item3.m_to.m_itemData.m_shared.m_name, item3.m_from.m_itemData.m_shared.m_name); } } } return dictionary; } private static Dictionary<string, List<string>> BuildPieceCache() { Logger.LogDebug((object)"Creating PieceCache"); Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>(StringComparer.Ordinal); if ((Object)(object)ZNetScene.instance == (Object)null) { return dictionary; } Piece val = default(Piece); foreach (GameObject value in ZNetScene.instance.m_namedPrefabs.Values) { if (!Object.op_Implicit((Object)(object)value) || !value.TryGetComponent<Piece>(ref val) || val.m_resources == null || val.m_resources.Length == 0) { continue; } Requirement[] resources = val.m_resources; foreach (Requirement val2 in resources) { if (!((Object)(object)val2.m_resItem == (Object)null)) { AddEntry(dictionary, val.m_name, val2.m_resItem.m_itemData.m_shared.m_name); } } } return dictionary; } private static void AddEntry(Dictionary<string, List<string>> dict, string key, string value) { Logger.LogDebug((object)("Adding " + key + ": " + value)); if (!dict.TryGetValue(key, out var value2)) { value2 = (dict[key] = new List<string>()); } value2.Add(value); } }