using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using Newtonsoft.Json; using UnityEngine; using UnityEngine.Networking; using neobotics.ModSdk; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("ReelySpecTackleLure")] [assembly: AssemblyConfiguration("Deploy")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+1685f20b8299edd109bbabfd554f5d93afd12c56")] [assembly: AssemblyProduct("ReelySpecTackleLure")] [assembly: AssemblyTitle("ReelySpecTackleLure")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] public sealed class ConfigurationManagerAttributes { public delegate void CustomHotkeyDrawerFunc(ConfigEntryBase setting, ref bool isCurrentlyAcceptingInput); public bool? ShowRangeAsPercent; public Action CustomDrawer; public CustomHotkeyDrawerFunc CustomHotkeyDrawer; public bool? Browsable; public string Category; public object DefaultValue; public bool? HideDefaultButton; public bool? HideSettingName; public string Description; public string DispName; public int? Order; public bool? ReadOnly; public bool? IsAdvanced; public Func ObjToStr; public Func StrToObj; } namespace neobotics.ModSdk { public class AudioHelper : MonoBehaviour { private readonly Dictionary audioClips = new Dictionary(); private Logging logger; public void Awake() { logger = Logging.GetLogger(); logger.Debug("AudidHelper.Awake"); } public void Start() { logger.Debug("AudioHelper.Start"); ZRoutedRpc.instance.Register("NeoPlayClip", (Action)RPC_NeoPlayClip); } public void RPC_NeoPlayClip(long sender, Vector3 sourcePoint, string clipName) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (ZNet.instance.IsDedicated()) { return; } try { NeoPlayClip(sourcePoint, clipName); } catch (Exception e) { logger.Error(e, stackTrace: false); } } public void Play(Vector3 sourcePoint, string clipName) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "NeoPlayClip", new object[2] { sourcePoint, clipName }); } public void NeoPlayClip(Vector3 sourcePoint, string clipName) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)Player.m_localPlayer).transform.position; NeoPlayClip(sourcePoint, position, clipName); } public void NeoPlayClip(Vector3 sourcePoint, Vector3 targetPoint, string clipName) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) if (!audioClips.TryGetValue(clipName.ToLower(), out var value)) { logger.Warning("Couldn't find audio clip for " + clipName); return; } Vector3 val = sourcePoint - targetPoint; Vector3 normalized = ((Vector3)(ref val)).normalized; float num = (Vector3.Distance(sourcePoint, targetPoint) + 1f) / 10f; AudioSource.PlayClipAtPoint(value, targetPoint + normalized * num, 1f); } public float GetClipDuration(string clipName) { if (!audioClips.TryGetValue(clipName.ToLower(), out var value)) { return -1f; } return value.length; } internal void LoadAudioResources(string resourceFolder) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) audioClips.Clear(); logger.Debug("LoadAudioResources"); string[] files = Directory.GetFiles(resourceFolder, "*.*", SearchOption.TopDirectoryOnly); foreach (string text in files) { string text2 = Path.GetExtension(text).ToLowerInvariant(); AudioType val = (AudioType)0; if (!(text2 == ".wav")) { if (text2 == ".mp3") { val = (AudioType)13; } } else { val = (AudioType)20; } if ((int)val != 0) { ((MonoBehaviour)this).StartCoroutine(LoadExternalClip(text, val)); } } } private IEnumerator LoadExternalClip(string filePath, AudioType type) { //IL_0015: 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) string uri = new Uri(filePath).AbsoluteUri; string clipName = Path.GetFileName(filePath).ToLowerInvariant(); UnityWebRequest req = UnityWebRequestMultimedia.GetAudioClip(uri, type); yield return req.SendWebRequest(); if ((int)req.result == 1) { AudioClip content = DownloadHandlerAudioClip.GetContent(req); audioClips[clipName] = content; logger.Debug("Loaded external audio: " + clipName); } else { logger.Warning("Failed to load external audio: " + uri); } } } internal class CircularList { private List circle; private int index; public int Index => index; public CircularList(List source, T startingElement) { circle = new List(source); index = circle.FindIndex((T x) => x.Equals(startingElement)); } public T Next() { index = ((index < circle.Count - 1) ? (index + 1) : 0); return circle[index]; } public T Previous() { index = ((index > 0) ? (index - 1) : (circle.Count - 1)); return circle[index]; } } public static class ConfigFolderHelper { private const string ROOT = "Neobotics"; public static string GetOrCreateModConfigFolder(string modName) { string text = Path.Combine(Paths.ConfigPath, "Neobotics", modName); Directory.CreateDirectory(text); return text; } } public class ConfigMock { public bool Value { get; set; } } public class CrossPlatformRandom : Random { private const int LCG_MULTIPLIER = 134775813; private const int LCG_INCREMENT = 1; private int _seed; public float value => (float)NextDouble(); public CrossPlatformRandom() { Random random = new Random(); _seed = random.Next(); } public CrossPlatformRandom(int seed) { _seed = seed; } public float Range(int min, int max) { return Next(min, max); } public float Range(float min, float max) { return Mathf.Lerp(min, max, (float)NextDouble()); } private int GetNext() { _seed = _seed * 134775813 + 1; return _seed; } public override int Next() { return Next(int.MaxValue); } public override int Next(int maxValue) { if (maxValue < 0) { throw new ArgumentOutOfRangeException("maxValue is less than zero."); } return (int)((long)(uint)GetNext() * (long)(uint)maxValue >>> 32); } public override int Next(int minValue, int maxValue) { if (minValue > maxValue) { throw new ArgumentOutOfRangeException("minValue is greater than maxValue."); } return minValue + Next(maxValue - minValue); } public override double NextDouble() { return Sample(); } protected override double Sample() { return (double)Next() / 2147483647.0; } } internal class CustomDataWrapper { private Dictionary playerData; private Dictionary Data { get; set; } public CustomDataWrapper(Dictionary sourceData, string keyPrefix) { CustomDataWrapper customDataWrapper = this; playerData = sourceData; Data = new Dictionary(); sourceData.Keys.ToList().ForEach(delegate(string key) { if (key.StartsWith(keyPrefix)) { customDataWrapper.Data.Add(key, sourceData[key]); } }); } public void Add(string key, string value) { Data.Add(key, value); playerData.Add(key, value); } public bool Remove(string key) { return Data.Remove(key) & playerData.Remove(key); } public void Set(string key, string value) { if (Data.ContainsKey(key)) { Data[key] = value; } else { Data.Add(key, value); } if (playerData.ContainsKey(key)) { playerData[key] = value; } else { playerData.Add(key, value); } } public string Get(string key) { if (Data.ContainsKey(key)) { return Data[key]; } return null; } public bool ContainsKey(string key) { return Data.ContainsKey(key); } public void PreSaveSync() { foreach (KeyValuePair datum in Data) { if (!playerData.ContainsKey(datum.Key)) { playerData.Add(datum.Key, datum.Value); } } } } internal class DebugUtils { internal static void ObjectInspector(object o) { if (o == null) { Debug.Log((object)"Object is null"); return; } BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; Type type = o.GetType(); Debug.Log((object)("Object: " + o.ToString() + " Type " + type.Name)); PropertyInfo[] properties = type.GetProperties(bindingAttr); foreach (PropertyInfo propertyInfo in properties) { if (propertyInfo.CanRead) { Debug.Log((object)$"Property: {type.Name}.{propertyInfo.Name} = {propertyInfo.GetValue(o)}"); continue; } Debug.Log((object)("Property: " + type.Name + "." + propertyInfo.Name + " is write-only")); } FieldInfo[] fields = type.GetFields(bindingAttr); foreach (FieldInfo field in fields) { FieldPrinter(o, type, field); } } internal static void MethodInspector(object o) { if (o == null) { Debug.Log((object)"Object is null"); return; } BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; Type type = o.GetType(); Debug.Log((object)("Method: " + o.ToString() + " Type " + type.Name)); MethodInfo[] methods = type.GetMethods(bindingAttr); foreach (MethodInfo methodInfo in methods) { methodInfo.GetParameters(); string arg = string.Join(", ", (from x in methodInfo.GetParameters() select x.ParameterType?.ToString() + " " + x.Name).ToArray()); Debug.Log((object)$"{methodInfo.ReturnType} {methodInfo.Name} ({arg})"); } } private static void ItemDataInspector(ItemData item) { ObjectInspector(item); ObjectInspector(item?.m_shared); } private static void FieldPrinter(object o, Type t, FieldInfo field) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Expected O, but got Unknown try { if (field.FieldType == typeof(ItemData)) { ItemData val = (ItemData)field.GetValue(o); if (val != null) { ItemDataInspector(val); } else { Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)} [null]"); } } else if (field.FieldType == typeof(Transform)) { Transform val2 = (Transform)field.GetValue(o); if ((Object)(object)val2 != (Object)null) { Debug.Log((object)("\tTransform.parent = " + ((Object)val2.parent).name)); } else { Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)} [null]"); } } else if (field.FieldType == typeof(EffectList)) { EffectList val3 = (EffectList)field.GetValue(o); if (val3 != null) { Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)}:"); EffectData[] effectPrefabs = val3.m_effectPrefabs; foreach (EffectData val4 in effectPrefabs) { Debug.Log((object)("\tEffectData.m_prefab = " + ((Object)val4.m_prefab).name)); } } else { Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)} [null]"); } } else { Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)}"); } } catch (Exception) { Debug.Log((object)("Exception accessing " + t?.Name + "." + field?.Name)); } } internal static void GameObjectInspector(GameObject go) { if ((Object)(object)go == (Object)null) { Debug.Log((object)"\n\nGame Object is null"); return; } Debug.Log((object)("\n\nInspecting GameObject " + ((Object)go).name)); ObjectInspector(go); Component[] componentsInChildren = go.GetComponentsInChildren(); if (componentsInChildren.Length == 0) { return; } Component[] array = componentsInChildren; foreach (Component c in array) { try { ComponentInspector(c); } catch (Exception) { } } } internal static void PrintList(List l) { foreach (T item in l) { Debug.Log((object)item.ToString()); } } internal static void ComponentInspector(Component c) { string obj = ((c != null) ? ((Object)c).name : null); object obj2; if (c == null) { obj2 = null; } else { Transform transform = c.transform; if (transform == null) { obj2 = null; } else { Transform parent = transform.parent; obj2 = ((parent != null) ? ((Object)parent).name : null); } } Debug.Log((object)("\n\nInspecting Component " + obj + " with parent " + (string?)obj2)); ObjectInspector(c); } internal static void EffectsInspector(EffectList e) { EffectData[] effectPrefabs = e.m_effectPrefabs; Debug.Log((object)$"Effect list has effects {e.HasEffects()} count {effectPrefabs.Length}"); EffectData[] array = effectPrefabs; foreach (EffectData val in array) { Debug.Log((object)$"Effect Data {val} prefab name {((Object)val.m_prefab).name} prefab GameObject name {((Object)val.m_prefab.gameObject).name}"); } } internal static void PrintInventory() { foreach (ItemData allItem in ((Humanoid)Player.m_localPlayer).GetInventory().GetAllItems()) { Debug.Log((object)allItem.m_shared.m_name); } } internal static void PrintAllObjects() { ZNetScene.instance.m_prefabs.ForEach(delegate(GameObject x) { Debug.Log((object)("GameObject " + ((Object)x).name)); }); } internal static void PrintAllCharacters() { Character.GetAllCharacters().ForEach(delegate(Character x) { Debug.Log((object)("Character " + ((Object)x).name)); }); } internal static void PrintAllLayers() { string[] array = (from index in Enumerable.Range(0, 31) select LayerMask.LayerToName(index) into l where !string.IsNullOrEmpty(l) select l).ToArray(); foreach (string text in array) { Debug.Log((object)("Layer " + text + " " + Convert.ToString(LayerMask.NameToLayer(text), 2).PadLeft(32, '0'))); } } } public class DelegatedConfigEntry : DelegatedConfigEntryBase { private ConfigEntry _entry; private EventHandler rootHandler; private Action clientDelegate; private Logging Log; public ConfigEntry ConfigEntry { get { return _entry; } set { _entry = value; if (_entry != null && rootHandler != null) { _entry.SettingChanged += rootHandler; } Name = ((ConfigEntryBase)_entry).Definition.Key; Section = ((ConfigEntryBase)_entry).Definition.Section; ServerValue = ((ConfigEntryBase)_entry).GetSerializedValue(); Log.Trace("Set " + Section + " " + Name + " to serialized value " + ServerValue); } } public T Value { get { return _entry.Value; } set { _entry.Value = value; } } public DelegatedConfigEntry(bool useServerDelegate = false) : this((Action)null, useServerDelegate) { } public DelegatedConfigEntry(Action delegateHandler, bool useServerDelegate = false) { Log = Logging.GetLogger(); Log.Trace("DelegatedConfigEntry"); if (delegateHandler != null) { clientDelegate = delegateHandler; } if (useServerDelegate) { Log.Trace("Configuring server delegate"); rootHandler = delegate(object s, EventArgs e) { ServerDelegate(s, e); }; ServerConfiguration.ServerDelegatedEntries.Add(this); } else if (clientDelegate != null) { rootHandler = delegate(object s, EventArgs e) { clientDelegate(s, e); }; } } private void ServerDelegate(object sender, EventArgs args) { //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected O, but got Unknown Logging.GetLogger().Trace("ServerDelegate"); _entry.SettingChanged -= rootHandler; ZNet instance = ZNet.instance; bool? flag = ((instance != null) ? new bool?(instance.IsServer()) : ((bool?)null)); if (flag.HasValue) { if (flag == false && ServerConfiguration.Instance.ReceivedServerValues) { if (ServerValue != null) { ((ConfigEntryBase)_entry).SetSerializedValue(ServerValue); Log.Debug("Setting " + Name + " to server value " + ServerValue); } } else if (flag == true) { ServerValue = ((ConfigEntryBase)_entry).GetSerializedValue(); ServerConfiguration.Instance.SendConfigToAllClients(sender, (SettingChangedEventArgs)args); } } if (clientDelegate != null) { clientDelegate(sender, args); } _entry.SettingChanged += rootHandler; } public void EnableHandler(bool setActive) { if (setActive) { _entry.SettingChanged += rootHandler; } else { _entry.SettingChanged -= rootHandler; } } public bool IsKeyPressed() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) if (ConfigEntry is ConfigEntry val) { return InputEvaluator.IsPressed(val.Value); } Log.Error("Keyboard read attempted on non-KeyboardShortcut config."); return false; } public bool IsKeyDown() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) if (ConfigEntry is ConfigEntry val) { return InputEvaluator.IsDown(val.Value); } Log.Error("Keyboard read attempted on non-KeyboardShortcut config."); return false; } public bool IsKeyReleased() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) if (ConfigEntry is ConfigEntry val) { return InputEvaluator.IsReleased(val.Value); } Log.Error("Keyboard read attempted on non-KeyboardShortcut config."); return false; } } public class DelegatedConfigEntryBase { public string Name; public string Section; public string ServerValue; } internal class HarmonyHelper { public enum PatchType { Prefix, Postfix, Transpiler, Finalizer } private static Dictionary detectionSet = new Dictionary(); private static Dictionary unpatchMods = new Dictionary(); public static IReadOnlyDictionary DetectionSet => detectionSet; public static void GetDetectionSet(Dictionary harmonyIds) { Logging logger = Logging.GetLogger(); foreach (KeyValuePair harmonyId in harmonyIds) { if (Harmony.HasAnyPatches(harmonyId.Key)) { logger.Debug("Detected " + harmonyId.Value + " from Harmony"); if (!detectionSet.ContainsKey(harmonyId.Key)) { detectionSet.Add(harmonyId.Key, harmonyId.Value); } } else if (Chainloader.PluginInfos.ContainsKey(harmonyId.Key)) { logger.Debug("Detected " + harmonyId.Value + " from BepInEx"); if (!detectionSet.ContainsKey(harmonyId.Key)) { detectionSet.Add(harmonyId.Key, harmonyId.Value); } } } } public static void AddToUnpatch(string key) { if (detectionSet.ContainsKey(key)) { unpatchMods.Add(key, detectionSet[key]); } } public static void UnpatchMods(Harmony harmony) { Logging logger = Logging.GetLogger(); foreach (KeyValuePair unpatchMod in unpatchMods) { logger.Warning("Not compatible with " + unpatchMod.Value); Harmony.UnpatchID(unpatchMod.Key); detectionSet.Remove(unpatchMod.Key); logger.Warning("Disabled " + unpatchMod.Value); } } public static bool IsModDetected(string key) { return detectionSet.ContainsKey(key); } public static bool IsModNameDetected(string value) { return detectionSet.ContainsValue(value); } public static bool TryGetDetectedModName(string key, out string mod) { return detectionSet.TryGetValue(key, out mod); } public static bool TryGetDetectedModKey(string value, out string key) { key = null; foreach (string key2 in detectionSet.Keys) { if (detectionSet[key2] == value) { key = key2; return true; } } return false; } public static string AddAnonymousPatch(string baseMethodName, PatchType patchType, string modName, string patchMethodName = null) { string text = null; int num = 0; Logging logger = Logging.GetLogger(); foreach (MethodBase item in Harmony.GetAllPatchedMethods().ToList()) { MethodBaseExtensions.HasMethodBody(item); Patches patchInfo = Harmony.GetPatchInfo(item); ReadOnlyCollection readOnlyCollection = patchInfo.Prefixes; switch (patchType) { case PatchType.Postfix: readOnlyCollection = patchInfo.Postfixes; break; case PatchType.Prefix: readOnlyCollection = patchInfo.Prefixes; break; case PatchType.Transpiler: readOnlyCollection = patchInfo.Transpilers; break; case PatchType.Finalizer: readOnlyCollection = patchInfo.Finalizers; break; } foreach (Patch item2 in readOnlyCollection) { if (!item2.owner.StartsWith("harmony-auto") || !(item.Name == baseMethodName)) { continue; } if (patchMethodName != null) { if (item2.PatchMethod.Name == patchMethodName) { num++; text = item2.owner; } } else { num++; text = item2.owner; } } if (num == 1) { detectionSet.Add(text, modName); logger.Info($"Added unique anonymous {baseMethodName} {patchType}: {text} as {modName}"); } else if (num > 1) { text = null; logger.Warning($"Found multiple anonymous {baseMethodName} {patchType} entries. Can't identify correct patch to remove or modify."); } } if (num == 0) { logger.Info("No patch found for " + modName); } return text; } } public class ImageHelper { private readonly string externalFolder; private readonly Logging logger; public ImageHelper(string externalFolder) { this.externalFolder = externalFolder; logger = Logging.GetLogger(); } public Sprite LoadSprite(string name, int width, int height, bool linear = false, float pixelsPerUnit = 100f) { logger.Debug("Reading image and creating sprite " + name); if (TryLoadImage(name, width, height, linear, out var image)) { return LoadSprite(image, pixelsPerUnit); } return null; } public Sprite LoadSprite(Texture2D texture, float pixelsPerUnit = 100f) { return LoadSprite(texture, ((Object)texture).name, ((Texture)texture).width, ((Texture)texture).height, pixelsPerUnit); } public Sprite LoadSprite(Texture2D texture, string name, float width, float height, float pixelsPerUnit = 100f) { //IL_0044: 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) if ((Object)(object)texture == (Object)null) { return null; } if (string.IsNullOrWhiteSpace(name)) { name = ((Object)texture).name; } logger.Debug("Creating sprite " + name + " from existing texture"); Sprite obj = Sprite.Create(texture, new Rect(0f, 0f, width, height), Vector2.zero, pixelsPerUnit); if ((Object)(object)obj == (Object)null) { throw new ApplicationException("Can't create sprite " + name); } ((Object)obj).name = name; return obj; } public bool TryLoadImage(string name, int width, int height, bool linear, out Texture2D image) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown image = null; string text = Path.Combine(externalFolder, name); logger.Debug("Reading external file " + text); if (!File.Exists(text)) { throw new FileNotFoundException("Cannot find image " + name); } byte[] array = File.ReadAllBytes(text); Texture2D val = new Texture2D(width, height, (TextureFormat)4, true, linear); if (!ImageConversion.LoadImage(val, array, false)) { throw new FileLoadException("Can't load image " + name); } image = val; return true; } } internal class InputCycler { private static InputCycler _instance; private bool useMouseWheel; private DelegatedConfigEntry keyAdvance; private DelegatedConfigEntry keyReferse; public static InputCycler Instance { get { if (_instance == null) { _instance = new InputCycler(); } return _instance; } } private InputCycler() { } public void Init(bool useMouseWheel, DelegatedConfigEntry keyAdvance, DelegatedConfigEntry keyReverse = null) { this.useMouseWheel = useMouseWheel; this.keyAdvance = keyAdvance; keyReferse = keyReverse; } } internal static class InputEvaluator { public unsafe static bool IsPressed(KeyboardShortcut shortcut) { //IL_0002: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) object obj = KeyboardShortcut.Empty; if (((object)(*(KeyboardShortcut*)(&shortcut))/*cast due to .constrained prefix*/).Equals(obj)) { return false; } foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers) { if ((int)modifier != 0 && !Input.GetKey(modifier)) { return false; } } return Input.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey); } public unsafe static bool IsDown(KeyboardShortcut shortcut) { //IL_0002: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) object obj = KeyboardShortcut.Empty; if (((object)(*(KeyboardShortcut*)(&shortcut))/*cast due to .constrained prefix*/).Equals(obj)) { return false; } foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers) { if ((int)modifier != 0 && !Input.GetKey(modifier)) { return false; } } return Input.GetKey(((KeyboardShortcut)(ref shortcut)).MainKey); } public unsafe static bool IsReleased(KeyboardShortcut shortcut) { //IL_0002: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) object obj = KeyboardShortcut.Empty; if (((object)(*(KeyboardShortcut*)(&shortcut))/*cast due to .constrained prefix*/).Equals(obj)) { return false; } foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers) { if ((int)modifier != 0 && !Input.GetKeyUp(modifier)) { return false; } } return Input.GetKeyUp(((KeyboardShortcut)(ref shortcut)).MainKey); } } public class IterativeStopwatch : Stopwatch { private double startMillis; private Logging Log = Logging.GetLogger(); public long Iterations { get; private set; } public double IterationMicroseconds { get; private set; } public double TotalElapsedMicroseconds { get; private set; } public double IterationMilliseconds { get; private set; } public double TotalElapsedMilliseconds { get; private set; } public double AverageMicroseconds { get; private set; } public double AverageMilliseconds { get; private set; } public IterativeStopwatch() { Iterations = 0L; } public new void Start() { startMillis = base.Elapsed.TotalMilliseconds; base.Start(); } public new void Stop() { if (base.IsRunning) { base.Stop(); Iterations++; IterationMilliseconds = base.Elapsed.TotalMilliseconds - startMillis; IterationMicroseconds = IterationMilliseconds * 1000.0; TotalElapsedMilliseconds = base.Elapsed.TotalMilliseconds; TotalElapsedMicroseconds = base.Elapsed.TotalMilliseconds * 1000.0; AverageMilliseconds = TotalElapsedMilliseconds / (double)Iterations; AverageMicroseconds = TotalElapsedMicroseconds / (double)Iterations; } } public new void Reset() { startMillis = 0.0; Iterations = 0L; base.Reset(); } public new void Restart() { startMillis = 0.0; Iterations = 0L; base.Restart(); } } public static class JsonHelper { [Serializable] private class JsonWrapper { public T[] Items; } public static T[] FromJson(string json) { return JsonUtility.FromJson>(json).Items; } public static string ToJson(T[] array) { return JsonUtility.ToJson((object)new JsonWrapper { Items = array }); } public static string ToJson(T[] array, bool prettyPrint) { return JsonUtility.ToJson((object)new JsonWrapper { Items = array }, prettyPrint); } } public class Logging { internal enum LogLevels { Critical, Error, Warning, Info, Debug, Trace } private static Logging _instance; public static Logging Instance { get { if (_instance == null) { throw new InvalidOperationException("Logging.Instance was accessed before initialization. Call Logging.Initialize() in your mod's startup code first."); } return _instance; } private set { _instance = value; } } internal LogLevels LogLevel { get; set; } internal string ModName { get; private set; } private Logging(LogLevels level, string name) { LogLevel = level; ModName = name; } internal static Logging Initialize(LogLevels level, string name) { if (_instance != null) { Instance.Warning("Logger is already initialized. Using existing logger"); return _instance; } Instance = new Logging(level, name); return _instance; } internal static Logging GetLogger(LogLevels level, string name) { if (_instance == null) { Initialize(level, name); } return Instance; } internal static Logging GetLogger() { return Instance; } internal void Trace(string msg) { if (LogLevel >= LogLevels.Trace) { Debug.Log((object)Message(msg)); } } internal void Debug(string msg) { if (LogLevel >= LogLevels.Debug) { Debug.Log((object)Message(msg)); } } internal void Info(string msg) { if (LogLevel >= LogLevels.Info) { Debug.Log((object)Message(msg)); } } internal void Warning(string msg) { if (LogLevel >= LogLevels.Warning) { Debug.LogWarning((object)Message(msg)); } } internal void Error(string msg) { if (LogLevel >= LogLevels.Error) { Debug.LogWarning((object)Message(msg)); } } internal void Error(Exception e) { Error(e, stackTrace: false); } internal void Error(Exception e, bool stackTrace) { if (LogLevel >= LogLevels.Error) { Warning(Message(e.Message)); if (stackTrace) { Warning(e.StackTrace); } } } internal void Critical(Exception e) { if (LogLevel >= LogLevels.Critical) { Debug(Message(e.Message)); Error(e.StackTrace); } } private string Message(string msg) { return ModName + ": " + msg; } internal bool Testing() { return Instance.LogLevel >= LogLevels.Debug; } internal static void ChangeLogging(object s, EventArgs e) { ConfigEntry val = s as ConfigEntry; if (_instance != null) { Instance.LogLevel = val.Value; Instance.Info($"Change {((ConfigEntryBase)val).Definition.Key} to {val.Value}"); } } } public static class ModResourceBootstrap { public static string InitializeModResources(Type pluginType, string modName) { string orCreateModConfigFolder = ConfigFolderHelper.GetOrCreateModConfigFolder(modName); Logging.Instance.Debug("Mod config folder: " + orCreateModConfigFolder); string prefix = modName + ".Resources."; Logging.Instance.Debug("Mod resources: " + orCreateModConfigFolder); ExtractResources(pluginType.Assembly, prefix, orCreateModConfigFolder); return orCreateModConfigFolder; } private static void ExtractResources(Assembly asm, string prefix, string targetFolder) { Logging.Instance.Debug("Checking resources for " + prefix); string[] manifestResourceNames = asm.GetManifestResourceNames(); foreach (string text in manifestResourceNames) { Logging.Instance.Debug("Resource " + text); if (!text.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) { continue; } string text2 = text.Substring(prefix.Length); string text3 = Path.Combine(targetFolder, text2); Logging.Instance.Debug("Extracting " + text2 + " to " + text3); if (File.Exists(text3)) { continue; } using Stream stream = asm.GetManifestResourceStream(text); using FileStream destination = File.Create(text3); stream.CopyTo(destination); } } } public class ServerConfiguration { [HarmonyPatch(typeof(ZNet), "StopAll")] private static class ZNet_Shutdown_Patch { [HarmonyPrefix] private static void ZNet_StopAll_Prefix(ZNet __instance) { if (_instance != null) { Log.Debug("ZNet_StopAll_Patch_Prefix"); _instance.ReceivedServerValues = false; } } } [HarmonyPatch(typeof(ZNet), "OnNewConnection")] private static class ZNet_OnNewConnection_Patch { private static void Postfix(ZNet __instance, ZNetPeer peer) { Log.Debug("ZNet OnNewConnection postfix"); if (!__instance.IsServer()) { try { peer.m_rpc.Register("ClientConfigReceiver." + GetPluginGuid(), (Action)Instance.RPC_ClientConfigReceiver); Log.Debug("Player registered RPC_ClientConfigReceiver"); return; } catch (Exception) { Log.Warning("Failed to register RPC"); return; } } try { Instance.SendConfigToClient(peer); } catch (Exception) { Log.Warning("Error sending server configuration to client"); } } } public static List ServerDelegatedEntries = new List(); private static ConfigFile LocalConfig; private static BaseUnityPlugin Mod; private static string ConfigFileName; private static ServerConfiguration _instance; private static Logging Log; public bool IsSetup; public bool ReceivedServerValues; public FileSystemWatcher ConfigWatcher; private const string NOT_CONFIGURED = "ServerConfiguration not initialized. Setup first."; public static ServerConfiguration Instance { get { if (_instance == null) { _instance = new ServerConfiguration(); } return _instance; } } private ServerConfiguration() { } public void Setup(ConfigFile config, BaseUnityPlugin modInstance) { LocalConfig = config; Log = Logging.GetLogger(); Log.Trace("ServerConfiguration Setup"); Mod = modInstance; ConfigFileName = Path.GetFileName(LocalConfig.ConfigFilePath); IsSetup = true; } public void CreateConfigWatcher() { ConfigWatcher = Utils.CreateFileWatcher(LocalConfig.ConfigFilePath, LoadConfig); } private void LoadConfig(object sender, FileSystemEventArgs e) { if (!File.Exists(LocalConfig.ConfigFilePath)) { return; } try { Log.Debug($"Loading configuration {e.ChangeType}"); LocalConfig.Reload(); } catch { Log.Error("Error loading configuration file " + ConfigFileName); } } public static string GetPluginGuid() { return Mod.Info.Metadata.GUID; } public void RPC_ClientConfigReceiver(ZRpc zrpc, ZPackage package) { if (!Instance.IsSetup) { Log.Error("ServerConfiguration not initialized. Setup first."); return; } Log.Debug("ClientConfigReceiver"); string section; string name; while (package.GetPos() < package.Size()) { section = package.ReadString(); name = package.ReadString(); string text = package.ReadString(); Log.Trace("Reading " + section + " " + name + " value " + text + " from ZPackage"); DelegatedConfigEntryBase delegatedConfigEntryBase = ServerDelegatedEntries.Find((DelegatedConfigEntryBase e) => e.Name == name && e.Section == section); if (delegatedConfigEntryBase != null) { Log.Trace("Found DCEB on client and setting to server value " + text); delegatedConfigEntryBase.ServerValue = text; } ConfigEntryBase val = LocalConfig[section, name]; if (val != null) { Log.Trace("Found local CEB and setting underlying config value " + text); val.SetSerializedValue(text); } } ReceivedServerValues = true; } internal void WriteConfigEntries(ZPackage zpkg) { foreach (DelegatedConfigEntryBase serverDelegatedEntry in ServerDelegatedEntries) { Log.Trace("Writing " + serverDelegatedEntry.Section + " " + serverDelegatedEntry.Name + " value " + serverDelegatedEntry.ServerValue + " to ZPackage"); zpkg.Write(serverDelegatedEntry.Section); zpkg.Write(serverDelegatedEntry.Name); zpkg.Write(serverDelegatedEntry.ServerValue); } } internal void SendConfigToClient(ZNetPeer peer) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown if (!Instance.IsSetup) { Log.Error("ServerConfiguration not initialized. Setup first."); return; } Log.Debug("SendConfigToClient"); ZPackage val = new ZPackage(); WriteConfigEntries(val); peer.m_rpc.Invoke("ClientConfigReceiver." + GetPluginGuid(), new object[1] { val }); Log.Trace("Invoked ClientConfigReceiver on peer"); } public void SendConfigToAllClients(object o, SettingChangedEventArgs e) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown if (!IsSetup) { Log.Error("ServerConfiguration not initialized. Setup first."); } else if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer() && ZNet.instance.GetPeerConnections() > 0) { Log.Debug("SendConfigToAllClients"); ZPackage zpkg = new ZPackage(); WriteConfigEntries(zpkg); ((MonoBehaviour)Mod).StartCoroutine(_instance.Co_BroadcastConfig(zpkg)); } } private IEnumerator Co_BroadcastConfig(ZPackage zpkg) { Log.Debug("Co_BroadcastConfig"); List connectedPeers = ZNet.instance.GetConnectedPeers(); foreach (ZNetPeer item in connectedPeers) { if (item != ZNet.instance.GetServerPeer()) { item.m_rpc.Invoke("ClientConfigReceiver." + GetPluginGuid(), new object[1] { zpkg }); Log.Trace("Invoked ClientConfigReceiver on peer"); } yield return null; } } } public class Utils { public static TEnum Guardrails(string value, TEnum enumDefault) where TEnum : struct { if (Enum.TryParse(value, ignoreCase: true, out var result)) { return result; } return enumDefault; } public static int Guardrails(int value, int lbound, int ubound) { if (value < lbound) { return lbound; } if (value > ubound) { return ubound; } return value; } public static string Truncate(string value, int maxChars) { if (value == null) { return null; } if (value.Length <= maxChars) { return value; } return value.Substring(0, maxChars); } public static void GetCharactersInRangeXZ(Vector3 point, float radius, List characters) { //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) float num = radius * radius; foreach (Character s_character in Character.s_characters) { if (DistanceSqrXZ(((Component)s_character).transform.position, point) < num) { characters.Add(s_character); } } } public static PinData GetClosestPin(Vector3 pos, float radius, PinType pType) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) PinData result = null; float num = float.MaxValue; float num2 = radius * radius; if ((Object)(object)Minimap.instance != (Object)null) { foreach (PinData pin in Minimap.instance.m_pins) { if ((Object)(object)pin.m_uiElement != (Object)null && pin.m_type == pType) { float num3 = DistanceSqrXZ(pos, pin.m_pos); if (Logging.Instance.LogLevel >= Logging.LogLevels.Debug) { Logging.Instance.Debug($"Testing for pin at {pin.m_pos} within radius {radius} from {pos}"); } if (num3 < num2 && num3 < num) { Logging.Instance.Debug("Pin is within radius"); num = num3; result = pin; } } } } return result; } public static float DistanceSqr(Vector3 v0, Vector3 v1) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) Vector3 val = v1 - v0; return ((Vector3)(ref val)).sqrMagnitude; } public static float DistanceSqrXZ(Vector3 v0, Vector3 v1) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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) float num = v1.x - v0.x; float num2 = v1.z - v0.z; return num * num + num2 * num2; } public static Vector3 ClosestPoint(Vector3 point, IEnumerable collection, Func selector) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) Vector3 result = default(Vector3); float num = float.MaxValue; foreach (T item in collection) { Vector3 val = selector(item); Vector3 val2 = val - point; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (sqrMagnitude < num) { num = sqrMagnitude; result = val; } } return result; } public static T ClosestObject(Vector3 point, IEnumerable collection, Func selector) { //IL_0020: 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) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) T result = default(T); float num = float.MaxValue; foreach (T item in collection) { Vector3 val = selector(item) - point; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (sqrMagnitude < num) { num = sqrMagnitude; result = item; } } return result; } public static Vector3 ClosestPointXZ(Vector3 point, IEnumerable collection, Func selector) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) Vector3 result = default(Vector3); float num = float.MaxValue; foreach (T item in collection) { Vector3 val = selector(item); float num2 = DistanceSqrXZ(val, point); if (num2 < num) { num = num2; result = val; } } return result; } public static T ClosestObjectXZ(Vector3 point, IEnumerable collection, Func selector) { //IL_0020: 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) T result = default(T); float num = float.MaxValue; foreach (T item in collection) { float num2 = DistanceSqrXZ(selector(item), point); if (num2 < num) { num = num2; result = item; } } return result; } public static float Guardrails(float value, float lbound, float ubound) { if (value < lbound) { return lbound; } if (value > ubound) { return ubound; } return value; } public static string UnClonifiedName(string name) { if (name == null) { return null; } int num = name.IndexOf("(Clone)"); if (num < 1) { return name; } return name.Substring(0, num); } public static void SetTranslator(int id, string idText) { Localization.instance.AddWord("skill_" + id, idText); } public static string GetTranslated(int id) { Logging.GetLogger().Debug(string.Format("Got translation for id {0} to {1}", id, Localization.instance.Localize("skill_" + id))); return Localization.instance.Localize("$skill_" + id); } public static string GetAssemblyPathedFile(string fileName) { return new FileInfo(Assembly.GetExecutingAssembly().Location).DirectoryName.Replace('\\', '/') + "/" + fileName; } public static Sprite GetPrefabIcon(string prefabName) { Sprite result = null; GameObject prefab = GetPrefab(prefabName); ItemDrop val = default(ItemDrop); if (Object.op_Implicit((Object)(object)prefab) && prefab.TryGetComponent(ref val)) { result = val.m_itemData.GetIcon(); } return result; } public static Player GetPlayerByZDOID(ZDOID zid) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) foreach (Player allPlayer in Player.GetAllPlayers()) { ZDOID zDOID = ((Character)allPlayer).GetZDOID(); if (((ZDOID)(ref zDOID)).Equals(zid)) { return allPlayer; } } return null; } public static Character GetCharacterByZDOID(string cid) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) foreach (Character allCharacter in Character.GetAllCharacters()) { if (((object)allCharacter.GetZDOID()/*cast due to .constrained prefix*/).ToString().Equals(cid)) { return allCharacter; } } return null; } public static Character GetCharacterByZDOID(ZDOID cid) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) foreach (Character allCharacter in Character.GetAllCharacters()) { ZDOID zDOID = allCharacter.GetZDOID(); if (((ZDOID)(ref zDOID)).Equals(cid)) { return allCharacter; } } return null; } public static ZNetPeer GetPeerByRPC(ZRpc rpc) { foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (peer.m_rpc == rpc) { return peer; } } return null; } public static List GetGameObjectsOfType(Type t) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) List list = new List(); Object[] array = Object.FindObjectsByType(t, (FindObjectsSortMode)0); foreach (Object val in array) { list.Add(((Component)val).gameObject); } return list; } public static GameObject GetClosestGameObjectOfType(Type t, Vector3 point, float radius) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return GetGameObjectsOfTypeInRangeByDistance(t, point, radius)?[0]; } public static List GetGameObjectsOfTypeInRangeByDistance(Type t, Vector3 point, float radius) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) List> list = new List>(); List gameObjectsOfTypeInRange = GetGameObjectsOfTypeInRange(t, point, radius); if (gameObjectsOfTypeInRange.Count > 0) { foreach (GameObject item in gameObjectsOfTypeInRange) { list.Add(new KeyValuePair(item, Vector3.Distance(item.transform.position, point))); } list.Sort((KeyValuePair pair1, KeyValuePair pair2) => pair1.Value.CompareTo(pair2.Value)); return list.ConvertAll((KeyValuePair x) => x.Key); } return null; } public static List GetGameObjectsOfTypeInRange(Type t, Vector3 point, float radius) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) float radiusSq = radius * radius; return GetGameObjectsOfType(t).Where(delegate(GameObject x) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: 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) Vector3 val = x.transform.position - point; return ((Vector3)(ref val)).sqrMagnitude < radiusSq; }).ToList(); } public static float GetPointDepth(Vector3 p) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) return ZoneSystem.instance.m_waterLevel - GetSolidHeight(p); } public static List GetDelimitedStringAsList(string delimitedString, char delimiter) { List list = new List(); string[] array = delimitedString.Split(new char[1] { delimiter }, StringSplitOptions.RemoveEmptyEntries); foreach (string text in array) { list.Add(text.Trim()); } return list; } public static float GetSolidHeight(Vector3 p) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) int solidRayMask = ZoneSystem.instance.m_solidRayMask; float result = 0f; p.y += 1000f; RaycastHit val = default(RaycastHit); if (Physics.Raycast(p, Vector3.down, ref val, 2000f, solidRayMask) && !Object.op_Implicit((Object)(object)((RaycastHit)(ref val)).collider.attachedRigidbody)) { result = ((RaycastHit)(ref val)).point.y; } return result; } public static Transform FindChild(Transform aParent, string aName) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown foreach (Transform item in aParent) { Transform val = item; if (((Object)val).name == aName) { return val; } Transform val2 = FindChild(val, aName); if ((Object)(object)val2 != (Object)null) { return val2; } } return null; } public static Transform FindParent(Transform go) { while ((Object)(object)go.parent != (Object)null) { go = go.parent; } return go; } public static bool IsPrefabInScene(string prefabName) { return IsPrefabInScene(StringExtensionMethods.GetStableHashCode(prefabName)); } public static bool IsPrefabInScene(int prefabHash) { ZNetScene instance = ZNetScene.instance; return (Object)(object)((instance != null) ? instance.GetPrefab(prefabHash) : null) != (Object)null; } public static bool TryGetPrefab(string prefabName, out GameObject prefab) { return TryGetPrefab(StringExtensionMethods.GetStableHashCode(prefabName), out prefab); } public static bool TryGetPrefab(int prefabHash, out GameObject prefab) { prefab = GetPrefabByHash(prefabHash); return (Object)(object)prefab != (Object)null; } public static GameObject GetPrefabByHash(int prefabHash) { GameObject val = null; Logging logger = Logging.GetLogger(); ZNetScene instance = ZNetScene.instance; val = ((instance != null) ? instance.GetPrefab(prefabHash) : null); if ((Object)(object)val != (Object)null) { logger.Debug("Found prefab in Scene"); return val; } val = ObjectDB.instance.GetItemPrefab(prefabHash); if ((Object)(object)val != (Object)null) { logger.Debug("Found prefab in ObjectDB"); return val; } logger.Debug("No prefab found"); return val; } public static GameObject GetPrefab(int prefabHash) { return GetPrefabByHash(prefabHash); } public static GameObject GetPrefab(string prefabName) { return GetPrefabByHash(StringExtensionMethods.GetStableHashCode(prefabName)); } public static void LoadPrefabInScene(GameObject prefab) { int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)prefab).name); if ((Object)(object)ZNetScene.instance != (Object)null && !ZNetScene.instance.m_namedPrefabs.ContainsKey(stableHashCode)) { ZNetScene.instance.m_prefabs.Add(prefab); ZNetScene.instance.m_namedPrefabs[stableHashCode] = prefab; } } public static GameObject SpawnObject(string prefabName, Vector3 position, Quaternion rotation, bool persist = true) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (TryGetPrefab(prefabName, out var prefab)) { return SpawnObject(prefab, position, rotation, persist); } return null; } public static GameObject SpawnObject(GameObject prefab, Vector3 position, Quaternion rotation, bool persist = true) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) LoadPrefabInScene(prefab); GameObject val = Object.Instantiate(prefab, position, rotation); ZNetView val2 = default(ZNetView); if (persist && val.TryGetComponent(ref val2)) { val2.GetZDO().Persistent = true; } return val; } public static string SerializeFromDictionary(string delimp, string delimc, IDictionary dict) { if (dict == null) { return null; } IEnumerable values = dict.Select(delegate(KeyValuePair kvp) { KeyValuePair keyValuePair = kvp; string? obj = keyValuePair.Key?.ToString(); string text = delimc; keyValuePair = kvp; return obj + text + keyValuePair.Value; }); return string.Join(delimp, values); } public static void DeserializeToDictionary(string serializedString, string delimp, string delimc, ref IDictionary dict) { if (dict == null) { return; } dict.Clear(); string[] separator = new string[1] { delimp }; string[] separator2 = new string[1] { delimc }; string[] array = serializedString.Split(separator, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(separator2, StringSplitOptions.RemoveEmptyEntries); if (array2.Length == 2) { dict.Add(TypedValue(array2[0]), TypedValue(array2[1])); } } } public static FileSystemWatcher CreateFileWatcher(string fullPath, FileSystemEventHandler handler) { string fileName = Path.GetFileName(fullPath); FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(fullPath.Substring(0, fullPath.Length - fileName.Length), fileName); fileSystemWatcher.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.Size | NotifyFilters.LastWrite | NotifyFilters.CreationTime; fileSystemWatcher.Changed += handler; fileSystemWatcher.Created += handler; fileSystemWatcher.IncludeSubdirectories = false; fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher.EnableRaisingEvents = true; return fileSystemWatcher; } public static T TypedValue(object a) { return (T)Convert.ChangeType(a, typeof(T)); } public static float TimeAdjustedRamp(float maxValue, float duration, float elapsedTime, float pctFromStartRise, float pctFromEndFall) { float num = elapsedTime / duration; if (num <= pctFromStartRise) { return maxValue * (num / pctFromStartRise); } if (num >= 1f - pctFromEndFall) { return maxValue * ((1f - num) / pctFromEndFall); } return maxValue; } public static Color IntToColor(int rgba) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) float num = (float)((rgba >> 16) & 0xFF) / 255f; float num2 = (float)((rgba >> 8) & 0xFF) / 255f; float num3 = (float)(rgba & 0xFF) / 255f; float num4 = (float)((rgba >> 24) & 0xFF) / 255f; return new Color(num, num2, num3, num4); } public static bool CopyComponentToGameObject(Component original, ref GameObject destination) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown Logging logger = Logging.GetLogger(); Type type = ((object)original).GetType(); logger.Debug($"Original Type is {type}"); GameObject obj = destination; logger.Debug("Destination GameObject " + ((obj != null) ? ((Object)obj).name : null)); Component val = destination.GetComponent(type); if (!Object.op_Implicit((Object)(object)val)) { val = destination.AddComponent(type); } if (!Object.op_Implicit((Object)(object)val)) { logger.Debug("Destination component is null"); return false; } Component val2 = (Component)Activator.CreateInstance(type); if (!Object.op_Implicit((Object)(object)val2)) { logger.Debug("Destination component is null"); return false; } if (!Object.op_Implicit((Object)(object)val2)) { logger.Debug("Boxed component is null"); return false; } FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { fieldInfo.SetValue(val2, fieldInfo.GetValue(original)); } val = val2; return true; } public static bool CopyObject(object original, object target) { Logging logger = Logging.GetLogger(); Type type = original.GetType(); Type type2 = target.GetType(); if (type == null) { logger.Warning("Copy Object: Source object is null"); return false; } if (type2 == null) { logger.Warning("Copy Object: Destination object is null"); return false; } if (type2 != type) { logger.Warning("Copy Object: Source and destination components are different types"); return false; } FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { fieldInfo.SetValue(target, fieldInfo.GetValue(original)); } return true; } } } namespace neobotics.ValheimMods { internal class Cfg { public static ConfigEntry floatSize; public static DelegatedConfigEntry useRodBonus; public static DelegatedConfigEntry noBaseRestriction; public static DelegatedConfigEntry debugLevel; public static DelegatedConfigEntry enableSerpentSpawn; public static DelegatedConfigEntry enableLeviathanSpawn; public static DelegatedConfigEntry craftableTackle; public static DelegatedConfigEntry genericBaitChance; public static DelegatedConfigEntry noCauldronRawFish; private static Logging Log; public static void BepInExConfig(BaseUnityPlugin _instance, string modName) { //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Expected O, but got Unknown //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Expected O, but got Unknown Log = Logging.GetLogger(Logging.LogLevels.Info, modName); ServerConfiguration.Instance.Setup(_instance.Config, _instance); debugLevel = new DelegatedConfigEntry(ChangeLogging); debugLevel.ConfigEntry = _instance.Config.Bind("Utility", "LogLevel", Logging.LogLevels.Info, "Controls the level of information contained in the log"); Log.LogLevel = debugLevel.Value; useRodBonus = new DelegatedConfigEntry(useServerDelegate: true); useRodBonus.ConfigEntry = _instance.Config.Bind("General", "UseRodBonus", true, "Allows upgraded fishing rods to add to the fishing skill. Default=true"); floatSize = _instance.Config.Bind("General", "FloatSize", 1, new ConfigDescription("The size of the float. Increase to make the float larger and more visible in the water. Default is 1 (the standard Valheim float size)", (AcceptableValueBase)(object)new AcceptableValueRange(1, 3), Array.Empty())); noBaseRestriction = new DelegatedConfigEntry(useServerDelegate: true); noBaseRestriction.ConfigEntry = _instance.Config.Bind("General", "NoBaseRestrictedSpawn", false, "Set True to enable fish to spawn near Player base structures such as workbenches and campfires. Set False for Valheim's normal restriction."); enableSerpentSpawn = new DelegatedConfigEntry(useServerDelegate: true); enableSerpentSpawn.ConfigEntry = _instance.Config.Bind("General", "EnableSerpentSpawn", true, "Set True to enable occasional serpent spawning when fishing in the Ocean."); enableLeviathanSpawn = new DelegatedConfigEntry(useServerDelegate: true); enableLeviathanSpawn.ConfigEntry = _instance.Config.Bind("General", "EnableLeviathanSpawn", true, "Set True to enable rare Leviathan spawning when fishing in the Ocean."); craftableTackle = new DelegatedConfigEntry(useServerDelegate: true); craftableTackle.ConfigEntry = _instance.Config.Bind("General", "EnableCraftableTackle", true, "Set True to enable crafting and upgrading (adds to fishing skill) of fishing rods, and craftable bait."); genericBaitChance = new DelegatedConfigEntry(useServerDelegate: true); genericBaitChance.ConfigEntry = _instance.Config.Bind("General", "RegularBaitHookChance", 0, new ConfigDescription("Provides a percent chance for basic fishing bait to hook any fish regardless of bait preference. Default is 0. 100 would provide the same chance as the biome-specific bait.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); noCauldronRawFish = new DelegatedConfigEntry(ReelySpecTackleLure.ChangeRawFish, useServerDelegate: true); noCauldronRawFish.ConfigEntry = _instance.Config.Bind("General", "SkinFishInField", false, "Set True to allow skinning and cleaning fish in the field without a cauldron. Appears in the non-station crafting menu."); ServerConfiguration.Instance.CreateConfigWatcher(); } public static void ChangeLogging(object s, EventArgs e) { SettingChangedEventArgs e2 = (SettingChangedEventArgs)(object)((e is SettingChangedEventArgs) ? e : null); Log.Debug($"ChangeLog {e2.ChangedSetting.Definition.Key} to {e2.ChangedSetting.BoxedValue}"); Log.LogLevel = debugLevel.Value; } } public class FishingBait : ICustomRecipe { public bool CanBeRepaired => false; public string Item => "$item_fishingbait"; public float MaxDurability => 1f; public int MaxQuality => 1; public string RecipeName => "Recipe_FishingBait"; public string Prefab => "FishingBait"; public bool RecoverPieces => false; public bool UseDurability => false; } internal class FishingRod : ICustomRecipe { public bool CanBeRepaired => true; public string Item => "$item_fishingrod"; public float MaxDurability => 100f; public int MaxQuality => 4; public string RecipeName => "Recipe_FishingRod"; public string Prefab => "FishingRod"; public bool RecoverPieces => true; public bool UseDurability => true; } public interface ICustomRecipe { string Item { get; } string RecipeName { get; } string Prefab { get; } bool CanBeRepaired { get; } int MaxQuality { get; } float MaxDurability { get; } bool UseDurability { get; } bool RecoverPieces { get; } } internal interface IMod { } [Serializable] public class RecipeDo { public string Name { get; set; } public int Amount { get; set; } public bool Enabled { get; set; } public string CraftingStation { get; set; } public int MinStationLevel { get; set; } public List Requirements { get; set; } } public static class RecipeReader { private static string defaultJson = "\r\n{\r\n \"RecipeList\": [\r\n {\r\n \"Name\": \"Recipe_FishingRod\",\r\n\t \"Amount\": 1,\r\n\t \"Enabled\": true,\r\n\t \"CraftingStation\": \"piece_workbench\",\r\n\t \"MinStationLevel\": 2,\r\n \"Requirements\": [\r\n {\r\n \"Item\": \"LinenThread\",\r\n \"Amount\": 0,\r\n\t\t \"AmountPerLevel\": 10\r\n },\r\n {\r\n \"Item\": \"FineWood\",\r\n \"Amount\": 10,\r\n\t\t \"AmountPerLevel\": 5\r\n }\r\n ]\r\n },\r\n {\r\n \"Name\": \"Recipe_FishingBait\",\r\n\t \"Amount\": 20,\r\n\t \"Enabled\": true,\r\n\t \"CraftingStation\": \"piece_cauldron\",\r\n\t \"MinStationLevel\": 2,\r\n \"Requirements\": [\r\n {\r\n \"Item\": \"Entrails\",\r\n \"Amount\": 10\r\n },\r\n {\r\n \"Item\": \"Feathers\",\r\n \"Amount\": 5\r\n }\r\n ]\r\n }\r\n ]\r\n}\r\n"; private static Logging mLog = Logging.GetLogger(); public static Recipes ReadRecipes(string filePath) { mLog.Debug("ReadRecipes"); Recipes recipes = null; try { return JsonConvert.DeserializeObject(File.ReadAllText(Path.Combine(filePath, "RSTLrecipes.json"))); } catch (Exception) { mLog.Warning("Can't read RSTLrecipies.json. Using default config."); return JsonConvert.DeserializeObject(defaultJson); } } } public class Recipes { public List RecipeList { get; set; } } internal class RecipieMaker { private static Logging mLog = Logging.GetLogger(); public static void InitFishingRecipes(Recipes recipes) { ICustomRecipe customRecipe; foreach (RecipeDo recipe in recipes.RecipeList) { string name = recipe.Name; if (!(name == "Recipe_FishingRod")) { if (!(name == "Recipe_FishingBait")) { mLog.Error("Recipe " + recipe.Name + " not supported"); break; } customRecipe = new FishingBait(); } else { customRecipe = new FishingRod(); } Recipe val = ObjectDB.instance.m_recipes.Find((Recipe x) => ((Object)x).name.Equals(customRecipe.RecipeName)); if ((Object)(object)val == (Object)null) { mLog.Debug(customRecipe.RecipeName + " recipe not found. Adding..."); val = ScriptableObject.CreateInstance(); if (ConfigFishingRecipe(ref val, customRecipe, recipe)) { ObjectDB.instance.m_recipes.Add(val); } else { mLog.Error("Failed to add recipe " + customRecipe.RecipeName); } } else { mLog.Debug(customRecipe.RecipeName + " recipe already exists"); } } } public static bool ConfigFishingRecipe(ref Recipe recipe, ICustomRecipe customRecipe, RecipeDo rdo) { //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Expected O, but got Unknown GameObject prefab = ZNetScene.instance.GetPrefab(rdo.CraftingStation); if ((Object)(object)prefab == (Object)null) { mLog.Error("Crafting station " + rdo.CraftingStation + " prefab is missing"); return false; } CraftingStation val = default(CraftingStation); if (!prefab.TryGetComponent(ref val)) { mLog.Error("Crafting station component " + rdo.CraftingStation + " is missing"); return false; } GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(customRecipe.Prefab); if ((Object)(object)itemPrefab == (Object)null) { mLog.Error("Item " + customRecipe.Prefab + " prefab is missing"); return false; } ItemDrop val2 = default(ItemDrop); if (!itemPrefab.TryGetComponent(ref val2)) { mLog.Error("ItemDrop " + customRecipe.Prefab + " component is missing"); return false; } List requirements = rdo.Requirements; Requirement[] array = (Requirement[])(object)new Requirement[requirements.Count]; ItemDrop val3 = default(ItemDrop); for (int i = 0; i < requirements.Count; i++) { mLog.Debug("Getting requirement " + requirements[i].Item); GameObject itemPrefab2 = ObjectDB.instance.GetItemPrefab(requirements[i].Item); if ((Object)(object)itemPrefab2 == (Object)null) { mLog.Error("Requirement " + requirements[i].Item + " prefab is missing"); return false; } if (!itemPrefab2.TryGetComponent(ref val3)) { mLog.Error("ItemDrop " + requirements[i].Item + " component is missing"); return false; } mLog.Debug($"Requirement item {i} {val3.m_itemData.m_shared.m_name}"); array[i] = new Requirement(); array[i].m_amount = requirements[i].Amount; array[i].m_recover = customRecipe.RecoverPieces; array[i].m_amountPerLevel = requirements[i].AmountPerLevel; array[i].m_resItem = val3; mLog.Debug($"Amount {array[i].m_amount}"); mLog.Debug($"Amount per level {array[i].m_amountPerLevel}"); mLog.Debug($"Recover {array[i].m_recover}"); } val2.m_itemData.m_shared.m_canBeReparied = customRecipe.CanBeRepaired; val2.m_itemData.m_shared.m_maxQuality = customRecipe.MaxQuality; val2.m_itemData.m_shared.m_maxDurability = customRecipe.MaxDurability; val2.m_itemData.m_shared.m_useDurability = customRecipe.UseDurability; recipe.m_craftingStation = val; recipe.m_repairStation = (customRecipe.CanBeRepaired ? val : null); recipe.m_amount = rdo.Amount; recipe.m_enabled = rdo.Enabled; recipe.m_minStationLevel = rdo.MinStationLevel; recipe.m_item = val2; recipe.m_resources = array; ((Object)recipe).name = customRecipe.RecipeName; return true; } } [BepInPlugin("neobotics.valheim_mod.reelyspectacklelure", "ReelySpecTackleLure", "0.2.6")] [BepInProcess("valheim.exe")] [BepInProcess("valheim_server.exe")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class ReelySpecTackleLure : BaseUnityPlugin { [HarmonyPatch(typeof(Skills), "GetSkillFactor")] private static class Skills_GetSkillFactor_Patch { private static bool Prefix(Skills __instance, SkillType skillType, Player ___m_player, ref float __result) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_0014: Unknown result type (might be due to invalid IL or missing references) if ((int)skillType != 104 || !Cfg.useRodBonus.Value) { return true; } float skillLevel = __instance.GetSkillLevel(skillType); ItemData value = Traverse.Create((object)___m_player).Field("m_rightItem").GetValue(); if (value == null) { return true; } float num = (float)(value.m_quality - 1) * 5f; __result = Mathf.Clamp01((skillLevel + num) / 100f); if (Log.LogLevel >= Logging.LogLevels.Trace) { Log.Trace($"Fishing Skill with Rod Bonus {__result}"); } return false; } } [HarmonyPatch(typeof(FejdStartup), "SetupObjectDB")] private class FejdStartup_SetupObjectDB_Patch { [HarmonyPriority(100)] private static void Postfix(FejdStartup __instance, GameObject ___m_objectDBPrefab) { Log.Debug("FejdStartup SetupObjectDB postfix"); GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("FishingRod"); AdjustFishingRod((itemPrefab == null) ? null : itemPrefab.GetComponent()?.m_itemData); } } [HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData) })] private static class Inventory_AddItem_Patch { private static void Postfix(Inventory __instance, ItemData item) { if (item.m_shared.m_name.Equals("$item_fishingrod")) { Log.Debug($"Adding fishing rod of quality {item.m_quality}"); } } } [HarmonyPatch(typeof(Fish), "TestBate")] private static class Fish_TestBate_Patch { [HarmonyPostfix] private static void Fish_TestBate_Postfix(Fish __instance, FishingFloat ff, ref bool __result) { if (!__result && Cfg.genericBaitChance.Value > 0) { string bait = ff.GetBait(); Log.Debug("Fish testing " + bait); if (bait == "FishingBait" && Random.value < (float)Cfg.genericBaitChance.Value / 100f) { Log.Debug("Nibbling regular bait"); __result = true; } else { Log.Debug("Ignoring regular bait"); } } } } [HarmonyPatch(typeof(FishingFloat), "Setup")] private static class FishingFloat_Setup_Patch { private static void Postfix(ref FishingFloat __instance) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) Log.Debug("FishingFloat Setup Postfix"); Transform transform = ((Component)__instance).gameObject.transform; transform.localScale *= (float)(Cfg.floatSize.Value + 1) / 2f; Cast(((Component)__instance).transform.position); } } [HarmonyPatch(typeof(SpawnSystem), "IsSpawnPointGood")] private static class SpawnSystem_SpawnPoint_Patch { private static void Prefix(SpawnData spawn, ref Vector3 spawnPoint, out bool __state) { __state = spawn.m_insidePlayerBase; if (spawn != null && Cfg.noBaseRestriction.Value && spawn.m_name.ToLower().Contains("fish")) { Log.Trace("Setting fish spawner base restriction off"); spawn.m_insidePlayerBase = true; } } private static void Postfix(bool __result, SpawnData spawn, ref Vector3 spawnPoint, bool __state) { spawn.m_insidePlayerBase = __state; } } [HarmonyPatch(typeof(PlayerProfile), "LoadPlayerData")] private class PlayerProfile_LoadPlayerData_Patch { private static void Postfix(PlayerProfile __instance, Player player) { Log.Debug("PlayerProfile_LoadPlayerData_Patch"); if ((Object)(object)player == (Object)(object)Player.m_localPlayer && Cfg.craftableTackle.Value) { RecipieMaker.InitFishingRecipes(rstlRecipes); SetRawFishStation(); } } } internal const string PLUGIN_NAME = "ReelySpecTackleLure"; internal const string PLUGIN_VERSION = "0.2.6"; internal const string PLUGIN_GUID = "neobotics.valheim_mod.reelyspectacklelure"; private static ReelySpecTackleLure _modinstance; public static Logging Log; private readonly Harmony harmony = new Harmony("neobotics.valheim_mod.reelyspectacklelure"); private static Random rand = new Random(); private static float castSpawnDelaySeconds = 10f; private static int serpentSpawnChanceNight = 15; private static int serpentSpawnChanceDay = 25; private static int leviathanSpawnChance = 100; private static CraftingStation rawFishStation = null; public static GameObject serpentPrefab = null; public static GameObject leviathanPrefab = null; public const string rodPrefabName = "FishingRod"; public const string rodItemName = "$item_fishingrod"; private const string rodDescription = "A craftable fishing rod."; private static bool canSpawn = true; public static bool testingFishSpawnLocation = false; internal static string s_resourceFolder; public static Recipes rstlRecipes = null; public static ReelySpecTackleLure GetInstance() { return _modinstance; } private void Awake() { _modinstance = this; ConfigureMod(); harmony.PatchAll(Assembly.GetExecutingAssembly()); Log.Info("0.2.6 Awake"); } private void ConfigureMod() { Cfg.BepInExConfig((BaseUnityPlugin)(object)_modinstance, "ReelySpecTackleLure"); Log = Logging.GetLogger(); s_resourceFolder = ModResourceBootstrap.InitializeModResources(typeof(ReelySpecTackleLure), "ReelySpecTackleLure"); rstlRecipes = RecipeReader.ReadRecipes(s_resourceFolder); } internal static void ChangeRawFish(object s, EventArgs e) { SettingChangedEventArgs e2 = (SettingChangedEventArgs)(object)((e is SettingChangedEventArgs) ? e : null); Log.Debug($"ChangeRawFish {e2.ChangedSetting.Definition.Key} to {e2.ChangedSetting.BoxedValue}"); SetRawFishStation(); } internal static void SetRawFishStation() { Recipe val = ObjectDB.instance.m_recipes.Find((Recipe x) => ((Object)x).name.Equals("Recipe_Fish1")); if ((Object)(object)val != (Object)null) { if ((Object)(object)rawFishStation == (Object)null) { rawFishStation = val.m_craftingStation; } val.m_craftingStation = (Cfg.noCauldronRawFish.Value ? null : rawFishStation); if ((Object)(object)Player.m_localPlayer != (Object)null) { Player.m_localPlayer.UpdateKnownRecipesList(); } } } private void OnDestroy() { harmony.UnpatchSelf(); } private static void Cast(Vector3 position) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Invalid comparison between Unknown and I4 //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) Log.Debug("Cast"); if ((int)Player.m_localPlayer.GetCurrentBiome() == 256) { Log.Debug($"Can spawn {canSpawn}"); if ((Object)(object)serpentPrefab == (Object)null) { serpentPrefab = ZNetScene.instance.GetPrefab("Serpent"); } if ((Object)(object)leviathanPrefab == (Object)null) { leviathanPrefab = ZNetScene.instance.GetPrefab("Leviathan"); } int playersInRangeXZ = Player.GetPlayersInRangeXZ(((Component)Player.m_localPlayer).transform.position, 100f); Log.Debug($"Players within range: {playersInRangeXZ}"); if (canSpawn && (Object)(object)serpentPrefab != (Object)null && Cfg.enableSerpentSpawn.Value) { if (rand.Next(EnvMan.IsNight() ? (serpentSpawnChanceNight * playersInRangeXZ) : (serpentSpawnChanceDay * playersInRangeXZ)) == 0) { ((MonoBehaviour)_modinstance).StartCoroutine(_modinstance.Co_DeepSeaSpawn(position, serpentPrefab, 3f)); } } else if (canSpawn && (Object)(object)leviathanPrefab != (Object)null && Cfg.enableLeviathanSpawn.Value && rand.Next(leviathanSpawnChance * playersInRangeXZ) == 0) { ((MonoBehaviour)_modinstance).StartCoroutine(_modinstance.Co_DeepSeaSpawn(position, leviathanPrefab, 10f)); } } if (canSpawn) { ((MonoBehaviour)_modinstance).StartCoroutine(_modinstance.Co_SpawnThrottle()); } } private IEnumerator Co_SpawnThrottle() { Log.Trace("Co_SpawnThrottle"); canSpawn = false; Log.Trace($"Spawn {canSpawn} {DateTime.Now}"); yield return (object)new WaitForSeconds(castSpawnDelaySeconds); canSpawn = true; Log.Trace($"Spawn {canSpawn} {DateTime.Now}"); } private IEnumerator Co_DeepSeaSpawn(Vector3 position, GameObject prefab, float depth) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) Log.Trace("Co_DeepSeaSpawn"); yield return (object)new WaitForSeconds((float)rand.NextDouble() * 5f + 3f); if (!(Utils.GetPointDepth(position) > 12f)) { yield break; } Vector3 position2 = position + new Vector3(0f, 0f - depth, 0f); Character val = default(Character); if (Utils.SpawnObject(prefab, position2, Quaternion.identity).TryGetComponent(ref val) && rand.Next(EnvMan.IsNight() ? 5 : 10) == 0) { if (rand.Next(EnvMan.IsNight() ? 5 : 10) == 0) { val.SetLevel(3); Transform transform = ((Component)val).transform; transform.localScale *= 1.5f; } else { val.SetLevel(2); Transform transform2 = ((Component)val).transform; transform2.localScale *= 1.25f; } } } private static void AdjustFishingRod(ItemData item) { if (item == null) { Log.Error("Fishing Rod item not found"); return; } item.m_shared.m_canBeReparied = true; item.m_shared.m_useDurability = true; item.m_shared.m_maxQuality = 4; item.m_shared.m_description = "A craftable fishing rod"; Log.Debug("Adjusted Fishing Rod to be craftable and upgradeable."); } } [Serializable] public class RequirementDo { public string Item { get; set; } public int Amount { get; set; } public int AmountPerLevel { get; set; } public RequirementDo(string i, int a, int apl) { Item = i; Amount = a; AmountPerLevel = apl; } } internal class SkillTester { [HarmonyPatch(typeof(Skills), "Save")] [HarmonyPriority(800)] private static class Skills_Save_Patch { private static void Prefix(Skills __instance, ZPackage pkg) { ReelySpecTackleLure.Log.Trace("Skills Save Prefix"); } private static void Postfix(Skills __instance, ZPackage pkg) { ReelySpecTackleLure.Log.Trace("Skills Save Postfix"); } } [HarmonyPatch(typeof(Player), "Save")] [HarmonyPriority(800)] private static class Player_Save_Patch { private static void Prefix(Player __instance, ZPackage pkg) { ReelySpecTackleLure.Log.Trace("Player Save Prefix"); } private static void Postfix(Player __instance, ZPackage pkg) { ReelySpecTackleLure.Log.Trace("Player Save Postfix"); } } [HarmonyPatch(typeof(PlayerProfile), "SavePlayerData")] [HarmonyPriority(800)] private static class PlayerProfile_SavePlayerData_Patch { private static void Prefix(Player __instance) { ReelySpecTackleLure.Log.Trace("PlayerProfile SavePlayerData Prefix"); } private static void Postfix(Player __instance) { ReelySpecTackleLure.Log.Trace("PlayerProfile SavePlayerData Postfix"); } } [HarmonyPatch(typeof(Game), "SavePlayerProfile")] [HarmonyPriority(800)] private static class Game_SavePlayerProfile_Patch { private static void Prefix(bool setLogoutPoint) { ReelySpecTackleLure.Log.Trace("Game SavePlayerProfile Prefix"); } private static void Postfix(bool setLogoutPoint) { ReelySpecTackleLure.Log.Trace("Game SavePlayerProfile Postfix"); } } } }