Please disclose if your mod was created primarily 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 Glitnir Timekeeper v4.4.0
Timekeeper.dll
Decompiled 5 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using JetBrains.Annotations; using LocalizationManager; using Managers; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using ServerSync; using TMPro; using Timekeeper.Managers; using UnityEngine; using UnityEngine.Events; using UnityEngine.Networking; using UnityEngine.UI; [assembly: Guid("4358610B-F3F4-4843-B7AF-98B7BC60DCDE")] [assembly: ComVisible(false)] [assembly: AssemblyTrademark("")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyProduct("Timekeeper")] [assembly: AssemblyCompany("RustyMods")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyDescription("")] [assembly: AssemblyTitle("Timekeeper")] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: CompilationRelaxations(8)] [assembly: AssemblyFileVersion("1.0.2")] [assembly: AssemblyConfiguration("")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.2.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [<8b5605b8-2a90-4f12-892b-5b97acc01c23>Embedded] internal sealed class <8b5605b8-2a90-4f12-892b-5b97acc01c23>EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [<8b5605b8-2a90-4f12-892b-5b97acc01c23>Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class <0e657ea4-f9a5-4535-99f9-133b42a018b4>NullableAttribute : Attribute { public readonly byte[] NullableFlags; public <0e657ea4-f9a5-4535-99f9-133b42a018b4>NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public <0e657ea4-f9a5-4535-99f9-133b42a018b4>NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [<8b5605b8-2a90-4f12-892b-5b97acc01c23>Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class <b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContextAttribute : Attribute { public readonly byte Flag; public <b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace LocalizationManager { [PublicAPI] [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(0)] [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] public class Localizer { private static readonly Dictionary<string, Dictionary<string, Func<string>>> PlaceholderProcessors; private static readonly Dictionary<string, Dictionary<string, string>> loadedTexts; private static readonly ConditionalWeakTable<Localization, string> localizationLanguage; private static readonly List<WeakReference<Localization>> localizationObjects; [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(2)] private static BaseUnityPlugin _plugin; private static readonly List<string> fileExtensions; private static BaseUnityPlugin plugin { get { //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown if (_plugin == null) { IEnumerable<TypeInfo> source; try { source = Assembly.GetExecutingAssembly().DefinedTypes.ToList(); } catch (ReflectionTypeLoadException ex) { source = from t in ex.Types where t != null select t.GetTypeInfo(); } _plugin = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First([<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(0)] (TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t))); } return _plugin; } } private static void UpdatePlaceholderText(Localization localization, string key) { localizationLanguage.TryGetValue(localization, out var value); string text = loadedTexts[value][key]; if (PlaceholderProcessors.TryGetValue(key, out var value2)) { text = value2.Aggregate(text, [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(0)] (string current, KeyValuePair<string, Func<string>> kv) => current.Replace("{" + kv.Key + "}", kv.Value())); } localization.AddWord(key, text); } public static void AddPlaceholder<T>(string key, string placeholder, ConfigEntry<T> config, [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(new byte[] { 2, 1, 1 })] Func<T, string> convertConfigValue = null) { if (convertConfigValue == null) { convertConfigValue = [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(0)] [return: <0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(1)] (T val) => val.ToString(); } if (!PlaceholderProcessors.ContainsKey(key)) { PlaceholderProcessors[key] = new Dictionary<string, Func<string>>(); } config.SettingChanged += [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(0)] (object _, EventArgs _) => { UpdatePlaceholder(); }; if (loadedTexts.ContainsKey(Localization.instance.GetSelectedLanguage())) { UpdatePlaceholder(); } void UpdatePlaceholder() { PlaceholderProcessors[key][placeholder] = () => convertConfigValue(config.Value); UpdatePlaceholderText(Localization.instance, key); } } public static void AddText(string key, string text) { List<WeakReference<Localization>> list = new List<WeakReference<Localization>>(); foreach (WeakReference<Localization> localizationObject in localizationObjects) { if (localizationObject.TryGetTarget(out var target)) { Dictionary<string, string> dictionary = loadedTexts[localizationLanguage.GetOrCreateValue(target)]; if (!target.m_translations.ContainsKey(key)) { dictionary[key] = text; target.AddWord(key, text); } } else { list.Add(localizationObject); } } foreach (WeakReference<Localization> item in list) { localizationObjects.Remove(item); } } public static void Load() { LoadLocalization(Localization.instance, Localization.instance.GetSelectedLanguage()); } private static void LoadLocalization(Localization __instance, string language) { //IL_01a6: Expected O, but got Unknown //IL_02a6: Expected O, but got Unknown if (!localizationLanguage.Remove(__instance)) { localizationObjects.Add(new WeakReference<Localization>(__instance)); } localizationLanguage.Add(__instance, language); Dictionary<string, string> dictionary = new Dictionary<string, string>(); foreach (string item in from f in Directory.GetFiles(Path.GetDirectoryName(Paths.PluginPath), plugin.Info.Metadata.Name + ".*", SearchOption.AllDirectories) where fileExtensions.IndexOf(Path.GetExtension(f)) >= 0 select f) { string text = Path.GetFileNameWithoutExtension(item).Split(new char[1] { '.' })[1]; if (dictionary.ContainsKey(text)) { Debug.LogWarning((object)("Duplicate key " + text + " found for " + plugin.Info.Metadata.Name + ". The duplicate file found at " + item + " will be skipped.")); } else { dictionary[text] = item; } } byte[] array = LoadTranslationFromAssembly("English"); if (array == null) { throw new Exception("Found no English localizations in mod " + plugin.Info.Metadata.Name + ". Expected an embedded resource translations/English.json."); } Dictionary<string, string> dictionary2; try { dictionary2 = JsonConvert.DeserializeObject<Dictionary<string, string>>(Encoding.UTF8.GetString(array)); } catch (JsonException val) { JsonException val2 = val; throw new Exception("Localization for mod " + plugin.Info.Metadata.Name + " failed: Invalid JSON in English localization file. " + ((Exception)(object)val2).Message); } if (dictionary2 == null) { throw new Exception("Localization for mod " + plugin.Info.Metadata.Name + " failed: Localization file was empty."); } string text2 = null; if (language != "English") { if (dictionary.ContainsKey(language)) { text2 = File.ReadAllText(dictionary[language]); } else { byte[] array2 = LoadTranslationFromAssembly(language); if (array2 != null) { text2 = Encoding.UTF8.GetString(array2); } } } if (text2 == null && dictionary.ContainsKey("English")) { text2 = File.ReadAllText(dictionary["English"]); } if (text2 != null) { Dictionary<string, string> dictionary3; try { dictionary3 = JsonConvert.DeserializeObject<Dictionary<string, string>>(text2); } catch (JsonException val3) { JsonException val4 = val3; throw new Exception("Localization for mod " + plugin.Info.Metadata.Name + " failed: Invalid JSON in " + language + " localization file. " + ((Exception)(object)val4).Message); } foreach (KeyValuePair<string, string> item2 in dictionary3 ?? new Dictionary<string, string>()) { dictionary2[item2.Key] = item2.Value; } } loadedTexts[language] = dictionary2; foreach (KeyValuePair<string, string> item3 in dictionary2) { UpdatePlaceholderText(__instance, item3.Key); } } static Localizer() { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown PlaceholderProcessors = new Dictionary<string, Dictionary<string, Func<string>>>(); loadedTexts = new Dictionary<string, Dictionary<string, string>>(); localizationLanguage = new ConditionalWeakTable<Localization, string>(); localizationObjects = new List<WeakReference<Localization>>(); fileExtensions = new List<string> { ".json" }; Harmony val = new Harmony("org.bepinex.helpers.LocalizationManager"); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Localization), "LoadCSV", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalization", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } [return: <0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(2)] private static byte[] LoadTranslationFromAssembly(string language) { foreach (string fileExtension in fileExtensions) { byte[] array = ReadEmbeddedFileBytes("translations." + language + fileExtension); if (array != null) { return array; } } return null; } [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(2)] public static byte[] ReadEmbeddedFileBytes([<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(1)] string resourceFileName, Assembly containingAssembly = null) { using MemoryStream memoryStream = new MemoryStream(); if ((object)containingAssembly == null) { containingAssembly = Assembly.GetCallingAssembly(); } string text = containingAssembly.GetManifestResourceNames().FirstOrDefault([<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(0)] (string str) => str.EndsWith(resourceFileName, StringComparison.Ordinal)); if (text != null) { containingAssembly.GetManifestResourceStream(text)?.CopyTo(memoryStream); } return (memoryStream.Length == 0L) ? null : memoryStream.ToArray(); } } } namespace Timekeeper { [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(0)] [BepInPlugin("RustyMods.Timekeeper", "Timekeeper", "1.0.2")] public class TimekeeperPlugin : BaseUnityPlugin { [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(0)] public enum Toggle { On = 1, Off = 0 } internal const string ModName = "Timekeeper"; internal const string ModVersion = "1.0.2"; internal const string Author = "RustyMods"; private const string ModGUID = "RustyMods.Timekeeper"; private static readonly string ConfigFileName = "RustyMods.Timekeeper.cfg"; private static readonly string ConfigFileFullPath; internal static string ConnectionError; private readonly Harmony _harmony = new Harmony("RustyMods.Timekeeper"); public static readonly ManualLogSource TimekeeperLogger; public static readonly ConfigSync ConfigSync; public static TimekeeperPlugin instance; private static ConfigEntry<Toggle> _serverConfigLocked; public void Awake() { instance = this; Timekeeper.Setup(); TimeMan.Setup(); Localizer.Load(); Webhook.Setup(); CommandManager.Setup(); _serverConfigLocked = config("1 - General", "Lock Configuration", Toggle.On, "If on, the configuration is locked and can be changed by server admins only."); ConfigSync.AddLockingConfigEntry<Toggle>(_serverConfigLocked); Assembly executingAssembly = Assembly.GetExecutingAssembly(); _harmony.PatchAll(executingAssembly); SetupWatcher(); } private void OnDestroy() { ((BaseUnityPlugin)this).Config.Save(); } private void SetupWatcher() { FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, ConfigFileName); fileSystemWatcher.Changed += ReadConfigValues; fileSystemWatcher.Created += ReadConfigValues; fileSystemWatcher.Renamed += ReadConfigValues; fileSystemWatcher.IncludeSubdirectories = true; fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher.EnableRaisingEvents = true; } private void ReadConfigValues(object sender, FileSystemEventArgs e) { if (!File.Exists(ConfigFileFullPath)) { return; } try { TimekeeperLogger.LogDebug((object)"ReadConfigValues called"); ((BaseUnityPlugin)this).Config.Reload(); } catch { TimekeeperLogger.LogError((object)("There was an issue loading your " + ConfigFileName)); TimekeeperLogger.LogError((object)"Please check your config entries for spelling and format!"); } } public ConfigEntry<T> config<[<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(2)] T>(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown ConfigDescription val = new ConfigDescription(description.Description + (synchronizedSetting ? " [Synced with Server]" : " [Not Synced with Server]"), description.AcceptableValues, description.Tags); ConfigEntry<T> val2 = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, val); SyncedConfigEntry<T> syncedConfigEntry = ConfigSync.AddConfigEntry<T>(val2); syncedConfigEntry.SynchronizedConfig = synchronizedSetting; return val2; } public ConfigEntry<T> config<[<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(2)] T>(string group, string name, T value, string description, bool synchronizedSetting = true) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting); } static TimekeeperPlugin() { string configPath = Paths.ConfigPath; char directorySeparatorChar = Path.DirectorySeparatorChar; ConfigFileFullPath = configPath + directorySeparatorChar + ConfigFileName; ConnectionError = ""; TimekeeperLogger = Logger.CreateLogSource("Timekeeper"); ConfigSync = new ConfigSync("RustyMods.Timekeeper") { DisplayName = "Timekeeper", CurrentVersion = "1.0.2", MinimumRequiredVersion = "1.0.2" }; instance = null; _serverConfigLocked = null; } } [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(0)] public static class Helpers { public static void SetText(this GameObject prefab, string childName, string text) { Transform val = Utils.FindChild(prefab.transform, childName, (IterativeSearchType)0); Text val2 = default(Text); if (!((Object)(object)val == (Object)null) && ((Component)val).TryGetComponent<Text>(ref val2)) { val2.text = Localization.instance.Localize(text); } } public static void CopySpriteAndMaterial(this GameObject prefab, GameObject source, string childName, string sourceChildName = "") { Image component = ((Component)prefab.transform.Find(childName)).GetComponent<Image>(); Image component2 = ((Component)source.transform.Find(Utility.IsNullOrWhiteSpace(sourceChildName) ? childName : sourceChildName)).GetComponent<Image>(); component.sprite = component2.sprite; ((Graphic)component).material = ((Graphic)component2).material; } public static void CopyButtonState(this GameObject prefab, GameObject source, string childName, string sourceChildName = "") { //IL_002e: Unknown result type (might be due to invalid IL or missing references) ((Selectable)((Component)prefab.transform.Find(childName)).GetComponent<Button>()).spriteState = ((Selectable)((Component)source.transform.Find(Utility.IsNullOrWhiteSpace(sourceChildName) ? childName : sourceChildName)).GetComponent<Button>()).spriteState; } } [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(0)] [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] public class Timekeeper : MonoBehaviour { [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(0)] private enum PanelType { Opaque, Transparent } [HarmonyPatch(typeof(Menu), "Start")] [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(0)] private static class Menu_Start_Patch { [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] private static void Postfix(Menu __instance) { //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Expected O, but got Unknown Sprite sprite = ((Component)((Component)((Component)__instance).transform.parent.Find("Inventory_screen")).GetComponent<InventoryGui>().m_trophieElementPrefab.transform.Find("icon_bkg")).GetComponent<Image>().sprite; GameObject val = Object.Instantiate<GameObject>(((Component)((Transform)__instance.menuEntriesParent).Find("Settings")).gameObject, (Transform)(object)__instance.menuEntriesParent); ((Object)val).name = "Timekeeper"; val.transform.SetAsFirstSibling(); TMP_Text MenuLabel = val.GetComponentInChildren<TMP_Text>(); MenuLabel.text = Localization.instance.Localize("$label_timekeeper"); ((UnityEventBase)val.GetComponent<Button>().onClick).RemoveAllListeners(); ((UnityEvent)val.GetComponent<Button>().onClick).AddListener(new UnityAction(OnOpen)); GameObject sfxPrefab = __instance.m_settingsPrefab.GetComponentInChildren<ButtonSfx>().m_sfxPrefab; ButtonSfx[] componentsInChildren = m_root.GetComponentsInChildren<ButtonSfx>(true); foreach (ButtonSfx val2 in componentsInChildren) { val2.m_sfxPrefab = sfxPrefab; } m_item.GetComponent<ButtonSfx>().m_sfxPrefab = sfxPrefab; ((Component)m_item.transform.Find("Background")).GetComponent<Image>().sprite = sprite; ((Component)m_star.transform.Find("Day")).gameObject.SetActive(false); m_root.CopySpriteAndMaterial(__instance.m_settingsPrefab, "Panel"); m_root.CopySpriteAndMaterial(__instance.m_settingsPrefab, "Panel/TabContent"); m_root.CopySpriteAndMaterial(__instance.m_settingsPrefab, "Panel/HeaderLine"); m_root.CopySpriteAndMaterial(__instance.m_settingsPrefab, "Panel/Back"); m_root.CopySpriteAndMaterial(__instance.m_settingsPrefab, "Panel/Collect", "Panel/Ok"); m_root.CopyButtonState(__instance.m_settingsPrefab, "Panel/Back"); m_root.CopyButtonState(__instance.m_settingsPrefab, "Panel/Collect", "Panel/Ok"); FontManager.SetFont(m_root.GetComponentsInChildren<Text>(true)); FontManager.SetFont(m_item.GetComponentsInChildren<Text>(true)); FontManager.SetFont(m_star.GetComponentsInChildren<Text>(true)); m_root.AddComponent<Timekeeper>(); Localization.OnLanguageChange = (Action)Delegate.Combine(Localization.OnLanguageChange, (Action)delegate { MenuLabel.text = Localization.instance.Localize("$label_timekeeper"); }); } } private static GameObject m_root; private static GameObject m_item; private static GameObject m_star; private static ConfigEntry<float> m_scale; private static ConfigEntry<PanelType> m_panelBackground; private static ConfigEntry<TimekeeperPlugin.Toggle> m_sendOnCollect; [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(2)] private static Timekeeper instance; public Image m_panel = null; public Image m_darken = null; public Text m_title = null; public Text m_description = null; public Text m_timeLabel = null; public Text m_time = null; public GameObject m_tooltipParent = null; public VerticalLayoutGroup m_tooltipContent = null; public RectTransform m_tooltipRect = null; public Text m_tooltip = null; public RectTransform m_rewardListRoot = null; public Image m_lineFill = null; public RectTransform m_starListRoot = null; public Button m_collectButton = null; public Text m_collectButtonLabel = null; public Text m_backButtonLabel = null; private int m_selectedReward = -1; [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(2)] private GameObject m_selectedRewardObject; private readonly Dictionary<int, float> m_fillLevels = new Dictionary<int, float> { [0] = 0f, [1] = 0.1f, [2] = 0.23f, [3] = 0.35f, [4] = 0.48f, [5] = 0.6f, [6] = 0.73f, [7] = 0.85f, [8] = 1f }; [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(new byte[] { 2, 1 })] [method: <0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(new byte[] { 2, 1 })] [field: <0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(new byte[] { 2, 1 })] private event Action<string> OnCollect; public static void Setup() { //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) m_root = AssetManager.GetAssetBundle("timekeeperbundle").LoadAsset<GameObject>("Timekeeper_UI"); m_item = AssetManager.GetAssetBundle("timekeeperbundle").LoadAsset<GameObject>("Timekeeper_Item"); m_star = AssetManager.GetAssetBundle("timekeeperbundle").LoadAsset<GameObject>("Timekeeper_Star"); m_scale = TimekeeperPlugin.instance.config("Settings", "Panel Scale", 1f, new ConfigDescription("Set scale of panel", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.3f, 3f), Array.Empty<object>())); m_panelBackground = TimekeeperPlugin.instance.config("Settings", "Background", PanelType.Opaque, "Set background panel"); m_panelBackground.SettingChanged += [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(0)] (object _, EventArgs _) => { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)instance == (Object)null)) { ((Graphic)instance.m_panel).color = ((m_panelBackground.Value == PanelType.Opaque) ? Color.white : Color.clear); ((Graphic)instance.m_darken).color = (Color)((m_panelBackground.Value == PanelType.Opaque) ? Color.clear : new Color(0f, 0f, 0f, 0.5f)); } }; RectTransform rect = m_root.GetComponent<RectTransform>(); ((Transform)rect).localScale = Vector3.one * m_scale.Value; m_scale.SettingChanged += [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(0)] (object _, EventArgs _) => { //IL_0007: 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) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) ((Transform)rect).localScale = Vector3.one * m_scale.Value; if ((Object)(object)instance != (Object)null) { ((Transform)((Component)instance).GetComponent<RectTransform>()).localScale = Vector3.one * m_scale.Value; } }; m_sendOnCollect = TimekeeperPlugin.instance.config("Discord", "On Collect", TimekeeperPlugin.Toggle.On, "If on, plugin will send message when player collects reward"); } private static void OnOpen() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)Settings.instance)) { Settings.instance.OnBack(); } Object.Instantiate<GameObject>(m_root, ((Component)Menu.instance).transform); Menu.instance.m_closeMenuState = (CloseMenuState)0; } public void Awake() { //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Expected O, but got Unknown //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Expected O, but got Unknown //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)instance != (Object)null) { Object.Destroy((Object)(object)instance); } instance = this; m_panel = ((Component)((Component)this).transform.Find("Panel")).GetComponent<Image>(); m_darken = ((Component)((Component)this).transform.Find("Panel/darken")).GetComponent<Image>(); m_title = ((Component)((Component)this).transform.Find("Panel/Title")).GetComponent<Text>(); m_description = ((Component)((Component)this).transform.Find("Panel/TabContent/Rewards/Text")).GetComponent<Text>(); m_timeLabel = ((Component)((Component)this).transform.Find("Panel/TabContent/Rewards/TimeLabel")).GetComponent<Text>(); m_time = ((Component)((Component)this).transform.Find("Panel/TabContent/Rewards/Time")).GetComponent<Text>(); m_tooltipParent = ((Component)((Component)this).transform.Find("Panel/TabContent/Rewards/Tooltip")).gameObject; m_tooltipContent = ((Component)((Component)this).transform.Find("Panel/TabContent/Rewards/Tooltip/Viewport/Content")).GetComponent<VerticalLayoutGroup>(); m_tooltip = ((Component)((Component)this).transform.Find("Panel/TabContent/Rewards/Tooltip/Viewport/Content/Text")).GetComponent<Text>(); m_tooltipRect = ((Component)m_tooltip).GetComponent<RectTransform>(); m_rewardListRoot = ((Component)((Component)this).transform.Find("Panel/TabContent/Rewards/RewardList/Viewport/Content")).GetComponent<RectTransform>(); m_lineFill = ((Component)((Component)this).transform.Find("Panel/TabContent/Rewards/Timeline/LineFill")).GetComponent<Image>(); m_starListRoot = ((Component)((Component)this).transform.Find("Panel/TabContent/Rewards/Timeline/StarGroup")).GetComponent<RectTransform>(); m_collectButton = ((Component)((Component)this).transform.Find("Panel/Collect")).GetComponent<Button>(); ((Selectable)m_collectButton).interactable = false; m_collectButtonLabel = ((Component)((Component)m_collectButton).transform.Find("Label")).GetComponent<Text>(); m_backButtonLabel = ((Component)((Component)this).transform.Find("Panel/Back/Label")).GetComponent<Text>(); Button component = ((Component)((Component)this).transform.Find("Panel/Back")).GetComponent<Button>(); ((UnityEvent)component.onClick).AddListener(new UnityAction(OnBack)); Button component2 = ((Component)((Component)this).transform.Find("Panel/Collect")).GetComponent<Button>(); ((UnityEvent)component2.onClick).AddListener(new UnityAction(Collect)); ((Graphic)m_panel).color = ((m_panelBackground.Value == PanelType.Opaque) ? Color.white : Color.clear); ((Graphic)m_darken).color = (Color)((m_panelBackground.Value == PanelType.Opaque) ? Color.clear : new Color(0f, 0f, 0f, 0.5f)); m_title.text = Localization.instance.Localize("Glitnir $label_timekeeper"); m_collectButtonLabel.text = Localization.instance.Localize("$label_collect"); m_backButtonLabel.text = Localization.instance.Localize("$label_back"); OnCollect += Webhook.SendNotice; } public void Start() { //IL_00ad: Unknown result type (might be due to invalid IL or missing references) LoadStars(); LoadRewardItems(); SetDescription(); m_timeLabel.text = Localization.instance.Localize("$msg_active_for: "); m_tooltipParent.SetActive(false); m_tooltip.text = ""; int day = TimeMan.GetDay(); string text = day + ((day > 1) ? " $msg_days" : " $msg_day") + " " + TimeMan.GetTimeDisplay(); m_time.text = Localization.instance.Localize(text); ((Graphic)m_time).color = new Color(1f, 0.5f, 0f, 1f); } public void OnDestroy() { instance = null; } public void Update() { if (ZInput.GetKey((KeyCode)304, true)) { ((Selectable)m_collectButton).interactable = true; m_collectButtonLabel.text = Localization.instance.Localize("$label_collect_all"); } else { ((Selectable)m_collectButton).interactable = false; m_collectButtonLabel.text = Localization.instance.Localize("$label_collect"); } if (ZInput.GetKeyDown((KeyCode)27, true)) { OnBack(); } } public void SetDescription() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("$msg_welcome_back " + Player.m_localPlayer.GetPlayerName() + "!\n"); stringBuilder.Append($"$msg_next_reward {TimeMan.GetNextRewardDay()}\n"); m_description.text = Localization.instance.Localize(stringBuilder.ToString()); } public void LoadStars() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown if (((Transform)m_starListRoot).childCount > 0) { foreach (Transform item in (Transform)m_starListRoot) { Transform val = item; Object.Destroy((Object)(object)((Component)val).gameObject); } } int day = TimeMan.GetDay(); List<KeyValuePair<int, TimeMan.Reward>> list = (from r in TimeMan.GetRewards() orderby r.Key select r).ToList(); int num = ((day > 0) ? GetCurrentChunkIndex(list, day) : 0); int num2 = num * 8; int num3 = Math.Min(num2 + 8, list.Count); int num4 = num3 - num2; KeyValuePair<int, TimeMan.Reward>[] array = new KeyValuePair<int, TimeMan.Reward>[num4]; for (int i = 0; i < num4; i++) { array[i] = list[num2 + i]; } if (num4 > 0) { float num5 = CalculateFillAmount(array, day, num4); if (Math.Abs(num5 - 1f) < 0.01f) { num++; num2 = num * 8; num3 = Math.Min(num2 + 8, list.Count); num4 = num3 - num2; if (num4 > 0) { if (array.Length != num4) { array = new KeyValuePair<int, TimeMan.Reward>[num4]; } for (int j = 0; j < num4; j++) { array[j] = list[num2 + j]; } num5 = CalculateFillAmount(array, day, num4); } } CreateStarsForRewards(array, num4, day); m_lineFill.fillAmount = num5; } else { m_lineFill.fillAmount = 0f; } CreatePlaceholderStars(8 - num4); } private void CreateStarsForRewards([<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(new byte[] { 1, 0, 1 })] KeyValuePair<int, TimeMan.Reward>[] rewards, int count, int playerDay) { for (int i = 0; i < count; i++) { KeyValuePair<int, TimeMan.Reward> keyValuePair = rewards[i]; GameObject val = Object.Instantiate<GameObject>(m_star, (Transform)(object)m_starListRoot); Text component = ((Component)val.transform.Find("Label")).GetComponent<Text>(); GameObject gameObject = ((Component)val.transform.Find("Star/Star_Lit")).gameObject; component.text = keyValuePair.Key.ToString(); if (playerDay >= keyValuePair.Key) { gameObject.SetActive(true); } } } private void CreatePlaceholderStars(int count) { for (int i = 0; i < count; i++) { GameObject val = Object.Instantiate<GameObject>(m_star, (Transform)(object)m_starListRoot); Text component = ((Component)val.transform.Find("Label")).GetComponent<Text>(); GameObject gameObject = ((Component)val.transform.Find("Star/Star_Lit")).gameObject; component.text = "?"; gameObject.SetActive(false); } } private static int GetCurrentChunkIndex([<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(new byte[] { 1, 0, 1 })] List<KeyValuePair<int, TimeMan.Reward>> rewards, int playerDay) { int count = rewards.Count; int num = (count + 8 - 1) / 8; for (int i = 0; i < num; i++) { int num2 = i * 8; int num3 = Math.Min(num2 + 8, count); if (num2 >= count) { break; } int key = rewards[num3 - 1].Key; if (playerDay <= key) { return i; } } return Math.Max(0, (count - 1) / 8); } private float CalculateFillAmount([<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(new byte[] { 1, 0, 1 })] KeyValuePair<int, TimeMan.Reward>[] chunkRewards, int playerDay, int count) { if (count == 0) { return 0f; } for (int i = 0; i < count; i++) { int key = chunkRewards[i].Key; if (playerDay > key) { continue; } if (playerDay == key) { return m_fillLevels[i + 1]; } if (i == 0) { if (playerDay >= key) { return m_fillLevels[1]; } float num = (float)(playerDay - 1) / (float)(key - 1); return Mathf.Lerp(m_fillLevels[0], m_fillLevels[1], num); } int key2 = chunkRewards[i - 1].Key; float num2 = (float)(playerDay - key2) / (float)(key - key2); return Mathf.Lerp(m_fillLevels[i], m_fillLevels[i + 1], num2); } return m_fillLevels[Math.Min(count, 8)]; } public void LoadRewardItems() { //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Expected O, but got Unknown ItemDrop val = default(ItemDrop); foreach (KeyValuePair<int, TimeMan.Reward> item2 in from kv in TimeMan.GetRewards() orderby kv.Key select kv) { int day = item2.Key; if (TimeMan.IsRewardCollected(day)) { continue; } TimeMan.Reward value = item2.Value; GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(value.ItemPrefab); if (itemPrefab != null && itemPrefab.TryGetComponent<ItemDrop>(ref val)) { bool canInteract = TimeMan.CanCollectReward(day) && !TimeMan.IsRewardCollected(day); GameObject item = Object.Instantiate<GameObject>(m_item, (Transform)(object)m_rewardListRoot); Button component = item.GetComponent<Button>(); Text component2 = ((Component)item.transform.Find("Label")).GetComponent<Text>(); Image component3 = ((Component)item.transform.Find("Background/Icon")).GetComponent<Image>(); ItemData data = val.m_itemData.Clone(); data.m_stack = value.Amount; data.m_quality = value.Quality; data.m_variant = value.Variant; component2.text = Localization.instance.Localize("$msg_day " + day); component3.sprite = val.m_itemData.GetIcon(); ((Graphic)component3).color = (canInteract ? Color.white : Color.black); ((UnityEvent)component.onClick).AddListener((UnityAction)delegate { SetTooltip(data); m_selectedReward = day; ((Selectable)m_collectButton).interactable = canInteract; m_selectedRewardObject = item; }); } } } public void OnBack() { Object.Destroy((Object)(object)((Component)this).gameObject); if (Object.op_Implicit((Object)(object)Settings.instance)) { Settings.instance.OnBack(); } } public void Collect() { if (ZInput.GetKey((KeyCode)304, true)) { int day = TimeMan.GetDay(); ItemDrop val = default(ItemDrop); foreach (KeyValuePair<int, TimeMan.Reward> item in from kvp in TimeMan.GetRewards() orderby kvp.Key select kvp) { if (item.Key > day) { break; } if (TimeMan.IsRewardCollected(item.Key)) { continue; } GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(item.Value.ItemPrefab); if (itemPrefab != null && itemPrefab.TryGetComponent<ItemDrop>(ref val)) { ItemData val2 = val.m_itemData.Clone(); val2.m_dropPrefab = itemPrefab; val2.m_stack = item.Value.Amount; val2.m_quality = item.Value.Quality; val2.m_variant = item.Value.Variant; if (!((Humanoid)Player.m_localPlayer).GetInventory().CanAddItem(val2, -1)) { ((Character)Player.m_localPlayer).Message((MessageType)1, "$inventory_full", 0, (Sprite)null); break; } if (!((Humanoid)Player.m_localPlayer).GetInventory().AddItem(val2)) { break; } if (m_sendOnCollect.Value == TimekeeperPlugin.Toggle.On) { this.OnCollect?.Invoke($"{Player.m_localPlayer.GetPlayerName()} $msg_has_collected {m_selectedReward}"); } TimeMan.SetRewardCollected(item.Key); m_tooltipParent.SetActive(false); m_selectedReward = -1; m_tooltip.text = ""; ((Selectable)m_collectButton).interactable = false; ((Character)Player.m_localPlayer).Message((MessageType)1, "$msg_added " + val2.m_shared.m_name, val2.m_stack, val2.GetIcon()); } } OnBack(); } else { if (TimeMan.IsRewardCollected(m_selectedReward) || !TimeMan.GetRewards().TryGetValue(m_selectedReward, out var value)) { return; } GameObject itemPrefab2 = ObjectDB.instance.GetItemPrefab(value.ItemPrefab); ItemDrop val3 = default(ItemDrop); if (itemPrefab2 == null || !itemPrefab2.TryGetComponent<ItemDrop>(ref val3)) { return; } ItemData val4 = val3.m_itemData.Clone(); val4.m_dropPrefab = itemPrefab2; val4.m_stack = value.Amount; val4.m_quality = value.Quality; val4.m_variant = value.Variant; if (!((Humanoid)Player.m_localPlayer).GetInventory().CanAddItem(val4, -1)) { ((Character)Player.m_localPlayer).Message((MessageType)1, "$inventory_full", 0, (Sprite)null); } else if (((Humanoid)Player.m_localPlayer).GetInventory().AddItem(val4)) { if (m_sendOnCollect.Value == TimekeeperPlugin.Toggle.On) { this.OnCollect?.Invoke($"{Player.m_localPlayer.GetPlayerName()} $msg_has_collected {m_selectedReward}"); } TimeMan.SetRewardCollected(m_selectedReward); m_tooltipParent.SetActive(false); m_selectedReward = -1; m_tooltip.text = ""; ((Selectable)m_collectButton).interactable = false; if ((Object)(object)m_selectedRewardObject != (Object)null) { Object.Destroy((Object)(object)m_selectedRewardObject); } ((Character)Player.m_localPlayer).Message((MessageType)1, "$msg_added " + val4.m_shared.m_name, val4.m_stack, val4.GetIcon()); } } } [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(2)] public void SetTooltip(ItemData item) { //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) if (item == null) { m_tooltip.text = ""; } else { m_tooltipParent.SetActive(true); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("<color=yellow>" + item.m_shared.m_name + "</color>" + ((item.m_stack > 1) ? $" x{item.m_stack}" : "") + "\n\n"); stringBuilder.Append(item.GetTooltip(-1) + "\n\n"); m_tooltip.text = Localization.instance.Localize(stringBuilder.ToString()); } Canvas.ForceUpdateCanvases(); float textPreferredHeight = GetTextPreferredHeight(m_tooltip, m_tooltipRect); textPreferredHeight += (float)(((LayoutGroup)m_tooltipContent).padding.top + ((LayoutGroup)m_tooltipContent).padding.bottom); float num = 260f; float num2 = Mathf.Max(textPreferredHeight, num); float x = m_tooltipRect.sizeDelta.x; Vector2 sizeDelta = m_tooltipRect.sizeDelta; ((Vector2)(ref sizeDelta)).Set(x, num2); } private static float GetTextPreferredHeight(Text text, RectTransform rect) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(text.text)) { return 0f; } TextGenerator cachedTextGenerator = text.cachedTextGenerator; Rect rect2 = rect.rect; TextGenerationSettings generationSettings = text.GetGenerationSettings(((Rect)(ref rect2)).size); return cachedTextGenerator.GetPreferredHeight(text.text, generationSettings); } } [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(0)] public static class TimeMan { [HarmonyPatch(typeof(Player), "SetControls")] [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(0)] private static class Player_SetControls_Patch { [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] private static void Postfix(Player __instance, Vector3 movedir, bool attack, bool attackHold, bool secondaryAttack, bool secondaryAttackHold, bool block, bool blockHold, bool jump, bool crouch, bool run, bool autoRun, bool dodge) { //IL_0032: 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) if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { if (attack || attackHold || secondaryAttack || secondaryAttackHold || block || blockHold || jump || crouch || run || dodge || movedir != Vector3.zero) { m_active = true; m_timeSinceLastInput = Time.fixedDeltaTime; } else if (Time.fixedDeltaTime > m_timeSinceLastInput + m_afkDuration.Value) { m_active = false; } if (m_active) { m_activeTimer = Math.Max(0.0, m_activeTimer); m_activeTimer += Math.Max(0f, Time.fixedDeltaTime); SendDayNotice(); } } } } [HarmonyPatch(typeof(Player), "Load")] [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(0)] private static class Player_Load_Patch { [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] private static void Postfix(Player __instance) { Load(__instance); } } [HarmonyPatch(typeof(Player), "Save")] [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(0)] private static class Player_Save_Patch { [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] private static void Prefix(Player __instance) { Save(__instance); } } [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(0)] [HarmonyPatch(typeof(ZNet), "Awake")] private static class ZNet_Awake_Patch { [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] private static void Postfix(ZNet __instance) { if (__instance.IsServer()) { UpdateServerRewards(); } } } [Serializable] [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(0)] public class Reward { public string ItemPrefab; public int Amount; public int Quality; public int Variant; public Reward(string item, int amount = 1, int quality = 1, int variant = 0) { ItemPrefab = item; Amount = amount; Quality = quality; Variant = variant; } } private const string RootFolderName = "Timekeeper"; private const string FileName = "Rewards.json"; private static readonly string RootFolderPath; private static readonly string FilePath; private static readonly CustomSyncedValue<string> ServerRewards; private static Dictionary<int, Reward> m_rewards; private static List<int> m_collectedRewards; private static bool m_active; private static float m_timeSinceLastInput; public static double m_activeTimer; private static int m_lastDay; private static ConfigEntry<float> m_afkDuration; private static ConfigEntry<TimekeeperPlugin.Toggle> m_sendDay; private static void SendDayNotice() { if (m_sendDay.Value != 0) { int day = GetDay(); if (day != m_lastDay) { m_lastDay = day; Webhook.instance.SendNotification($"{Player.m_localPlayer.GetPlayerName()} $msg_has_been_active {day} $msg_days"); } } } private static void UpdateServerRewards() { string value = JsonConvert.SerializeObject((object)m_rewards); ServerRewards.Value = value; } public static Dictionary<int, Reward> GetRewards() { return m_rewards; } public static int GetDay() { if (m_activeTimer < 0.0) { TimekeeperPlugin.TimekeeperLogger.LogWarning((object)$"Active timer is negative: {m_activeTimer}, resetting to 0"); m_activeTimer = 0.0; } return (int)(m_activeTimer / 1800.0); } private static float GetTimeOfDay() { return (float)(m_activeTimer % 1800.0); } public static string GetTimeDisplay() { float timeOfDay = GetTimeOfDay(); float num = 1800f; float num2 = num / 24f; float num3 = num2 / 60f; int num4 = Mathf.FloorToInt(timeOfDay / num2); int num5 = Mathf.FloorToInt(timeOfDay % num2 / num3); return $"{num4}:{num5:D2}"; } public static void Clear(Player player) { player.m_customData.Remove("TimekeeperCollected"); player.m_customData.Remove("TimekeeperTime"); m_activeTimer = 0.0; m_collectedRewards.Clear(); } private static void Save(Player player) { player.m_customData["TimekeeperCollected"] = JsonConvert.SerializeObject((object)m_collectedRewards); player.m_customData["TimekeeperTime"] = m_activeTimer.ToString(CultureInfo.CurrentCulture); } private static void Load(Player player) { m_activeTimer = 0.0; if (player.m_customData.TryGetValue("TimekeeperCollected", out var value)) { try { List<int> list = JsonConvert.DeserializeObject<List<int>>(value); if (list != null) { m_collectedRewards = list; } } catch { TimekeeperPlugin.TimekeeperLogger.LogWarning((object)"Failed to parse collected timekeeper keys"); player.m_customData.Remove("TimekeeperCollected"); } } if (player.m_customData.TryGetValue("TimekeeperTime", out var value2) && double.TryParse(value2, out var result)) { m_activeTimer = Math.Max(0.0, result); m_lastDay = GetDay(); } } public static bool IsRewardCollected(int key) { return m_collectedRewards.Contains(key); } public static void SetRewardCollected(int key) { m_collectedRewards.Add(key); } public static int GetNextRewardDay() { foreach (KeyValuePair<int, Reward> item in m_rewards.OrderBy([<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(0)] (KeyValuePair<int, Reward> kvp) => kvp.Key)) { if (item.Key <= GetDay()) { continue; } return item.Key; } return -1; } public static bool CanCollectReward(int key) { return key <= GetDay(); } public static void Setup() { m_afkDuration = TimekeeperPlugin.instance.config("Settings", "AFK Duration", 10f, "Set seconds until no input triggers AFK status"); m_sendDay = TimekeeperPlugin.instance.config("Discord", "On New Day", TimekeeperPlugin.Toggle.Off, "If on, will send message when player reaches a new day"); ServerRewards.ValueChanged += delegate { if ((!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer()) && !Utility.IsNullOrWhiteSpace(ServerRewards.Value)) { Dictionary<int, Reward> dictionary3 = JsonConvert.DeserializeObject<Dictionary<int, Reward>>(ServerRewards.Value); if (dictionary3 != null) { m_rewards = dictionary3; } } }; LoadDefaults(); if (!Directory.Exists(RootFolderPath)) { Directory.CreateDirectory(RootFolderPath); } if (!File.Exists(FilePath)) { UpdateRewardFile(); } else { try { Dictionary<int, Reward> dictionary = JsonConvert.DeserializeObject<Dictionary<int, Reward>>(File.ReadAllText(FilePath)); if (dictionary != null) { m_rewards = dictionary; } } catch { TimekeeperPlugin.TimekeeperLogger.LogWarning((object)"Failed to parse file: Rewards.json"); } } FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(RootFolderPath, "Rewards.json"); fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher.EnableRaisingEvents = true; fileSystemWatcher.Changed += OnFileChange; fileSystemWatcher.Created += OnFileChange; static void OnFileChange(object sender, FileSystemEventArgs args) { if (Object.op_Implicit((Object)(object)ZNet.instance) && !ZNet.instance.IsServer()) { return; } TimekeeperPlugin.TimekeeperLogger.LogDebug((object)"Timekeeper config changed, reloading rewards"); try { Dictionary<int, Reward> dictionary2 = JsonConvert.DeserializeObject<Dictionary<int, Reward>>(File.ReadAllText(FilePath)); if (dictionary2 != null) { m_rewards = dictionary2; } UpdateServerRewards(); } catch { TimekeeperPlugin.TimekeeperLogger.LogWarning((object)"Failed to parse file: Rewards.json"); } } } private static void LoadDefaults() { m_rewards[1] = new Reward("Coins"); m_rewards[2] = new Reward("Coins"); m_rewards[4] = new Reward("Coins"); m_rewards[6] = new Reward("Coins"); m_rewards[8] = new Reward("Coins"); m_rewards[10] = new Reward("Coins"); m_rewards[12] = new Reward("Coins"); m_rewards[14] = new Reward("Coins"); m_rewards[16] = new Reward("Coins"); m_rewards[18] = new Reward("Coins"); m_rewards[21] = new Reward("Coins"); m_rewards[24] = new Reward("Coins"); m_rewards[27] = new Reward("Coins"); m_rewards[30] = new Reward("Coins"); m_rewards[33] = new Reward("Coins"); m_rewards[36] = new Reward("Coins"); m_rewards[39] = new Reward("Coins"); m_rewards[42] = new Reward("Coins"); m_rewards[45] = new Reward("Coins"); m_rewards[48] = new Reward("Coins"); m_rewards[51] = new Reward("Coins"); m_rewards[54] = new Reward("Coins"); m_rewards[57] = new Reward("Coins"); m_rewards[60] = new Reward("Coins"); m_rewards[63] = new Reward("Coins"); m_rewards[66] = new Reward("Coins"); m_rewards[69] = new Reward("Coins"); m_rewards[72] = new Reward("Coins"); m_rewards[75] = new Reward("Coins"); m_rewards[78] = new Reward("Coins"); m_rewards[81] = new Reward("Coins"); m_rewards[84] = new Reward("Coins"); m_rewards[87] = new Reward("Coins"); m_rewards[90] = new Reward("Coins"); m_rewards[94] = new Reward("Coins"); m_rewards[98] = new Reward("Coins"); m_rewards[102] = new Reward("Coins"); m_rewards[106] = new Reward("Coins"); m_rewards[110] = new Reward("Coins"); m_rewards[114] = new Reward("Coins"); m_rewards[118] = new Reward("Coins"); m_rewards[122] = new Reward("Coins"); m_rewards[126] = new Reward("Coins"); m_rewards[130] = new Reward("Coins"); m_rewards[134] = new Reward("Coins"); m_rewards[138] = new Reward("Coins"); m_rewards[142] = new Reward("Coins"); m_rewards[146] = new Reward("Coins"); m_rewards[150] = new Reward("Coins"); m_rewards[154] = new Reward("Coins"); m_rewards[158] = new Reward("Coins"); m_rewards[162] = new Reward("Coins"); m_rewards[166] = new Reward("Coins"); m_rewards[170] = new Reward("Coins"); m_rewards[174] = new Reward("Coins"); m_rewards[178] = new Reward("Coins"); m_rewards[182] = new Reward("Coins"); m_rewards[187] = new Reward("Coins"); m_rewards[192] = new Reward("Coins"); m_rewards[197] = new Reward("Coins"); m_rewards[202] = new Reward("Coins"); m_rewards[207] = new Reward("Coins"); m_rewards[212] = new Reward("Coins"); m_rewards[217] = new Reward("Coins"); m_rewards[222] = new Reward("Coins"); m_rewards[227] = new Reward("Coins"); m_rewards[232] = new Reward("Coins"); m_rewards[237] = new Reward("Coins"); m_rewards[242] = new Reward("Coins"); m_rewards[247] = new Reward("Coins"); m_rewards[252] = new Reward("Coins"); m_rewards[257] = new Reward("Coins"); m_rewards[262] = new Reward("Coins"); m_rewards[267] = new Reward("Coins"); m_rewards[272] = new Reward("Coins"); m_rewards[277] = new Reward("Coins"); m_rewards[282] = new Reward("Coins"); m_rewards[287] = new Reward("Coins"); m_rewards[292] = new Reward("Coins"); m_rewards[297] = new Reward("Coins"); m_rewards[302] = new Reward("Coins"); m_rewards[307] = new Reward("Coins"); m_rewards[312] = new Reward("Coins"); m_rewards[317] = new Reward("Coins"); m_rewards[322] = new Reward("Coins"); m_rewards[326] = new Reward("Coins"); m_rewards[330] = new Reward("Coins"); m_rewards[334] = new Reward("Coins"); m_rewards[338] = new Reward("Coins"); m_rewards[341] = new Reward("Coins"); m_rewards[344] = new Reward("Coins"); m_rewards[347] = new Reward("Coins"); m_rewards[350] = new Reward("Coins"); m_rewards[353] = new Reward("Coins"); m_rewards[356] = new Reward("Coins"); m_rewards[358] = new Reward("Coins"); m_rewards[360] = new Reward("Coins"); m_rewards[362] = new Reward("Coins"); m_rewards[364] = new Reward("Coins"); m_rewards[365] = new Reward("Coins"); } public static void AddReward(int day, Reward reward) { m_rewards[day] = reward; } public static void UpdateRewardFile() { string contents = JsonConvert.SerializeObject((object)m_rewards, (Formatting)1); File.WriteAllText(FilePath, contents); } static TimeMan() { string configPath = Paths.ConfigPath; char directorySeparatorChar = Path.DirectorySeparatorChar; RootFolderPath = configPath + directorySeparatorChar + "Timekeeper"; string rootFolderPath = RootFolderPath; directorySeparatorChar = Path.DirectorySeparatorChar; FilePath = rootFolderPath + directorySeparatorChar + "Rewards.json"; ServerRewards = new CustomSyncedValue<string>(TimekeeperPlugin.ConfigSync, "ServerTimekeeperRewards", ""); m_rewards = new Dictionary<int, Reward>(); m_collectedRewards = new List<int>(); m_activeTimer = 0.0; m_lastDay = -1; m_afkDuration = null; m_sendDay = null; } } [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(0)] [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] public class Webhook : MonoBehaviour { [Serializable] [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(2)] [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(0)] public class DiscordWebhookData { public string content; public bool tts; [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(new byte[] { 2, 1 })] public Embed[] embeds; public string username; public string avatar_url; [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] public DiscordWebhookData(string content) { this.content = Localization.instance.Localize(content); } [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] public DiscordWebhookData(params Embed[] embeds) { this.embeds = embeds; } } [Serializable] [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(2)] [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(0)] public class Embed { public string title; public string description; public string url; public string timestamp; public int? color; public Footer footer; public EmbedImage image; public EmbedImage thumbnail; public EmbedVideo video; public EmbedProvider provider; public EmbedAuthor author; [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(new byte[] { 2, 1 })] public EmbedField[] fields; public Embed() { timestamp = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"); } [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] public Embed(string title, string description) { this.title = Localization.instance.Localize(title); this.description = Localization.instance.Localize(description); timestamp = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"); } [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] public Embed(string title, params EmbedField[] fields) { this.title = title; this.fields = fields; timestamp = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"); } [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] public Embed(string description) { this.description = Localization.instance.Localize(description); timestamp = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"); } [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] public Embed(string title, List<EmbedField> fields) : this(title, fields.ToArray()) { } [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] public void AddImage(string imageUrl) { if (!string.IsNullOrEmpty(imageUrl)) { image = new EmbedImage(imageUrl); } } [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] public void AddThumbnail(string thumbnailUrl) { if (!string.IsNullOrEmpty(thumbnailUrl)) { thumbnail = new EmbedImage(thumbnailUrl); } } public void SetColor(Color Color) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) color = ColorToInt(Color); } } [Serializable] [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(0)] [Description("Discord image json object")] public class EmbedImage { [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(2)] public string url; public int width; public int height; [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] public EmbedImage(string url, int width = 256, int height = 256) { this.url = url; this.width = width; this.height = height; } } [Serializable] [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(0)] public class EmbedVideo { [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(2)] public string url; public int height; public int width; } [Serializable] [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(2)] [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(0)] public class EmbedProvider { public string name; public string url; } [Serializable] [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(2)] [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(0)] [Description("Discord author json object")] public class EmbedAuthor { public string name; public string icon_url; } [Serializable] [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(2)] [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(0)] [Description("Discord embed json object")] public class EmbedField { public string name; public string value; public bool inline; [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] public EmbedField(string name, string value, bool inline = true) { this.name = Localization.instance.Localize(name); this.value = Localization.instance.Localize(value); this.inline = inline; } } [Serializable] [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(0)] [Description("Discord footer json object")] public class Footer { [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(2)] public string text; [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(2)] public string icon_url; public Footer(string text) { this.text = Localization.instance.Localize(text); } public void AddIcon(string url) { if (!string.IsNullOrEmpty(url)) { icon_url = url; } } } [Serializable] [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(2)] [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(0)] [Description("Discord message json object")] public class Message { public string id; public string channel_id; public User author; public string content; public string timestamp; public string edited_timestamp; public bool tts; public bool mention_everyone; [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(new byte[] { 2, 1 })] public User[] mentions; [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(new byte[] { 2, 1 })] public User[] mention_roles; public int type; [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(new byte[] { 2, 1 })] public Embed[] embeds; } [Serializable] [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(2)] [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(0)] [Description("Discord user json object")] public class User { public string id; public string username; public string global_name; public string discriminator; public bool bot; public string avatar; [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] public string GetDisplayName() { return ((!string.IsNullOrEmpty(global_name)) ? global_name : username) ?? string.Empty; } [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] public string GetFullUsername() { return (!string.IsNullOrEmpty(discriminator) && discriminator != "0") ? (username + "#" + discriminator) : (username ?? string.Empty); } } private static ConfigEntry<string> m_webhookURL; public static Webhook instance; [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(new byte[] { 2, 1 })] [method: <0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(new byte[] { 2, 1 })] [field: <0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(new byte[] { 2, 1 })] public event Action<string> OnError; public static void Setup() { m_webhookURL = TimekeeperPlugin.instance.config("Discord", "Webhook URL", "", "Set webhook to receive notifications about timekeeper"); ((Component)TimekeeperPlugin.instance).gameObject.AddComponent<Webhook>(); } public void Awake() { instance = this; OnError += HandleError; } private static void HandleError(string message) { TimekeeperPlugin.TimekeeperLogger.LogWarning((object)message); } public static void SendNotice(string message) { instance.SendNotification(message); } public void SendNotification(string message) { DiscordWebhookData data = new DiscordWebhookData(message); ((MonoBehaviour)this).StartCoroutine(SendWebhookMessage(data, m_webhookURL.Value)); } public static void SendEmbedNotice(string title, string content, string thumbnail = "") { instance.SendEmbedMessage(title, content, thumbnail); } public void SendEmbedMessage(string title, string content, string thumbnail = "") { Embed embed = new Embed(title, content); embed.AddThumbnail(thumbnail); DiscordWebhookData data = new DiscordWebhookData(embed); ((MonoBehaviour)this).StartCoroutine(SendWebhookMessage(data, m_webhookURL.Value)); } private IEnumerator SendWebhookMessage(DiscordWebhookData data, string webhookURL) { if (string.IsNullOrEmpty(webhookURL)) { this.OnError?.Invoke("Webhook URL is not set!"); yield break; } string jsonData = JsonConvert.SerializeObject((object)data); byte[] bodyRaw = Encoding.UTF8.GetBytes(jsonData); UnityWebRequest request = new UnityWebRequest(webhookURL, "POST"); try { request.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw); request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); request.SetRequestHeader("Content-Type", "application/json"); yield return request.SendWebRequest(); if ((int)request.result != 1) { string error = "Failed to send message: " + request.error + " - " + request.downloadHandler.text; this.OnError?.Invoke(error); } } finally { ((IDisposable)request)?.Dispose(); } } public static int ColorToInt(Color color) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.RoundToInt(color.r * 255f); int num2 = Mathf.RoundToInt(color.g * 255f); int num3 = Mathf.RoundToInt(color.b * 255f); return (num << 16) + (num2 << 8) + num3; } } [HarmonyPatch(typeof(ZNet), "OnNewConnection")] public static class RegisterAndCheckVersion { [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] private static void Prefix(ZNetPeer peer, ref ZNet __instance) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown TimekeeperPlugin.TimekeeperLogger.LogDebug((object)"Registering version RPC handler"); peer.m_rpc.Register<ZPackage>("Timekeeper_VersionCheck", (Action<ZRpc, ZPackage>)RpcHandlers.RPC_Timekeeper_Version); TimekeeperPlugin.TimekeeperLogger.LogInfo((object)"Invoking version check"); ZPackage val = new ZPackage(); val.Write("1.0.2"); peer.m_rpc.Invoke("Timekeeper_VersionCheck", new object[1] { val }); } } [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(0)] public static class VerifyClient { private static bool Prefix(ZRpc rpc, ZPackage pkg, ref ZNet __instance) { if (!__instance.IsServer() || RpcHandlers.ValidatedPeers.Contains(rpc)) { return true; } TimekeeperPlugin.TimekeeperLogger.LogWarning((object)("Peer (" + rpc.m_socket.GetHostName() + ") never sent version or couldn't due to previous disconnect, disconnecting")); rpc.Invoke("Error", new object[1] { 3 }); return false; } private static void Postfix(ZNet __instance) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), "TimekeeperRequestAdminSync", new object[1] { (object)new ZPackage() }); } } [HarmonyPatch(typeof(FejdStartup), "ShowConnectError")] public class ShowConnectionError { [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] private static void Postfix(FejdStartup __instance) { if (__instance.m_connectionFailedPanel.activeSelf) { __instance.m_connectionFailedError.fontSizeMax = 25f; __instance.m_connectionFailedError.fontSizeMin = 15f; TMP_Text connectionFailedError = __instance.m_connectionFailedError; connectionFailedError.text = connectionFailedError.text + "\n" + TimekeeperPlugin.ConnectionError; } } } [HarmonyPatch(typeof(ZNet), "Disconnect")] public static class RemoveDisconnectedPeerFromVerified { [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] private static void Prefix(ZNetPeer peer, ref ZNet __instance) { if (__instance.IsServer()) { TimekeeperPlugin.TimekeeperLogger.LogInfo((object)("Peer (" + peer.m_rpc.m_socket.GetHostName() + ") disconnected, removing from validated list")); RpcHandlers.ValidatedPeers.Remove(peer.m_rpc); } } } [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(0)] [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] public static class RpcHandlers { public static readonly List<ZRpc> ValidatedPeers = new List<ZRpc>(); public static void RPC_Timekeeper_Version(ZRpc rpc, ZPackage pkg) { string text = pkg.ReadString(); TimekeeperPlugin.TimekeeperLogger.LogInfo((object)("Version check, local: 1.0.2, remote: " + text)); if (text != "1.0.2") { TimekeeperPlugin.ConnectionError = "Timekeeper Installed: 1.0.2\n Needed: " + text; if (ZNet.instance.IsServer()) { TimekeeperPlugin.TimekeeperLogger.LogWarning((object)("Peer (" + rpc.m_socket.GetHostName() + ") has incompatible version, disconnecting...")); rpc.Invoke("Error", new object[1] { 3 }); } } else if (!ZNet.instance.IsServer()) { TimekeeperPlugin.TimekeeperLogger.LogInfo((object)"Received same version from server!"); } else { TimekeeperPlugin.TimekeeperLogger.LogInfo((object)("Adding peer (" + rpc.m_socket.GetHostName() + ") to validated list")); ValidatedPeers.Add(rpc); } } public static string ComputeHashForMod() { using SHA256 sHA = SHA256.Create(); byte[] array = sHA.ComputeHash(File.ReadAllBytes(Assembly.GetExecutingAssembly().Location)); StringBuilder stringBuilder = new StringBuilder(); byte[] array2 = array; foreach (byte b in array2) { stringBuilder.Append(b.ToString("X2")); } return stringBuilder.ToString(); } } } namespace Timekeeper.Managers { public static class CommandManager { [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(0)] [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] public class CommandData { [HarmonyPatch(typeof(Terminal), "updateSearch")] [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(0)] private static class Terminal_UpdateSearch_Patch { [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] private static bool Prefix(Terminal __instance, string word) { if ((Object)(object)__instance.m_search == (Object)null) { return true; } string[] array = ((TMP_InputField)__instance.m_input).text.Split(new char[1] { ' ' }); if (array.Length < 3) { return true; } if (array[0] != m_startCommand) { return true; } return HandleSearch(__instance, word, array); } } [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(0)] [HarmonyPatch(typeof(Terminal), "tabCycle")] private static class Terminal_TabCycle_Patch { [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] private static bool Prefix(Terminal __instance, string word, [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(new byte[] { 2, 1 })] List<string> options, bool usePrefix) { if (options == null || options.Count == 0) { return true; } usePrefix = usePrefix && __instance.m_tabPrefix > '\0'; if (usePrefix) { if (word.Length < 1 || word[0] != __instance.m_tabPrefix) { return true; } word = word.Substring(1); } return HandleTabCycle(__instance, word, options, usePrefix); } } public static readonly string m_startCommand = "timekeeper"; public static readonly Dictionary<string, CommandData> m_commands = new Dictionary<string, CommandData>(); public readonly string m_description; private readonly bool m_isSecret; private readonly bool m_adminOnly; private readonly Func<ConsoleEventArgs, bool> m_command; [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(new byte[] { 2, 1, 1 })] private readonly Func<List<string>> m_optionFetcher; public bool Run(ConsoleEventArgs args) { return !IsAdmin() || m_command(args); } private bool IsAdmin() { if (!Object.op_Implicit((Object)(object)ZNet.m_instance)) { return true; } if (!m_adminOnly || ZNet.m_instance.LocalPlayerIsAdminOrHost()) { return true; } Debug.LogWarning((object)"Admin only command"); return false; } public bool IsSecret() { return m_isSecret; } public List<string> FetchOptions() { return (m_optionFetcher == null) ? new List<string>() : m_optionFetcher(); } public bool HasOptions() { return m_optionFetcher != null; } public CommandData(string input, string description, Func<ConsoleEventArgs, bool> command, [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(new byte[] { 2, 1, 1 })] Func<List<string>> optionsFetcher = null, bool isSecret = false, bool adminOnly = false) { m_description = description; m_command = command; m_isSecret = isSecret; m_commands[input] = this; m_optionFetcher = optionsFetcher; m_adminOnly = adminOnly; } private static bool HandleSearch(Terminal __instance, string word, string[] strArray) { if (!m_commands.TryGetValue(strArray[1], out var value)) { return true; } if (value.HasOptions() && strArray.Length == 3) { List<string> list = value.FetchOptions(); string currentSearch = strArray[2]; List<string> list2; if (!Utility.IsNullOrWhiteSpace(currentSearch)) { int num = list.IndexOf(currentSearch); list2 = ((num != -1) ? list.GetRange(num, list.Count - num) : list); list2 = list2.FindAll((string x) => x.ToLower().Contains(currentSearch.ToLower())); } else { list2 = list; } if (list2.Count <= 0) { __instance.m_search.text = value.m_description; } else { __instance.m_lastSearch.Clear(); __instance.m_lastSearch.AddRange(list2); __instance.m_lastSearch.Remove(word); __instance.m_search.text = ""; int num2 = 10; int num3 = Math.Min(__instance.m_lastSearch.Count, num2); for (int i = 0; i < num3; i++) { string text = __instance.m_lastSearch[i]; TMP_Text search = __instance.m_search; search.text = search.text + text + " "; } if (__instance.m_lastSearch.Count <= num2) { return false; } int num4 = __instance.m_lastSearch.Count - num2; TMP_Text search2 = __instance.m_search; search2.text += $"... {num4} more."; } } else { __instance.m_search.text = value.m_description; } return false; } private static bool HandleTabCycle(Terminal __instance, string word, List<string> options, bool usePrefix) { string text = ((TMP_InputField)__instance.m_input).text; string[] array = text.Split(new char[1] { ' ' }); if (array.Length < 2 || !string.Equals(array[0], m_startCommand, StringComparison.CurrentCultureIgnoreCase) || !m_commands.ContainsKey(array[1].ToLower())) { return true; } if (__instance.m_tabCaretPosition == -1) { __instance.m_tabOptions.Clear(); __instance.m_tabCaretPosition = ((TMP_InputField)__instance.m_input).caretPosition; word = word.ToLower(); __instance.m_tabLength = word.Length; if (__instance.m_tabLength == 0) { __instance.m_tabOptions.AddRange(options); } else { foreach (string option in options) { if (option != null && option.Length > __instance.m_tabLength && option.Substring(0, __instance.m_tabLength).ToLower() == word) { __instance.m_tabOptions.Add(option); } } } __instance.m_tabOptions.Sort(); __instance.m_tabIndex = -1; } if (__instance.m_tabOptions.Count == 0) { __instance.m_tabOptions.AddRange(__instance.m_lastSearch); } if (__instance.m_tabOptions.Count == 0) { return false; } if (++__instance.m_tabIndex >= __instance.m_tabOptions.Count) { __instance.m_tabIndex = 0; } if (__instance.m_tabCaretPosition - __instance.m_tabLength >= 0) { int num = 0; int num2 = 0; for (int i = 0; i < text.Length; i++) { if (text[i] == ' ') { num++; if (num == 2) { num2 = i + 1; break; } } } if (array.Length >= 3 && num2 > 0) { string text2 = text.Substring(0, num2); ((TMP_InputField)__instance.m_input).text = text2 + __instance.m_tabOptions[__instance.m_tabIndex]; } else if (array.Length == 2) { ((TMP_InputField)__instance.m_input).text = text + " " + __instance.m_tabOptions[__instance.m_tabIndex]; } } int tabCaretPositionEnd = (((TMP_InputField)__instance.m_input).caretPosition = ((TMP_InputField)__instance.m_input).text.Length); __instance.m_tabCaretPositionEnd = tabCaretPositionEnd; return false; } } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEventFailable <>9__0_0; public static Func<KeyValuePair<string, CommandData>, bool> <>9__0_1; public static Func<KeyValuePair<string, CommandData>, string> <>9__0_2; [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(new byte[] { 0, 1 })] public static Func<ConsoleEventArgs, bool> <>9__0_3; [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(new byte[] { 0, 1 })] public static Func<ConsoleEventArgs, bool> <>9__0_4; [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(new byte[] { 0, 1 })] public static Func<ConsoleEventArgs, bool> <>9__0_5; [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(new byte[] { 0, 1 })] public static Func<ConsoleEventArgs, bool> <>9__0_6; internal object <Setup>b__0_0(ConsoleEventArgs args) { if (args.Length < 2) { return false; } if (!CommandData.m_commands.TryGetValue(args[1], out var value)) { return false; } return value.Run(args); } internal bool <Setup>b__0_1(KeyValuePair<string, CommandData> x) { return !x.Value.IsSecret(); } internal string <Setup>b__0_2(KeyValuePair<string, CommandData> x) { return x.Key; } [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] internal bool <Setup>b__0_3(ConsoleEventArgs args) { if (args.Length < 3) { return false; } if (!float.TryParse(args[2], out var result)) { return false; } TimeMan.m_activeTimer += result; TimekeeperPlugin.TimekeeperLogger.LogInfo((object)("Added " + result + " seconds to local player")); return true; } [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] internal bool <Setup>b__0_4(ConsoleEventArgs _) { if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return false; } TimeMan.Clear(Player.m_localPlayer); TimekeeperPlugin.TimekeeperLogger.LogInfo((object)"Cleared local player timekeeper data"); return true; } [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] internal bool <Setup>b__0_5(ConsoleEventArgs _) { if (!Object.op_Implicit((Object)(object)EnvMan.instance)) { return false; } TimeMan.m_activeTimer += EnvMan.instance.m_dayLengthSec; TimekeeperPlugin.TimekeeperLogger.LogInfo((object)("Added " + EnvMan.instance.m_dayLengthSec + " seconds to local player")); return true; } [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] internal bool <Setup>b__0_6(ConsoleEventArgs args) { if (args.Length < 5) { return false; } if (!int.TryParse(args[2], out var result)) { return false; } GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(args[3].Trim()); if (itemPrefab == null) { return false; } if (!int.TryParse(args[4], out var result2)) { return false; } int num = 1; int num2 = 0; if (args.Length > 5) { num = (int.TryParse(args[5], out var result3) ? result3 : num); } if (args.Length > 6) { num2 = (int.TryParse(args[6], out var result4) ? result4 : num2); } TimeMan.Reward reward = new TimeMan.Reward(((Object)itemPrefab).name, result2, num, num2); TimeMan.AddReward(result, reward); TimeMan.UpdateRewardFile(); TimekeeperPlugin.TimekeeperLogger.LogInfo((object)"Updated rewards"); return true; } } public static void Setup() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Expected O, but got Unknown //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown string startCommand = CommandData.m_startCommand; object obj = <>c.<>9__0_0; if (obj == null) { ConsoleEventFailable val = delegate(ConsoleEventArgs args) { if (args.Length < 2) { return false; } CommandData value; return (!CommandData.m_commands.TryGetValue(args[1], out value)) ? ((object)false) : ((object)value.Run(args)); }; <>c.<>9__0_0 = val; obj = (object)val; } ConsoleCommand val2 = new ConsoleCommand(startCommand, "Use help to find commands", (ConsoleEventFailable)obj, false, false, false, false, false, new ConsoleOptionsFetcher(Enumerable.ToList), false, false, false); new CommandData("add", "adds seconds to player counter", [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] (ConsoleEventArgs args) => { if (args.Length < 3) { return false; } if (!float.TryParse(args[2], out var result5)) { return false; } TimeMan.m_activeTimer += result5; TimekeeperPlugin.TimekeeperLogger.LogInfo((object)("Added " + result5 + " seconds to local player")); return true; }, null, isSecret: false, adminOnly: true); new CommandData("reset", "clears data from player save", [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] (ConsoleEventArgs _) => { if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return false; } TimeMan.Clear(Player.m_localPlayer); TimekeeperPlugin.TimekeeperLogger.LogInfo((object)"Cleared local player timekeeper data"); return true; }); new CommandData("add_day", "adds a full day (1800) to the player counter", [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] (ConsoleEventArgs _) => { if (!Object.op_Implicit((Object)(object)EnvMan.instance)) { return false; } TimeMan.m_activeTimer += EnvMan.instance.m_dayLengthSec; TimekeeperPlugin.TimekeeperLogger.LogInfo((object)("Added " + EnvMan.instance.m_dayLengthSec + " seconds to local player")); return true; }, null, isSecret: false, adminOnly: true); new CommandData("add_reward", "[day] [itemName] [Amount] [Quality] [Variant], add a new reward", [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] (ConsoleEventArgs args) => { if (args.Length < 5) { return false; } if (!int.TryParse(args[2], out var result)) { return false; } GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(args[3].Trim()); if (itemPrefab == null) { return false; } if (!int.TryParse(args[4], out var result2)) { return false; } int num = 1; int num2 = 0; if (args.Length > 5) { num = (int.TryParse(args[5], out var result3) ? result3 : num); } if (args.Length > 6) { num2 = (int.TryParse(args[6], out var result4) ? result4 : num2); } TimeMan.Reward reward = new TimeMan.Reward(((Object)itemPrefab).name, result2, num, num2); TimeMan.AddReward(result, reward); TimeMan.UpdateRewardFile(); TimekeeperPlugin.TimekeeperLogger.LogInfo((object)"Updated rewards"); return true; }, null, isSecret: false, adminOnly: true); } } } namespace Managers { [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(0)] [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] public static class AssetManager { private static readonly Dictionary<string, AssetBundle> m_assetBundles = new Dictionary<string, AssetBundle>(); public static AssetBundle GetAssetBundle(string fileName) { if (m_assetBundles.TryGetValue(fileName, out var value)) { return value; } Assembly executingAssembly = Assembly.GetExecutingAssembly(); string name = executingAssembly.GetManifestResourceNames().Single([<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(0)] (string str) => str.EndsWith(fileName)); using Stream stream = executingAssembly.GetManifestResourceStream(name); value = AssetBundle.LoadFromStream(stream); m_assetBundles[fileName] = value; return value; } } [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(0)] [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(1)] public static class FontManager { [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(0)] public enum FontOptions { Norse, NorseBold, AveriaSerifLibre, AveriaSerifLibreBold, AveriaSerifLibreLight, LegacyRuntime } [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(0)] private class TextFont { private readonly Text m_text; public TextFont(Text text, [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(2)] Font font) { m_text = text; Update(font); m_allTexts.Add(this); } [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(2)] public void Update(Font font) { m_text.font = font; } } [<0e657ea4-f9a5-4535-99f9-133b42a018b4>Nullable(new byte[] { 1, 2 })] private static readonly Dictionary<FontOptions, Font> m_fonts = new Dictionary<FontOptions, Font>(); private static readonly List<TextFont> m_allTexts = new List<TextFont>(); private static string GetFontName(FontOptions option) { if (1 == 0) { } string result = option switch { FontOptions.Norse => "Norse", FontOptions.AveriaSerifLibre => "AveriaSerifLibre-Regular", FontOptions.AveriaSerifLibreBold => "AveriaSerifLibre-Bold", FontOptions.AveriaSerifLibreLight => "AveriaSerifLibre-Light", FontOptions.NorseBold => "Norsebold", FontOptions.LegacyRuntime => "LegacyRuntime", _ => "AveriaSerifLibre-Regular", }; if (1 == 0) { } return result; } [<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(2)] public static Font GetFont(FontOptions option) { if (m_fonts.TryGetValue(option, out var value)) { return value; } Font[] source = Resources.FindObjectsOfTypeAll<Font>(); Font val = ((IEnumerable<Font>)source).FirstOrDefault((Func<Font, bool>)([<b11550e8-a346-4c7f-ace6-76ca3e1977f2>NullableContext(0)] (Font x) => ((Object)x).name == GetFontName(option))); m_fonts[option] = val; return val; } public static void OnFontChange(object sender, EventArgs args) { Font font = GetFont(FontOptions.AveriaSerifLibre); foreach (TextFont allText in m_allTexts) { allText.Update(font); } } public static void SetFont(Text[] array) { foreach (Text text in array) { TextFont textFont = new TextFont(text, GetFont(FontOptions.AveriaSerifLibre)); } } } } namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] [Microsoft.CodeAnalysis.Embedded] [CompilerGenerated] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] [Microsoft.CodeAnalysis.Embedded] [CompilerGenerated] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ServerSync { [PublicAPI] internal abstract class OwnConfigEntryBase { public object? LocalBaseValue; public bool SynchronizedConfig = true; public abstract ConfigEntryBase BaseConfig { get; } } [PublicAPI] internal class SyncedConfigEntry<T> : OwnConfigEntryBase { public readonly ConfigEntry<T> SourceConfig; public override ConfigEntryBase BaseConfig => (ConfigEntryBase)(object)SourceConfig; public T Value { get { return SourceConfig.Value; } set { SourceConfig.Value = value; } } public SyncedConfigEntry(ConfigEntry<T> sourceConfig) { SourceConfig = sourceConfig; base..ctor(); } public void AssignLocalValue(T value) { if (LocalBaseValue == null) { Value = value; } else { LocalBaseValue = value; } } } internal abstract class CustomSyncedValueBase { public object? LocalBaseValue; public readonly string Identifier; public readonly Type Type; private object? boxedValue; protected bool localIsOwner; public readonly int Priority; public object? BoxedValue { get { return boxedValue; } set { boxedValue = value; this.ValueChanged?.Invoke(); } } public event Action? ValueChanged; protected CustomSyncedValueBase(ConfigSync configSync, string identifier, Type type, int priority) { Priority = priority; Identifier = identifier; Type = type; configSync.AddCustomValue(this); localIsOwner = configSync.IsSourceOfTruth; configSync.SourceOfTruthChanged += delegate(bool truth) { localIsOwner = truth; }; } } [PublicAPI] internal sealed class CustomSyncedValue<T> : CustomSyncedValueBase { public T Value { get { return (T)base.BoxedValue; } set { base.BoxedValue = value; } } public CustomSyncedValue(ConfigSync configSync, string identifier, T value = default(T), int priority = 0) : base(configSync, identifier, typeof(T), priority) { Value = value; } public void AssignLocalValue(T value) { if (localIsOwner) { Value = value; } else { LocalBaseValue = value; } } } internal class ConfigurationManagerAttributes { [UsedImplicitly] public bool? ReadOnly = false; } [PublicAPI] internal class ConfigSync { [HarmonyPatch(typeof(ZRpc), "HandlePackage")] private static class SnatchCurrentlyHandlingRPC { public static ZRpc? currentRpc; [HarmonyPrefix] private static void Prefix(ZRpc __instance) { currentRpc = __instance; } } [HarmonyPatch(typeof(ZNet), "Awake")] internal static class RegisterRPCPatch { [HarmonyPostfix] private static void Postfix(ZNet __instance) { isServer = __instance.IsServer(); foreach (ConfigSync configSync2 in configSyncs) { ZRoutedRpc.instance.Register<ZPackage>(configSync2.Name + " ConfigSync", (Action<long, ZPackage>)configSync2.RPC_FromOtherClientConfigSync); if (isServer) { configSync2.InitialSyncDone = true; Debug.Log((object)("Registered '" + configSync2.Name + " ConfigSync' RPC - waiting for incoming connections")); } } if (isServer) { ((MonoBehaviour)__instance).StartCoroutine(WatchAdminListChanges()); } static void SendAdmin(List<ZNetPeer> peers, bool isAdmin) { ZPackage package = ConfigsToPackage(null, null, new PackageEntry[1] { new PackageEntry { section = "Internal", key = "lockexempt", type = typeof(bool), value = isAdmin } }); ConfigSync configSync = configSyncs.First(); if (configSync != null) { ((MonoBehaviour)ZNet.instance).StartCoroutine(configSync.sendZPackage(peers, package)); } } static IEnumerator WatchAdminListChanges() { MethodInfo listContainsId = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null); SyncedList adminList = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance); List<string> CurrentList = new List<string>(adminList.GetList()); while (true) { yield return (object)new WaitForSeconds(30f); if (!adminList.GetList().SequenceEqual(CurrentList)) { CurrentList = new List<string>(adminList.GetList()); List<ZNetPeer> adminPeer = ZNet.instance.GetPeers().Where(delegate(ZNetPeer p) { string hostName = p.m_rpc.GetSocket().GetHostName(); return ((object)listContainsId == null) ? adminList.Contains(hostName) : ((bool)listContainsId.Invoke(ZNet.instance, new object[2] { adminList, hostName })); }).ToList(); List<ZNetPeer> nonAdminPeer = ZNet.instance.GetPeers().Except(adminPeer).ToList(); SendAdmin(nonAdminPeer, isAdmin: false); SendAdmin(adminPeer, isAdmin: true); } } } } } [HarmonyPatch(typeof(ZNet), "OnNewConnection")] private static class RegisterClientRPCPatch { [HarmonyPostfix] private static void Postfix(ZNet __instance, ZNetPeer peer) { if (__instance.IsServer()) { return; } foreach (ConfigSync configSync in configSyncs) { peer.m_rpc.Register<ZPackage>(configSync.Name + " ConfigSync", (Action<ZRpc, ZPackage>)configSync.RPC_FromServerConfigSync); } } } private class ParsedConfigs { public readonly Dictionary<OwnConfigEntryBase, object?> configValues = new Dictionary<OwnConfigEntryBase, object>(); public readonly Dictionary<CustomSyncedValueBase, object?> customValues = new Dictionary<CustomSyncedValueBase, object>(); } [HarmonyPatch(typeof(ZNet), "Shutdown")] private class ResetConfigsOnShutdown { [HarmonyPostfix] private static void Postfix() { ProcessingServerUpdate = true; foreach (ConfigSync configSync in configSyncs) { configSync.resetConfigsFromServer(); configSync.IsSourceOfTruth = true; configSync.InitialSyncDone = false; } ProcessingServerUpdate = false; } } [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] private class SendConfigsAfterLogin { private class BufferingSocket : ZPlayFabSocket, ISocket { public volatile bool finished = false; public volatile int versionMatchQueued = -1; public readonly List<ZPackage> Package = new List<ZPackage>(); public readonly ISocket Original; public BufferingSocket(ISocket original) { Original = original; ((ZPlayFabSocket)this)..ctor(); } public bool IsConnected() { return Original.IsConnected(); } public ZPackage Recv() { return Original.Recv(); } public int GetSendQueueSize() { return Original.GetSendQueueSize(); } public int GetCurrentSendRate() { return Original.GetCurrentSendRate(); } public bool IsHost() { return Original.IsHost(); } public void Dispose() { Original.Dispose(); } public bool GotNewData() { return Original.GotNewData(); } public void Close() { Original.Close(); } public string GetEndPointString() { return Original.GetEndPointString(); } public void GetAndResetStats(out int totalSent, out int totalRecv) { Original.GetAndResetStats(ref totalSent, ref totalRecv); } public void GetConnectionQuality(out float localQuality, out float remoteQuality, out int ping, out float outByteSec, out float inByteSec) { Original.GetConnectionQuality(ref localQuality, ref remoteQuality, ref ping, ref outByteSec, ref inByteSec); } public ISocket Accept() { return Original.Accept(); } public int GetHostPort() { return Original.GetHostPort(); } public bool Flush() { return Original.Flush(); } public string GetHostName() { return Original.GetHostName(); } public void VersionMatch() { if (finished) { Original.VersionMatch(); } else { versionMatchQueued = Package.Count; } } public void Send(ZPackage pkg) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown int pos = pkg.GetPos(); pkg.SetPos(0); int num = pkg.ReadInt(); if ((num == StringExtensionMethods.GetStableHashCode("PeerInfo") || num == StringExtensionMethods.GetStableHashCode("RoutedRPC") || num == StringExtensionMethods.GetStableHashCode("ZDOData")) && !finished) { ZPackage val = new ZPackage(pkg.GetArray()); val.SetPos(pos); Package.Add(val); } else { pkg.SetPos(pos); Original.Send(pkg); } } } [HarmonyPriority(800)] [HarmonyPrefix] private static void Prefix(ref Dictionary<Assembly, BufferingSocket>? __state, ZNet __instance, ZRpc rpc) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Invalid comparison between Unknown and I4 if (!__instance.IsServer()) { return; } BufferingSocket bufferingSocket = new BufferingSocket(rpc.GetSocket()); AccessTools.DeclaredField(typeof(ZRpc), "m_socket").SetValue(rpc, bufferingSocket); object? obj = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance, new object[1] { rpc }); ZNetPeer val = (ZNetPeer)((obj is ZNetPeer) ? obj : null); if (val != null && (int)ZNet.m_onlineBackend > 0) { FieldInfo fieldInfo = AccessTools.DeclaredField(typeof(ZNetPeer), "m_socket"); object? value = fieldInfo.GetValue(val); ZPlayFabSocket val2 = (ZPlayFabSocket)((value is ZPlayFabSocket) ? value : null); if (val2 != null) { typeof(ZPlayFabSocket).GetField("m_remotePlayerId").SetValue(bufferingSocket, val2.m_remotePlayerId); } fieldInfo.SetValue(val, bufferingSocket); } if (__state == null) { __state = new Dictionary<Assembly, BufferingSocket>(); } __state[Assembly.GetExecutingAssembly()] = bufferingSocket; } [HarmonyPostfix] private static void Postfix(Dictionary<Assembly, BufferingSocket> __state, ZNet __instance, ZRpc rpc) { ZRpc rpc2 = rpc; ZNet __instance2 = __instance; Dictionary<Assembly, BufferingSocket> __state2 = __state; ZNetPeer peer; if (__instance2.IsServer()) { object obj = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance2, new object[1] { rpc2 }); peer = (ZNetPeer)((obj is ZNetPeer) ? obj : null); if (peer == null) { SendBufferedData(); } else { ((MonoBehaviour)__instance2).StartCoroutine(sendAsync()); } } void SendBufferedData() { if (rpc2.GetSocket() is BufferingSocket bufferingSocket) { AccessTools.DeclaredField(typeof(ZRpc), "m_socket").SetValue(rpc2, bufferingSocket.Original); object? obj2 = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance2, new object[1] { rpc2 }); ZNetPeer val = (ZNetPeer)((obj2 is ZNetPeer) ? obj2 : null); if (val != null) { AccessTools.DeclaredField(typeof(ZNetPeer), "m_socket").SetValue(val, bufferingSocket.Original); } } BufferingSocket bufferingSocket2 = __state2[Assembly.GetExecutingAssembly()]; bufferingSocket2.finished = true; for (int i = 0; i < bufferingSocket2.Package.Count; i++) { if (i == bufferingSocket2.versionMatchQueued) { bufferingSocket2.Original.VersionMatch(); } bufferingSocket2.Original.Send(bufferingSocket2.Package[i]); } if (bufferingSocket2.Package.Count == bufferingSocket2.versionMatchQueued) { bufferingSocket2.Original.VersionMatch(); } } IEnumerator sendAsync() { foreach (ConfigSync configSync in configSyncs) { List<PackageEntry> entries = new List<PackageEntry>(); if (configSync.CurrentVersion != null) { entries.Add(new PackageEntry { section = "Internal", key = "serverversion", type = typeof(string), value = configSync.CurrentVersion }); } MethodInfo listContainsId = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null); SyncedList adminList = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance); entries.Add(new PackageEntry { section = "Internal", key = "lockexempt", type = typeof(bool), value = (((object)listContainsId == null) ? ((object)adminList.Contains(rpc2.GetSocket().GetHostName())) : listContainsId.Invoke(ZNet.instance, new object[2]