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 ShopkeeperMood v1.0.0
ShopkeeperMood.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 System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("ShopkeeperMood")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Force the shop's security robot to always discount or always refuse presented items. Host only.")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("ShopkeeperMood")] [assembly: AssemblyTitle("ShopkeeperMood")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [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 ShopkeeperMood { internal static class Lang { internal class Row { public string Id; public string[] Sec; public string[] Name; public string[] Desc; } public const int En = 0; public static readonly string[] Options = new string[6] { "Auto", "English", "中文", "日本語", "한국어", "Tiếng Việt" }; internal static ConfigEntry<string> Cur; private static string _autoCode; private static float _autoAt = -99f; private static readonly string[][] ModeNames = new string[3][] { new string[5] { "Vanilla", "原版", "通常", "기본", "Gốc" }, new string[5] { "Always discount", "永远打折", "常に割引", "항상 할인", "Luôn giảm giá" }, new string[5] { "Always refuse", "永远拒绝", "常に拒否", "항상 거절", "Luôn từ chối" } }; private static readonly string[] SecGeneral = new string[5] { "1.General", "1.常规", "1.一般", "1.일반", "1.Chung" }; private static readonly string[] SecRefuse = new string[5] { "2.AlwaysRefuse", "2.永远拒绝", "2.常に拒否", "2.항상 거절", "2.Luôn từ chối" }; internal static readonly Row[] Rows = new Row[5] { new Row { Id = "mode", Sec = SecGeneral, Name = new string[5] { "Mode", "模式", "モード", "모드", "Chế độ" }, Desc = new string[5] { "Vanilla = original behaviour. AlwaysDiscount = the robot always picks the item up, inspects it and gives a discount, and never throws it away. AlwaysRefuse = the robot always refuses and throws the item away; if you keep presenting items after enough refusals, it gets angry, throws the item violently and the item explodes, then the count restarts. Host only, other players are synced automatically.", "Vanilla = 原版行为。AlwaysDiscount = 永远打折:机器人每次都会拿起物品观察并打折,不会扔掉。AlwaysRefuse = 永远拒绝:机器人直接把物品扔掉;连续被拒绝若干次后如果还继续给它,它会生气,暴力扔掉物品并使其爆炸,然后重新计数。仅主机需要,其他玩家自动同步。", "Vanilla = 通常の動作。AlwaysDiscount = 常に割引:ロボットは毎回アイテムを手に取って観察し、割引して、投げ捨てません。AlwaysRefuse = 常に拒否:アイテムを投げ捨てます。連続で拒否された後もアイテムを見せ続けると怒って乱暴に投げ、アイテムが爆発し、カウントがリセットされます。ホストのみ有効で、他のプレイヤーには自動で同期されます。", "Vanilla = 기본 동작. AlwaysDiscount = 항상 할인: 로봇이 매번 아이템을 집어 살펴보고 할인해 주며 절대 던지지 않습니다. AlwaysRefuse = 항상 거절: 로봇이 아이템을 던져 버립니다. 연속으로 거절한 뒤에도 계속 아이템을 보여 주면 화가 나서 아이템을 세게 던지고 폭발시킨 다음 횟수를 초기화합니다. 호스트만 적용되며 다른 플레이어에게 자동으로 동기화됩니다.", "Vanilla = hành vi gốc. AlwaysDiscount = luôn giảm giá: robot lần nào cũng nhặt món đồ lên xem và giảm giá, không bao giờ ném đi. AlwaysRefuse = luôn từ chối: robot ném món đồ đi; sau một số lần từ chối liên tiếp, nếu bạn vẫn đưa đồ tiếp, nó sẽ nổi giận, ném mạnh và làm món đồ phát nổ, rồi đếm lại từ đầu. Chỉ chủ phòng cần cài, người chơi khác được đồng bộ tự động." } }, new Row { Id = "key", Sec = SecGeneral, Name = new string[5] { "Cycle mode key", "切换模式快捷键", "モード切替キー", "모드 전환 키", "Phím đổi chế độ" }, Desc = new string[5] { "Host only: press in game to cycle Vanilla, AlwaysDiscount, AlwaysRefuse.", "仅主机:游戏内按下后依次切换 原版、永远打折、永远拒绝。", "ホストのみ:ゲーム中に押すと 通常、常に割引、常に拒否 の順に切り替わります。", "호스트 전용: 게임 중에 누르면 기본, 항상 할인, 항상 거절 순서로 전환됩니다.", "Chỉ chủ phòng: nhấn trong game để chuyển lần lượt Gốc, Luôn giảm giá, Luôn từ chối." } }, new Row { Id = "toast", Sec = SecGeneral, Name = new string[5] { "Show on-screen message", "显示屏幕提示", "画面メッセージを表示", "화면 메시지 표시", "Hiện thông báo trên màn hình" }, Desc = new string[5] { "Show a short message when the mode changes.", "切换模式时在屏幕上显示一条简短提示。", "モードを切り替えたときに短いメッセージを表示します。", "모드를 전환할 때 짧은 메시지를 표시합니다.", "Hiện một thông báo ngắn khi đổi chế độ." } }, new Row { Id = "angry", Sec = SecRefuse, Name = new string[5] { "Angry violent throw", "愤怒暴力扔出", "怒りの乱暴な投げ捨て", "분노의 거친 던지기", "Ném giận dữ" }, Desc = new string[5] { "AlwaysRefuse only. After the refusal limit, the next item you present makes the robot angry: it throws the item violently and the item explodes. Then the count restarts. Off = it just keeps refusing politely.", "仅「永远拒绝」模式。拒绝达到上限后,再给它的下一件物品会让它生气:暴力扔掉并使物品爆炸,之后重新计数。关闭则一直只是普通拒绝。", "「常に拒否」モード専用。拒否回数が上限に達した後に次のアイテムを見せると怒って乱暴に投げ、アイテムが爆発します。その後カウントはリセットされます。オフなら通常の拒否のみ行います。", "'항상 거절' 모드 전용. 거절 횟수가 한도에 도달한 뒤 다음 아이템을 보여 주면 로봇이 화가 나서 아이템을 거칠게 던지고 폭발시킵니다. 이후 횟수가 초기화됩니다. 끄면 계속 일반 거절만 합니다.", "Chỉ dành cho chế độ Luôn từ chối. Khi đạt giới hạn số lần từ chối, món đồ tiếp theo bạn đưa sẽ làm robot nổi giận: nó ném mạnh và món đồ phát nổ, sau đó đếm lại từ đầu. Tắt = chỉ từ chối bình thường." } }, new Row { Id = "limit", Sec = SecRefuse, Name = new string[5] { "Refusals before anger", "生气前的拒绝次数", "怒るまでの拒否回数", "화내기 전 거절 횟수", "Số lần từ chối trước khi giận" }, Desc = new string[5] { "How many plain refusals (item thrown away) happen before the robot gets angry. Default 3.", "机器人生气之前,会先普通拒绝(扔掉物品)多少次。默认 3。", "怒るまでに通常の拒否(アイテムを投げ捨てる)を何回行うか。既定値は 3。", "로봇이 화내기 전에 일반 거절(아이템 던지기)을 몇 번 하는지. 기본값 3.", "Số lần từ chối thường (ném đồ đi) trước khi robot nổi giận. Mặc định 3." } } }; public static int Idx { get { string text = ((Cur != null) ? Cur.Value : "Auto"); for (int i = 1; i < Options.Length; i++) { if (text == Options[i]) { return i - 1; } } return FromGame(); } } public static string HostOnly => Pick("Host only", "只有主机可以切换", "ホストのみ切り替え可能", "호스트만 전환할 수 있습니다", "Chỉ chủ phòng mới đổi được"); public static string Title => Pick("Shop robot", "商店机器人", "ショップロボット", "상점 로봇", "Robot cửa hàng"); private static int FromGame() { if (_autoCode == null || Time.unscaledTime - _autoAt > 1f) { _autoAt = Time.unscaledTime; try { _autoCode = (SemiFunc.LocaleGetCode() ?? "en").ToLowerInvariant(); } catch { _autoCode = "en"; } } if (_autoCode.StartsWith("zh")) { return 1; } if (_autoCode.StartsWith("ja")) { return 2; } if (_autoCode.StartsWith("ko")) { return 3; } if (_autoCode.StartsWith("vi")) { return 4; } return 0; } public static string Pick(params string[] v) { int idx = Idx; if (idx >= v.Length || string.IsNullOrEmpty(v[idx])) { return v[0]; } return v[idx]; } public static string ModeName(Mood m) { return ModeNames[(int)m][Idx]; } public static string[] ModeNameList() { int idx = Idx; return new string[3] { ModeNames[0][idx], ModeNames[1][idx], ModeNames[2][idx] }; } public static bool TryParseMode(string s, out Mood mood) { mood = Mood.AlwaysDiscount; if (string.IsNullOrWhiteSpace(s)) { return false; } s = s.Trim().Trim('"'); for (int i = 0; i < ModeNames.Length; i++) { string[] array = ModeNames[i]; for (int j = 0; j < array.Length; j++) { if (string.Equals(array[j], s, StringComparison.OrdinalIgnoreCase)) { mood = (Mood)i; return true; } } } return Enum.TryParse<Mood>(s, ignoreCase: true, out mood); } internal static Row Find(string id) { Row[] rows = Rows; foreach (Row row in rows) { if (row.Id == id) { return row; } } return null; } } internal static class LangHost { private static ConfigFile _c; private static readonly Dictionary<string, ConfigEntryBase> Map = new Dictionary<string, ConfigEntryBase>(); private static readonly Dictionary<string, string> Legacy = new Dictionary<string, string> { { "mode", "Mode" }, { "key", "CycleKey" }, { "toast", "ShowToast" } }; private static int _applied = -1; private static float _refreshAt = -1f; public static void Init(ConfigFile c) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown _c = c; Lang.Cur = c.Bind<string>("0.Language", "Language", "Auto", new ConfigDescription("Auto = follow the game language (English if unsupported) / 自动=跟随游戏语言,不支持则英文 / 自動=ゲームの言語に従う(非対応なら英語) / 자동=게임 언어를 따름(미지원 시 영어) / Tự động = theo ngôn ngữ game (không hỗ trợ thì dùng tiếng Anh)", (AcceptableValueBase)(object)new AcceptableValueList<string>(Lang.Options), Array.Empty<object>())); Lang.Cur.SettingChanged += delegate { Apply(); }; _applied = Lang.Idx; } public static ConfigEntry<T> B<T>(string id, T def, AcceptableValueBase range = null) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown Lang.Row row = Lang.Find(id); int idx = Lang.Idx; string saved = FindSaved(row); ConfigEntry<T> val = _c.Bind<T>(row.Sec[idx], row.Name[idx], def, new ConfigDescription(row.Desc[idx], range, Array.Empty<object>())); Map[id] = (ConfigEntryBase)(object)val; RestoreSaved((ConfigEntryBase)(object)val, id, saved); return val; } public static ConfigEntry<string> BindMode(Mood def) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown Lang.Row row = Lang.Find("mode"); int idx = Lang.Idx; string saved = FindSaved(row); ConfigEntry<string> val = _c.Bind<string>(row.Sec[idx], row.Name[idx], Lang.ModeName(def), new ConfigDescription(row.Desc[idx], (AcceptableValueBase)(object)new AcceptableValueList<string>(Lang.ModeNameList()), Array.Empty<object>())); Map["mode"] = (ConfigEntryBase)(object)val; RestoreSaved((ConfigEntryBase)(object)val, "mode", saved); return val; } private static string FindSaved(Lang.Row r) { try { if (!(GetMember(_c, "OrphanedEntries") is IDictionary dictionary)) { return null; } string result = null; foreach (DictionaryEntry item in dictionary) { object key = item.Key; ConfigDefinition val = (ConfigDefinition)((key is ConfigDefinition) ? key : null); if (val == (ConfigDefinition)null) { continue; } string value; bool flag = Legacy.TryGetValue(r.Id, out value) && val.Key == value; int num = 0; while (!flag && num < r.Name.Length) { flag = val.Key == r.Name[num]; num++; } if (flag) { result = item.Value as string; if (val.Section == r.Sec[Lang.Idx] && val.Key == r.Name[Lang.Idx]) { break; } } } return result; } catch { return null; } } private static void RestoreSaved(ConfigEntryBase e, string id, string saved) { if (saved == null) { return; } try { if (id == "mode") { if (Lang.TryParseMode(saved, out var mood)) { ((ConfigEntry<string>)(object)e).Value = Lang.ModeName(mood); } } else { e.SetSerializedValue(saved); } } catch { } } public static void Finish() { try { if (GetMember(_c, "OrphanedEntries") is IDictionary dictionary) { dictionary.Clear(); } _c.Save(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Config cleanup: " + ex.Message)); } } public static void Tick() { if (_applied >= 0 && Lang.Idx != _applied) { Apply(); } if (_refreshAt >= 0f && Time.unscaledTime >= _refreshAt) { _refreshAt = -1f; RefreshMenu(); } } private static void Apply() { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Expected O, but got Unknown if (_c == null) { return; } try { Mood curMode = Plugin.CurMode; int num = (_applied = Lang.Idx); foreach (KeyValuePair<string, ConfigEntryBase> item in Map) { Lang.Row row = Lang.Find(item.Key); ConfigEntryBase value = item.Value; object obj; if (!(item.Key == "mode")) { ConfigDescription description = value.Description; obj = ((description != null) ? description.AcceptableValues : null); } else { obj = new AcceptableValueList<string>(Lang.ModeNameList()); } AcceptableValueBase val = (AcceptableValueBase)obj; SetBacking(value, "Definition", (object)new ConfigDefinition(row.Sec[num], row.Name[num])); string obj2 = row.Desc[num]; ConfigDescription description2 = value.Description; SetBacking(value, "Description", (object)new ConfigDescription(obj2, val, ((description2 != null) ? description2.Tags : null) ?? new object[0])); } if (GetMember(_c, "Entries") is IDictionary dictionary) { dictionary.Clear(); foreach (ConfigEntryBase value2 in Map.Values) { dictionary[value2.Definition] = value2; } dictionary[((ConfigEntryBase)Lang.Cur).Definition] = Lang.Cur; } else { Plugin.Log.LogWarning((object)"ConfigFile.Entries not found, config menu texts may not switch"); } if (Plugin.Mode != null) { Plugin.Mode.Value = Lang.ModeName(curMode); } if (GetMember(_c, "OrphanedEntries") is IDictionary dictionary2) { dictionary2.Clear(); } _c.Save(); _refreshAt = Time.unscaledTime + 0.15f; Plugin.Log.LogInfo((object)("Language -> " + Lang.Options[num + 1])); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Language switch failed: " + ex.Message)); } } private static object GetMember(object obj, string name) { Type type = obj.GetType(); while (type != null) { FieldInfo fieldInfo = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? type.GetField("<" + name + ">k__BackingField", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (fieldInfo != null) { return fieldInfo.GetValue(obj); } PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.GetIndexParameters().Length == 0) { return property.GetValue(obj); } type = type.BaseType; } return null; } private static void SetBacking(object obj, string member, object val) { Type type = obj.GetType(); while (type != null) { FieldInfo field = type.GetField("<" + member + ">k__BackingField", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { field.SetValue(obj, val); return; } type = type.BaseType; } throw new MissingFieldException(obj.GetType().Name, member); } private static void RefreshMenu() { try { Type type = FindType("MenuLib.MenuAPI"); Type type2 = FindType("REPOConfig.ConfigMenu"); if (type == null || type2 == null) { return; } FieldInfo field = type2.GetField("hasPopupMenuOpened", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { object value = field.GetValue(null); if (value is bool && !(bool)value) { return; } } type.GetMethod("CloseAllPagesAddedOnTop", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null)?.Invoke(null, null); type2.GetMethod("CreateModMenu", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null)?.Invoke(null, null); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Menu refresh: " + ex.Message)); } } private static Type FindType(string name) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { Type type = assemblies[i].GetType(name, throwOnError: false); if (type != null) { return type; } } return null; } } internal static class Patches { private class Track { public int Denied; public bool Forced; } private static readonly Dictionary<ShopKeeper, Track> Tracks = new Dictionary<ShopKeeper, Track>(); private static Track Get(ShopKeeper s) { if (!Tracks.TryGetValue(s, out var value)) { value = new Track(); Tracks[s] = value; } return value; } private static bool Master() { return SemiFunc.IsMasterClientOrSingleplayer(); } private static void Warn(Exception ex) { Plugin.Log.LogWarning((object)ex.ToString()); } [HarmonyPatch(typeof(ShopKeeper), "ItemScanProximityLogic")] [HarmonyPrefix] private static void ProximityPrefix(ShopKeeper __instance) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Invalid comparison between Unknown and I4 try { if (!Master()) { return; } Track track = Get(__instance); switch (Plugin.CurMode) { case Mood.AlwaysDiscount: __instance.itemDiscountAttempts = 0; track.Denied = 0; track.Forced = false; break; case Mood.AlwaysRefuse: track.Forced = true; if (!Plugin.RefuseAngry.Value || track.Denied < Plugin.RefuseLimit.Value) { __instance.itemDiscountAttempts = 3; } else if ((int)__instance.currentState == 3) { __instance.itemDiscountAttempts = 0; } break; default: if (track.Forced) { __instance.itemDiscountAttempts = 0; track.Denied = 0; track.Forced = false; } break; } } catch (Exception ex) { Warn(ex); } } [HarmonyPatch(typeof(ShopKeeper), "ItemDiscountDeniedSet")] [HarmonyPostfix] private static void DeniedPostfix(ShopKeeper __instance) { try { if (Master() && Plugin.CurMode == Mood.AlwaysRefuse) { Track track = Get(__instance); track.Denied++; Plugin.Log.LogInfo((object)("Shop robot refused an item (" + track.Denied + "/" + Plugin.RefuseLimit.Value + ")")); } } catch (Exception ex) { Warn(ex); } } [HarmonyPatch(typeof(ShopKeeper), "ItemVerdictPositiveGet")] [HarmonyPrefix] private static bool VerdictPrefix(ShopKeeper __instance, ref bool __result) { try { Mood curMode = Plugin.CurMode; if (!Master() || curMode == Mood.Vanilla) { return true; } if (!__instance.ItemTargetValid() || !__instance.ItemDiscountTargetValid(__instance.itemReactObject)) { __result = false; return false; } bool flag = curMode == Mood.AlwaysDiscount; ShopKeeperItemReaction orAdd = ShopKeeperItemReaction.GetOrAdd(((Component)__instance.itemReactObject).gameObject); __instance.ItemShownSet(__instance.itemReactObject, orAdd.TimesShownGet() + 1, !flag); __result = flag; return false; } catch (Exception ex) { Warn(ex); return true; } } [HarmonyPatch(typeof(ShopKeeper), "ItemDislikeAffectApply")] [HarmonyPrefix] private static void DislikePrefix(ShopKeeper __instance) { try { if (Master() && Plugin.CurMode == Mood.AlwaysRefuse) { Get(__instance).Denied = 0; Plugin.Log.LogInfo((object)"Shop robot threw an item angrily, refusal count reset"); } } catch (Exception ex) { Warn(ex); } } [HarmonyPatch(typeof(ShopKeeper), "ItemPresentationTargetValid")] [HarmonyPostfix] private static void PresentationPostfix(ShopKeeper __instance, PhysGrabObject _physGrab, ref bool __result) { try { if (__result && Master() && Plugin.CurMode == Mood.AlwaysRefuse && !__instance.ItemDiscountTargetValid(_physGrab)) { __result = false; } } catch (Exception ex) { Warn(ex); } } } public enum Mood { Vanilla, AlwaysDiscount, AlwaysRefuse } [BepInPlugin("com.yanyan.repo.shopkeepermood", "Shopkeeper Mood 商店机器人情绪", "1.0.0")] public class Plugin : BaseUnityPlugin { public const string Guid = "com.yanyan.repo.shopkeepermood"; public const string Version = "1.0.0"; internal static ManualLogSource Log; internal static ConfigEntry<string> Mode; internal static ConfigEntry<KeyCode> CycleKey; internal static ConfigEntry<bool> ShowToast; internal static ConfigEntry<bool> RefuseAngry; internal static ConfigEntry<int> RefuseLimit; private Harmony _harmony; private string _toast; private float _toastT = -99f; internal static Mood CurMode { get { if (Mode == null || !Lang.TryParseMode(Mode.Value, out var mood)) { return Mood.AlwaysDiscount; } return mood; } } private void Awake() { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; LangHost.Init(((BaseUnityPlugin)this).Config); Mode = LangHost.BindMode(Mood.AlwaysDiscount); CycleKey = LangHost.B<KeyCode>("key", (KeyCode)286); ShowToast = LangHost.B("toast", def: true); RefuseAngry = LangHost.B("angry", def: true); RefuseLimit = LangHost.B("limit", 3, (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10)); LangHost.Finish(); _harmony = new Harmony("com.yanyan.repo.shopkeepermood"); _harmony.PatchAll(typeof(Patches)); Log.LogInfo((object)("Shopkeeper Mood 1.0.0 loaded, mode = " + CurMode)); } private void Update() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) try { LangHost.Tick(); if ((int)CycleKey.Value != 0 && Input.GetKeyDown(CycleKey.Value)) { if (!SemiFunc.IsMasterClientOrSingleplayer()) { Toast(Lang.HostOnly); return; } Mood m = (Mood)((int)(CurMode + 1) % 3); Mode.Value = Lang.ModeName(m); Toast(Lang.Title + ": " + Lang.ModeName(m)); } } catch (Exception ex) { Log.LogWarning((object)ex.ToString()); } } private void Toast(string s) { if (ShowToast.Value) { _toast = s; _toastT = Time.unscaledTime; } } private void OnGUI() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_006b: 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) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) if (_toast != null && !(Time.unscaledTime - _toastT > 2.5f)) { GUIStyle val = new GUIStyle(GUI.skin.label) { fontSize = 22, alignment = (TextAnchor)4, fontStyle = (FontStyle)1 }; Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(0f, (float)Screen.height * 0.2f, (float)Screen.width, 40f); val.normal.textColor = Color.black; GUI.Label(new Rect(((Rect)(ref val2)).x + 2f, ((Rect)(ref val2)).y + 2f, ((Rect)(ref val2)).width, ((Rect)(ref val2)).height), _toast, val); val.normal.textColor = Color.white; GUI.Label(val2, _toast, val); } } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }