Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Luckstone v0.1.0
Luckstone.dll
Decompiled 3 days 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.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 UnityEngine; using UnityEngine.Networking; using neobotics.ModSdk; using neobotics.ValheimMods; [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("Luckstone")] [assembly: AssemblyConfiguration("Deploy")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+fba5a770148283f326e7870607ac144d786a0428")] [assembly: AssemblyProduct("Luckstone")] [assembly: AssemblyTitle("Luckstone")] [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<ConfigEntryBase> 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<object, string> ObjToStr; public Func<string, object> StrToObj; } namespace neobotics.ValheimMods { public class Localizer { [HarmonyPatch(typeof(Localization), "SetupLanguage")] private static class Localization_SetupLanguage_Patch { [HarmonyPostfix] private static void Postfix(Localization __instance) { //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown try { if (string.IsNullOrEmpty(LocFolder)) { return; } string selectedLanguage = __instance.GetSelectedLanguage(); string path = Path.Combine(LocFolder, selectedLanguage + ".loc"); if (!File.Exists(path)) { Logging.Instance.Warning("[" + ModName + "] Localization file not found for " + selectedLanguage + ", trying English fallback"); path = Path.Combine(LocFolder, "English.loc"); if (!File.Exists(path)) { Logging.Instance.Warning("[" + ModName + "] English fallback localization file not found"); return; } } TextAsset val = new TextAsset(File.ReadAllText(path)); __instance.LoadCSV(val, selectedLanguage); Logging.Instance.Info("[" + ModName + "] Loaded localization file: " + Path.GetFileName(path)); } catch (Exception ex) { Logging.Instance.Error("Localization load failed: " + ex); } } } internal static string ModName; internal static string LocFolder; public Localizer(string modName) { ModName = modName; LocFolder = ConfigFolderHelper.GetOrCreateModConfigFolder(modName); } public string Localize(string key) { return Localization.instance.Localize(key); } } public class Prefabricator { [HarmonyPatch(typeof(ZNetScene), "Awake")] public static class ZNetScene_Awake_Patch { [HarmonyPrefix] private static void Prefix(ZNetScene __instance) { foreach (Prefabricator item in Registry) { if (!((Object)(object)item.Prefab == (Object)null) && !__instance.m_prefabs.Contains(item.Prefab)) { __instance.m_prefabs.Add(item.Prefab); } } } [HarmonyPostfix] private static void Postfix(ZNetScene __instance) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) foreach (Prefabricator item in Registry) { if ((Object)(object)item.Prefab != (Object)null && item.TintColor.HasValue) { ApplyTintToMaterial(item.Prefab, item.TintColor.Value); } } } } [HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")] public static class ObjectDB_CopyOtherDB_Patch { [HarmonyPostfix] public static void ObjectDB_CopyOtherDB_Postfix(ObjectDB __instance) { foreach (Prefabricator item in Registry) { GameObject itemPrefab = __instance.GetItemPrefab(item.NewPrefabName); if ((Object)(object)itemPrefab != (Object)null) { item.Prefab = itemPrefab; continue; } GameObject itemPrefab2 = __instance.GetItemPrefab(item.PrototypeName); if ((Object)(object)itemPrefab2 == (Object)null) { Log.Debug("Can't find prototype " + item.PrototypeName); continue; } GameObject val = Object.Instantiate<GameObject>(itemPrefab2, GetAssetContainer().transform); ((Object)val).name = item.NewPrefabName; ItemDrop component = val.GetComponent<ItemDrop>(); if ((Object)(object)component != (Object)null) { component.m_itemData = component.m_itemData.Clone(); SharedData val2 = CopySharedData(component.m_itemData.m_shared); val2.m_name = item.NewItemName; val2.m_description = item.Description; component.m_itemData.m_shared = val2; component.m_itemData.m_dropPrefab = val; item.ConfigureItem?.Invoke(component.m_itemData); } if (!__instance.m_items.Contains(val)) { __instance.m_items.Add(val); } __instance.m_itemByHash[StringExtensionMethods.GetStableHashCode(((Object)val).name)] = val; if (component?.m_itemData?.m_shared != null) { __instance.m_itemByData[component.m_itemData.m_shared] = val; } item.Prefab = val; } } } [HarmonyPatch(typeof(ItemDrop), "OnCreateNew", new Type[] { typeof(GameObject) })] private static class ItemDrop_OnCreateNew_Patch { [HarmonyPrefix] private static void Prefix(ItemDrop __instance, GameObject go) { ItemDrop val = default(ItemDrop); foreach (Prefabricator item in Registry) { if (!((Object)(object)item.Prefab == (Object)null) && ((Object)go).name.StartsWith(item.NewPrefabName) && ZNetScene.instance.m_namedPrefabs.ContainsKey(StringExtensionMethods.GetStableHashCode(item.NewPrefabName)) && go.TryGetComponent<ItemDrop>(ref val)) { val.m_itemData.m_dropPrefab = item.Prefab; } } } } [HarmonyPatch(typeof(ObjectDB), "Awake")] public static class ObjectDB_Awake_Patch { [HarmonyPrefix] public static void ObjectDB_Awake_Prefix(ObjectDB __instance) { foreach (Prefabricator item in Registry) { if (!((Object)(object)item.Prefab == (Object)null) && !__instance.m_items.Contains(item.Prefab)) { __instance.m_items.Add(item.Prefab); } } } } internal static readonly List<Prefabricator> Registry = new List<Prefabricator>(); private static GameObject s_assetContainer; private static Logging Log = Logging.Instance; public string NewPrefabName { get; } public string PrototypeName { get; } public string NewItemName { get; } public string Description { get; } public GameObject Prefab { get; private set; } public Action<ItemData> ConfigureItem { get; set; } public Color? TintColor { get; set; } internal static GameObject GetAssetContainer() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown if ((Object)(object)s_assetContainer == (Object)null) { s_assetContainer = new GameObject("CustomAssets"); s_assetContainer.SetActive(false); Object.DontDestroyOnLoad((Object)(object)s_assetContainer); } return s_assetContainer; } public Prefabricator(string newPrefabName, string prototypeName, string newItemName, string description, Action<ItemData> configureItem = null) { NewPrefabName = newPrefabName; PrototypeName = prototypeName; NewItemName = newItemName; Description = description; ConfigureItem = configureItem; Registry.Add(this); } public static SharedData CopySharedData(SharedData source) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Expected O, but got Unknown if (source == null) { return null; } SharedData val = new SharedData(); Type? typeFromHandle = typeof(SharedData); BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; FieldInfo[] fields = typeFromHandle.GetFields(bindingAttr); foreach (FieldInfo fieldInfo in fields) { object value = fieldInfo.GetValue(source); if (value == null) { fieldInfo.SetValue(val, null); continue; } if (value is Array array) { fieldInfo.SetValue(val, array.Clone()); continue; } if (fieldInfo.FieldType.IsGenericType && fieldInfo.FieldType.GetGenericTypeDefinition() == typeof(List<>)) { object value2 = Activator.CreateInstance(fieldInfo.FieldType, value); fieldInfo.SetValue(val, value2); continue; } EffectList val2 = (EffectList)((value is EffectList) ? value : null); if (val2 != null) { EffectList val3 = new EffectList(); if (val2.m_effectPrefabs != null) { val3.m_effectPrefabs = (EffectData[])val2.m_effectPrefabs.Clone(); } fieldInfo.SetValue(val, val3); } else { Attack val4 = (Attack)((value is Attack) ? value : null); if (val4 != null) { fieldInfo.SetValue(val, val4.Clone()); } else { fieldInfo.SetValue(val, value); } } } return val; } private static Texture2D TintTexture(Texture2D origTex, Color tint) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)origTex == (Object)null) { return null; } RenderTexture temporary = RenderTexture.GetTemporary(((Texture)origTex).width, ((Texture)origTex).height, 0, (RenderTextureFormat)7, (RenderTextureReadWrite)1); Graphics.Blit((Texture)(object)origTex, temporary); RenderTexture.active = temporary; Texture2D val = new Texture2D(((Texture)origTex).width, ((Texture)origTex).height, (TextureFormat)4, false); val.ReadPixels(new Rect(0f, 0f, (float)((Texture)temporary).width, (float)((Texture)temporary).height), 0, 0); val.Apply(); RenderTexture.active = null; RenderTexture.ReleaseTemporary(temporary); Color[] pixels = val.GetPixels(); for (int i = 0; i < pixels.Length; i++) { float a = pixels[i].a; pixels[i] *= tint; pixels[i].a = a; } val.SetPixels(pixels); val.Apply(); return val; } private static void ApplyTintToMaterial(GameObject prefab, Color tint) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)prefab == (Object)null) { return; } Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { if ((Object)(object)val == (Object)null || val.sharedMaterials == null) { continue; } Material[] array = (Material[])(object)new Material[val.sharedMaterials.Length]; for (int j = 0; j < val.sharedMaterials.Length; j++) { if ((Object)(object)val.sharedMaterials[j] == (Object)null) { continue; } array[j] = new Material(val.sharedMaterials[j]); if (array[j].HasProperty("_MainTex")) { Texture texture = array[j].GetTexture("_MainTex"); Texture2D val2 = (Texture2D)(object)((texture is Texture2D) ? texture : null); if ((Object)(object)val2 != (Object)null) { array[j].SetTexture("_MainTex", (Texture)(object)TintTexture(val2, tint)); } } if (array[j].HasProperty("_Color")) { array[j].SetColor("_Color", tint); } if (array[j].HasProperty("_EmissionColor")) { array[j].SetColor("_EmissionColor", tint * 0.5f); } } val.sharedMaterials = array; } } } } namespace neobotics.ModSdk { public class AudioHelper : MonoBehaviour { private readonly Dictionary<string, AudioClip> audioClips = new Dictionary<string, AudioClip>(); private Logging logger; public void Awake() { logger = Logging.GetLogger(); logger.Debug("AudidHelper.Awake"); } public void Start() { logger.Debug("AudioHelper.Start"); ZRoutedRpc.instance.Register<Vector3, string>("NeoPlayClip", (Action<long, Vector3, string>)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<T> { private List<T> circle; private int index; public int Index => index; public CircularList(List<T> source, T startingElement) { circle = new List<T>(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<string, string> playerData; private Dictionary<string, string> Data { get; set; } public CustomDataWrapper(Dictionary<string, string> sourceData, string keyPrefix) { CustomDataWrapper customDataWrapper = this; playerData = sourceData; Data = new Dictionary<string, string>(); 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<string, string> 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<Component>(); if (componentsInChildren.Length == 0) { return; } Component[] array = componentsInChildren; foreach (Component c in array) { try { ComponentInspector(c); } catch (Exception) { } } } internal static void PrintList<T>(List<T> 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<T> : DelegatedConfigEntryBase { private ConfigEntry<T> _entry; private EventHandler rootHandler; private Action<object, EventArgs> clientDelegate; private Logging Log; public ConfigEntry<T> 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<object, EventArgs>)null, useServerDelegate) { } public DelegatedConfigEntry(Action<object, EventArgs> 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<KeyboardShortcut> 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<KeyboardShortcut> 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<KeyboardShortcut> 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<string, string> detectionSet = new Dictionary<string, string>(); private static Dictionary<string, string> unpatchMods = new Dictionary<string, string>(); public static IReadOnlyDictionary<string, string> DetectionSet => detectionSet; public static void GetDetectionSet(Dictionary<string, string> harmonyIds) { Logging logger = Logging.GetLogger(); foreach (KeyValuePair<string, string> 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<string, string> 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<Patch> 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; private bool isEmbedded; public ImageHelper(string externalFolder) : this(externalFolder, embedded: false) { } public ImageHelper(string externalFolder, bool embedded = true) { this.externalFolder = externalFolder; logger = Logging.GetLogger(); isEmbedded = embedded; } 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_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown image = null; byte[] array = null; if (isEmbedded) { Stream manifestResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(externalFolder + "." + name); if (manifestResourceStream == null) { throw new FileNotFoundException("Can't find " + name + " in " + externalFolder); } array = new byte[manifestResourceStream.Length]; manifestResourceStream.Read(array, 0, (int)manifestResourceStream.Length); } else { string text = Path.Combine(externalFolder, name); logger.Debug("Reading external file " + text); if (!File.Exists(text)) { throw new FileNotFoundException("Cannot find image " + name); } 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<KeyboardShortcut> keyAdvance; private DelegatedConfigEntry<KeyboardShortcut> keyReferse; public static InputCycler Instance { get { if (_instance == null) { _instance = new InputCycler(); } return _instance; } } private InputCycler() { } public void Init(bool useMouseWheel, DelegatedConfigEntry<KeyboardShortcut> keyAdvance, DelegatedConfigEntry<KeyboardShortcut> 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<T> { public T[] Items; } public static T[] FromJson<T>(string json) { return JsonUtility.FromJson<JsonWrapper<T>>(json).Items; } public static string ToJson<T>(T[] array) { return JsonUtility.ToJson((object)new JsonWrapper<T> { Items = array }); } public static string ToJson<T>(T[] array, bool prettyPrint) { return JsonUtility.ToJson((object)new JsonWrapper<T> { 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<LogLevels> val = s as ConfigEntry<LogLevels>; 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); string? name = pluginType.Assembly.GetName().Name; if (!Directory.Exists(orCreateModConfigFolder)) { Directory.CreateDirectory(orCreateModConfigFolder); Logging.Instance.Debug("Created subfolder layout: " + orCreateModConfigFolder); } string text = name + ".Resources."; Logging.Instance.Debug("Scanning assembly for standard prefix: " + text); ExtractResources(pluginType.Assembly, text, orCreateModConfigFolder); return orCreateModConfigFolder; } private static void ExtractResources(Assembly asm, string prefix, string targetFolder) { string[] manifestResourceNames = asm.GetManifestResourceNames(); foreach (string text in manifestResourceNames) { if (!text.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) { continue; } string text2 = text.Substring(prefix.Length); string text3 = Path.Combine(targetFolder, text2); if (File.Exists(text3)) { continue; } try { Logging.Instance.Debug("Extracting asset: " + text2 + " -> " + text3); using Stream stream = asm.GetManifestResourceStream(text); if (stream == null) { Logging.Instance.Error("Could not access resource stream for: " + text); continue; } using FileStream destination = File.Create(text3); stream.CopyTo(destination); } catch (Exception ex) { Logging.Instance.Error("Failed to unpack embedded asset " + text2 + ": " + ex.Message); } } } } 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<ZPackage>("ClientConfigReceiver." + GetPluginGuid(), (Action<ZRpc, ZPackage>)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<DelegatedConfigEntryBase> ServerDelegatedEntries = new List<DelegatedConfigEntryBase>(); 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<ZNetPeer> 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<TEnum>(string value, TEnum enumDefault) where TEnum : struct { if (Enum.TryParse<TEnum>(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<Character> 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<T>(Vector3 point, IEnumerable<T> collection, Func<T, Vector3> 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<T>(Vector3 point, IEnumerable<T> collection, Func<T, Vector3> 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<T>(Vector3 point, IEnumerable<T> collection, Func<T, Vector3> 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<T>(Vector3 point, IEnumerable<T> collection, Func<T, Vector3> 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<ItemDrop>(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<GameObject> GetGameObjectsOfType(Type t) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) List<GameObject> list = new List<GameObject>(); 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<GameObject> 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<KeyValuePair<GameObject, float>> list = new List<KeyValuePair<GameObject, float>>(); List<GameObject> gameObjectsOfTypeInRange = GetGameObjectsOfTypeInRange(t, point, radius); if (gameObjectsOfTypeInRange.Count > 0) { foreach (GameObject item in gameObjectsOfTypeInRange) { list.Add(new KeyValuePair<GameObject, float>(item, Vector3.Distance(item.transform.position, point))); } list.Sort((KeyValuePair<GameObject, float> pair1, KeyValuePair<GameObject, float> pair2) => pair1.Value.CompareTo(pair2.Value)); return list.ConvertAll((KeyValuePair<GameObject, float> x) => x.Key); } return null; } public static List<GameObject> 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<string> GetDelimitedStringAsList(string delimitedString, char delimiter) { List<string> list = new List<string>(); 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<GameObject>(prefab, position, rotation); ZNetView val2 = default(ZNetView); if (persist && val.TryGetComponent<ZNetView>(ref val2)) { val2.GetZDO().Persistent = true; } return val; } public static string SerializeFromDictionary<K, V>(string delimp, string delimc, IDictionary<K, V> dict) { if (dict == null) { return null; } IEnumerable<string> values = dict.Select(delegate(KeyValuePair<K, V> kvp) { KeyValuePair<K, V> 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<K, V>(string serializedString, string delimp, string delimc, ref IDictionary<K, V> 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<K>(array2[0]), TypedValue<V>(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<T>(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 Luckstone { internal class Cfg { public static DelegatedConfigEntry<float> resourceMagnitude; public static DelegatedConfigEntry<float> combatMagnitude; public static DelegatedConfigEntry<float> luckChance; public static DelegatedConfigEntry<float> luckDrain; public static DelegatedConfigEntry<float> dropChance; public static DelegatedConfigEntry<float> chestChance; public static DelegatedConfigEntry<bool> statusEffect; public static DelegatedConfigEntry<float> bossChance; public static DelegatedConfigEntry<bool> starScaling; public static DelegatedConfigEntry<float> rechargeTime; public static DelegatedConfigEntry<bool> showLuckPickupEffect; public static DelegatedConfigEntry<bool> displayLuckMessage; public static DelegatedConfigEntry<bool> playLuckPing; public static DelegatedConfigEntry<bool> showBonus; public static DelegatedConfigEntry<bool> mining; public static DelegatedConfigEntry<bool> woodcutting; public static DelegatedConfigEntry<bool> picking; public static DelegatedConfigEntry<bool> looting; public static DelegatedConfigEntry<bool> fishing; public static DelegatedConfigEntry<bool> damage; public static DelegatedConfigEntry<bool> attack; public static DelegatedConfigEntry<bool> crafting; public static DelegatedConfigEntry<bool> food; public static DelegatedConfigEntry<Logging.LogLevels> debugLevel; private static Logging Log; public static void BepInExConfig(BaseUnityPlugin plugin, string modName) { BepInExConfig(plugin); } public static void BepInExConfig(BaseUnityPlugin _instance) { //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Expected O, but got Unknown //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Expected O, but got Unknown //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Expected O, but got Unknown //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: 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_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Expected O, but got Unknown //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_02fe: Expected O, but got Unknown Log = Logging.Instance; ServerConfiguration.Instance.Setup(_instance.Config, _instance); debugLevel = new DelegatedConfigEntry<Logging.LogLevels>(Logging.ChangeLogging); debugLevel.ConfigEntry = _instance.Config.Bind<Logging.LogLevels>("Utility", "LogLevel", Logging.LogLevels.Info, "Controls the level of information contained in the log"); Log.LogLevel = debugLevel.Value; resourceMagnitude = new DelegatedConfigEntry<float>(useServerDelegate: true); resourceMagnitude.ConfigEntry = _instance.Config.Bind<float>("Luck", "Luck Magnitude", 1.5f, new ConfigDescription("The maximum amount of 'luck advantage' to apply to non-combat Luck Events. This is a multipier applied to random values.@", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 2f), Array.Empty<object>())); combatMagnitude = new DelegatedConfigEntry<float>(useServerDelegate: true); combatMagnitude.ConfigEntry = _instance.Config.Bind<float>("Luck", "Luck Magnitude (Combat)", 1.5f, new ConfigDescription("The maximum amount of 'luck advantage' to apply to combat Luck Events. This is a multipier applied to existing multipliers.@", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 2f), Array.Empty<object>())); luckChance = new DelegatedConfigEntry<float>(useServerDelegate: true); luckChance.ConfigEntry = _instance.Config.Bind<float>("Luck", "Luck Chance", 0.1f, new ConfigDescription("The percentage chance of you getting 'lucky'. This chance is applied to every configured Luck Event.@", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); luckDrain = new DelegatedConfigEntry<float>(useServerDelegate: true); luckDrain.ConfigEntry = _instance.Config.Bind<float>("Luck", "Luck Drain", 1f, new ConfigDescription("The amount of 'luck' drained from the Luckstone when 'lucky'.@", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), Array.Empty<object>())); rechargeTime = new DelegatedConfigEntry<float>(useServerDelegate: true); rechargeTime.ConfigEntry = _instance.Config.Bind<float>("Luck", "Luck Recharge Time", 5f, new ConfigDescription("The amount of time a Luckstone takes to recover before it can apply luck again (in seconds).@", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 60f), Array.Empty<object>())); dropChance = new DelegatedConfigEntry<float>(useServerDelegate: true); dropChance.ConfigEntry = _instance.Config.Bind<float>("Luckstone", "Drop Chance", 0.05f, new ConfigDescription("The chance of getting a Luckstone dropped by 'starred' creatures.@", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); starScaling = new DelegatedConfigEntry<bool>(useServerDelegate: true); starScaling.ConfigEntry = _instance.Config.Bind<bool>("Luckstone", "Drops Scale", true, "Drop Chance scales by number of creature 'stars'.@"); bossChance = new DelegatedConfigEntry<float>(useServerDelegate: true); bossChance.ConfigEntry = _instance.Config.Bind<float>("Luckstone", "Boss Drop Chance", 0.25f, new ConfigDescription("The base chance of getting a Luckstone dropped by a Boss.@", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); chestChance = new DelegatedConfigEntry<float>(useServerDelegate: true); chestChance.ConfigEntry = _instance.Config.Bind<float>("Luckstone", "Chest Chance", 0.03f, new ConfigDescription("The chance of finding a Luckstone in a world container.@", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); mining = new DelegatedConfigEntry<bool>(useServerDelegate: true); mining.ConfigEntry = _instance.Config.Bind<bool>("Luck Events", "Mining", true, "Apply luck when mining ores and other pickaxe use.@"); woodcutting = new DelegatedConfigEntry<bool>(useServerDelegate: true); woodcutting.ConfigEntry = _instance.Config.Bind<bool>("Luck Events", "Woodcutting", true, "Apply luck when chopping trees.@"); picking = new DelegatedConfigEntry<bool>(useServerDelegate: true); picking.ConfigEntry = _instance.Config.Bind<bool>("Luck Events", "Picking", true, "Apply luck when picking treasure, gathering, harvesting and other things that 'pop'.@"); looting = new DelegatedConfigEntry<bool>(useServerDelegate: true); looting.ConfigEntry = _instance.Config.Bind<bool>("Luck Events", "Looting", true, "Apply luck to loot drops from creatures.@"); fishing = new DelegatedConfigEntry<bool>(useServerDelegate: true); fishing.ConfigEntry = _instance.Config.Bind<bool>("Luck Events", "Fishing", true, "Apply luck to fishing extra drops.@"); crafting = new DelegatedConfigEntry<bool>(useServerDelegate: true); crafting.ConfigEntry = _instance.Config.Bind<bool>("Luck Events", "Crafting Output", true, "Apply luck to crafting output for stackable items.@"); food = new DelegatedConfigEntry<bool>(useServerDelegate: true); food.ConfigEntry = _instance.Config.Bind<bool>("Luck Events", "Food Creation", true, "Apply luck to recipe-based, stackable food creation.@"); damage = new DelegatedConfigEntry<bool>(useServerDelegate: true); damage.ConfigEntry = _instance.Config.Bind<bool>("Luck Events", "Combat Defense", false, "Apply luck to avoid some combat damage (not PvP).@"); attack = new DelegatedConfigEntry<bool>(useServerDelegate: true); attack.ConfigEntry = _instance.Config.Bind<bool>("Luck Events", "Combat Offense", false, "Apply luck to add some combat damage to attacks (not PvP).@"); statusEffect = new DelegatedConfigEntry<bool>(); statusEffect.ConfigEntry = _instance.Config.Bind<bool>("Notification", "Show Luck Status", true, "Display the lucky icon in the status bar when a Luckstone is in your inventory."); displayLuckMessage = new DelegatedConfigEntry<bool>(); displayLuckMessage.ConfigEntry = _instance.Config.Bind<bool>("Notification", "Display Luck Message", true, "Display a message in the notification area when you get lucky."); playLuckPing = new DelegatedConfigEntry<bool>(); playLuckPing.ConfigEntry = _instance.Config.Bind<bool>("Notification", "Play Luck Ding", true, "Play a 'ding' sound when you get lucky."); showBonus = new DelegatedConfigEntry<bool>(); showBonus.ConfigEntry = _instance.Config.Bind<bool>("Notification", "Show Luck Bonus", true, "Show the amount of luck bonus in the active area."); showLuckPickupEffect = new DelegatedConfigEntry<bool>(); showLuckPickupEffect.ConfigEntry = _instance.Config.Bind<bool>("Notification", "Show Luck Aura", true, "Show a luck 'aura' effect when first adding a Luckstone to your inventory."); ServerConfiguration.Instance.CreateConfigWatcher(); } } public static class LuckPulseVFX { private static GameObject s_pulsePrefab; private static Material s_pulseMaterial; private static Material GetPulseMaterial() { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown if ((Object)(object)s_pulseMaterial != (Object)null) { return s_pulseMaterial; } GameObject prefab = ZNetScene.instance.GetPrefab("vfx_Potion_eitr_minor"); if (Object.op_Implicit((Object)(object)prefab)) { Transform val = prefab.transform.Find("flare"); if (Object.op_Implicit((Object)(object)val)) { ParticleSystemRenderer component = ((Component)val).GetComponent<ParticleSystemRenderer>(); if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)((Renderer)component).sharedMaterial)) { s_pulseMaterial = new Material(((Renderer)component).sharedMaterial); } return s_pulseMaterial; } } Logging.Instance.Warning("Unable to find effectLayer"); return null; } public static GameObject GetOrCreate() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_003f: 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_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Expected O, but got Unknown //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)s_pulsePrefab)) { return s_pulsePrefab; } Color val = default(Color); ((Color)(ref val))..ctor(0.25f, 0.65f, 0.25f); GameObject val2 = new GameObject("vfx_LuckPulse_Root"); val2.SetActive(false); GameObject val3 = new GameObject("vfx_LuckPulse"); val3.transform.SetParent(val2.transform); ParticleSystem val4 = val3.AddComponent<ParticleSystem>(); MainModule main = val4.main; ((MainModule)(ref main)).duration = 0.3f; ((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(1f); ((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(0f); ((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(0.5f); ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(Color.white); ((MainModule)(ref main)).loop = false; ((MainModule)(ref main)).playOnAwake = false; ((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)0; ShapeModule shape = val4.shape; ((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)0; ((ShapeModule)(ref shape)).radius = 0.3f; EmissionModule emission = val4.emission; ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(0f); ((EmissionModule)(ref emission)).SetBursts((Burst[])(object)new Burst[1] { new Burst(0f, (short)30) }); Gradient val5 = new Gradient(); val5.SetKeys((GradientColorKey[])(object)new GradientColorKey[2] { new GradientColorKey(val, 0f), new GradientColorKey(val, 1f) }, (GradientAlphaKey[])(object)new GradientAlphaKey[2] { new GradientAlphaKey(0.1f, 0f), new GradientAlphaKey(0f, 1f) }); ColorOverLifetimeModule colorOverLifetime = val4.colorOverLifetime; ((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = true; ((ColorOverLifetimeModule)(ref colorOverLifetime)).color = new MinMaxGradient(val5); ParticleSystemRenderer component = ((Component)val4).GetComponent<ParticleSystemRenderer>(); component.renderMode = (ParticleSystemRenderMode)0; Material pulseMaterial = GetPulseMaterial(); if (!Object.op_Implicit((Object)(object)pulseMaterial)) { return null; } ((Renderer)component).material = pulseMaterial; s_pulsePrefab = val2; return s_pulsePrefab; } public static void Pulse(Player player) { //IL_0039: 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) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)player)) { return; } GameObject orCreate = GetOrCreate(); if (Object.op_Implicit((Object)(object)orCreate)) { GameObject obj = Object.Instantiate<GameObject>(orCreate, ((Component)player).transform); obj.transform.localPosition = new Vector3(0f, 1.5f, 0f); obj.transform.localRotation = Quaternion.identity; obj.SetActive(true); ParticleSystem componentInChildren = obj.GetComponentInChildren<ParticleSystem>(); if (componentInChildren != null) { componentInChildren.Play(); } MainModule main = componentInChildren.main; float duration = ((MainModule)(ref main)).duration; main = componentInChildren.main; MinMaxCurve startLifetime = ((MainModule)(ref main)).startLifetime; Object.Destroy((Object)(object)obj, duration + ((MinMaxCurve)(ref startLifetime)).constantMax + 0.1f); } } } [BepInPlugin("neobotics.valheim_mod.Luckstone", "Luckstone", "0.1.0")] [BepInProcess("valheim.exe")] [BepInProcess("valheim_server.exe")] public class Luckstone : BaseUnityPlugin { private static Luckstone _modInstance; internal const string PLUGIN_NAME = "Luckstone"; internal const string PLUGIN_VERSION = "0.1.0"; internal const string PLUGIN_GUID = "neobotics.valheim_mod.Luckstone"; internal static Logging Log; internal static bool s_isLuckstoneInInventory = false; internal static ImageHelper s_imageHelper = null; internal static float s_maxDurabilityPerLucksone = 200f; internal static string s_configFolder = string.Empty; internal static Prefabricator s_luckstonePrefab = null; public static SE_Luckstone s_luckSE = null; private static AudioClip s_pingClip = null; private static Harmony harmony = null; internal const string c_luckstonePrefabName = "Neobotics_Luckstone"; public const string c_prototypePrefabName = "Ruby"; public const string c_luckstoneItem = "$item_neobotics_luckstone"; public const string c_luckstoneDescription = "$item_neobotics_luckstone_desc"; public const float c_auraDist = 5f; internal const string c_chestCheck = "Luckstone_Chest"; internal const string c_inventoryCheck = "Luckstone_Stone"; internal const string c_rollTimeCheck = "Luckstone_Time"; internal const string c_ragdollSender = "Luckstone_RS"; internal const string c_ragdollBonus = "Luckstone_RB"; internal static readonly Dictionary<long, ZDOID> PlayerIdToZdoidMap = new Dictionary<long, ZDOID>(); private static int s_bounceFrame = 0; public static Luckstone GetInstance() { return _modInstance; } public static string GetModName() { return "Luckstone"; } public static string GetModVersion() { return "0.1.0"; } private void Awake() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) _modInstance = this; Log = Logging.Initialize(Logging.LogLevels.Info, "Luckstone"); harmony = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID); harmony.PatchAll(Assembly.GetExecutingAssembly()); ConfigureMod("Luckstone"); s_configFolder = ModResourceBootstrap.InitializeModResources(typeof(Luckstone), "Luckstone"); s_imageHelper = new ImageHelper(s_configFolder); s_luckstonePrefab = new Prefabricator("Neobotics_Luckstone", "Ruby", "$item_neobotics_luckstone", "$item_neobotics_luckstone_desc", ConfigureLuckstone) { TintColor = Color.green }; new Localizer("Luckstone"); Log.Info("0.1.0 Awake"); } private void ConfigureMod(string modName) { Cfg.BepInExConfig((BaseUnityPlugin)(object)_modInstance); } private void OnDestroy() { harmony.UnpatchSelf(); } internal static void CreateLuckStatusEffect() { s_luckSE = ScriptableObject.CreateInstance<SE_Luckstone>(); } internal static Sprite GetSprite(string imageFilename) { try { if (s_imageHelper.TryLoadImage(imageFilename + ".png", 1, 1, linear: true, out var image)) { return s_imageHelper.LoadSprite(image); } } catch (Exception) { Log.Warning("Can't create sprite from file"); } return null; } internal static float RandomMagnitude(float magnitude) { return Random.Range(1f, magnitude); } internal static void PlayPing(Vector3 location, float volume = 0.5f) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)s_pingClip)) { GameObject prefab = Utils.GetPrefab("sfx_secretfound"); ZSFX val = default(ZSFX); if (Object.op_Implicit((Object)(object)prefab) && prefab.TryGetComponent<ZSFX>(ref val)) { s_pingClip = val.m_audioClips[0]; } else { Log.Warning("Can't find ping clip"); } } if (Object.op_Implicit((Object)(object)s_pingClip)) { AudioSource.PlayClipAtPoint(s_pingClip, location, volume); } } internal static bool TryGetPlayerPosition(long playerId, out Vector3 position) { //IL_0001: 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_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) position = Vector3.zero; ZDO playerZDO = GetPlayerZDO(playerId); if (playerZDO != null) { position = playerZDO.GetPosition(); return true; } return false; } public static ZDO GetPlayerZDO(long playerId) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) if (playerId == 0L || ((Object)(object)Player.m_localPlayer != (Object)null && playerId == ((ZDOID)(ref ((Character)Player.m_localPlayer).m_nview.m_zdo.m_uid)).UserID)) { return ((Character)(Player.m_localPlayer?)).m_nview?.m_zdo; } if (PlayerIdToZdoidMap.TryGetValue(playerId, out var value)) { ZDO zDO = ZDOMan.instance.GetZDO(value); if (zDO != null) { return zDO; } PlayerIdToZdoidMap.Remove(playerId); } foreach (Player allPlayer in Player.GetAllPlayers()) { if (((Character)(allPlayer?)).m_nview?.m_zdo != null && ((ZDOID)(ref ((Character)allPlayer).m_nview.m_zdo.m_uid)).UserID == playerId) { PlayerIdToZdoidMap[playerId] = ((Character)allPlayer).m_nview.m_zdo.m_uid; return ((Character)allPlayer).m_nview.m_zdo; } } return null; } internal static bool TestLucky(long playerId) { Log.Debug($"TestLucky playerId {playerId}"); if (Time.frameCount == s_bounceFrame) { Log.Debug("Debounced"); return false; } s_bounceFrame = Time.frameCount; ZDO playerZDO = GetPlayerZDO(playerId); if (playerZDO == null) { return false; } if (!playerZDO.GetBool("Luckstone_Stone", false)) { Log.Debug("Luckstone not in inventory"); return false; } if ((double)playerZDO.GetFloat("Luckstone_Time", 0f) > ZNet.instance.GetTimeSeconds()) { Log.Debug("Cooldown not elapsed"); return false; } bool flag = Random.value <= GetCurrentLuckChance(); if (!flag) { return false; } return flag; } public static bool UpdateLuckstoneStatus() { Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer)) { s_isLuckstoneInInventory = false; return false; } bool num = ((Character)localPlayer).m_nview.m_zdo.GetBool("Luckstone_Stone", false); s_isLuckstoneInInventory = IsLuckstoneInInventory(localPlayer); if (num != s_isLuckstoneInInventory) { if (Cfg.showLuckPickupEffect.Value && s_isLuckstoneInInventory) { ((Character)localPlayer).Message((MessageType)1, "$msg_neobotics_new_luck", 0, (Sprite)null); LuckPulseVFX.Pulse(localPlayer); } ((Character)localPlayer).m_nview.m_zdo.Set("Luckstone_Stone", s_isLuckstoneInInventory); } return s_isLuckstoneInInventory; } internal static void RPC_ImLucky(long sender, Vector3 position, int bonus) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) Log.Debug("RPC_ImLucky"); ImLucky(position, bonus); } internal static void ImLucky(Vector3 position, int bonus) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) Log.Debug("You got lucky!"); Player localPlayer = Player.m_localPlayer; if (Cfg.displayLuckMessage.Value) { ((Character)localPlayer).Message((MessageType)1, "$msg_neobotics_got_lucky", 0, (Sprite)null)