Please disclose if your mod was created primarily using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of SafetyStatus v1.2.1
SafetyStatus.dll
Decompiled a year agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Entities; using Jotunn.Managers; using SafetyStatus.Extensions; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("SafetyStatus")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("SafetyStatus")] [assembly: AssemblyCopyright("Copyright © 2023")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")] [assembly: AssemblyFileVersion("1.2.1")] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.2.1.0")] [module: UnverifiableCode] namespace SafetyStatus { [BepInPlugin("Searica.Valheim.SafetyStatus", "SafetyStatus", "1.2.1")] [BepInDependency("com.jotunn.jotunn", "2.21.3")] internal sealed class SafetyStatus : BaseUnityPlugin { [HarmonyPatch(typeof(EffectArea))] internal static class EffectAreaPatch { [HarmonyPostfix] [HarmonyPatch("Awake")] private static void AwakePostfix(EffectArea __instance) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)__instance.m_type == 4) { __instance.m_statusEffect = "SafeStatusEffect"; __instance.m_statusEffectHash = SafeEffectHash; } } [HarmonyPrefix] [HarmonyPatch("CustomFixedUpdate")] private static void CustomFixedUpdatePrefex(EffectArea __instance, float deltaTime) { if (Object.op_Implicit((Object)(object)__instance)) { __instance.m_collidedWithCharacter = __instance.m_collidedWithCharacter.Where((Character x) => IsValidCollidedWithCharacter(x)).ToList(); } } private static bool IsValidCollidedWithCharacter(Character item) { if (!Object.op_Implicit((Object)(object)item) || item.GetSEMan() == null || !Object.op_Implicit((Object)(object)item.GetSEMan().m_nview) || !item.GetSEMan().m_nview.IsValid()) { return false; } return true; } } [HarmonyPatch(typeof(Piece))] internal static class PiecePatch { [HarmonyPostfix] [HarmonyPriority(200)] [HarmonyPatch("Awake")] private static void AwakePostfix(Piece __instance) { if (Object.op_Implicit((Object)(object)__instance)) { AddSafeEffect(((Component)__instance).gameObject); } } [HarmonyPostfix] [HarmonyPriority(200)] [HarmonyPatch("SetCreator")] private static void SetCreatorPostfix(Piece __instance) { if (Object.op_Implicit((Object)(object)__instance)) { AddSafeEffect(((Component)__instance).gameObject); } } private static void AddSafeEffect(GameObject gameObject) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Invalid comparison between Unknown and I4 if (!Object.op_Implicit((Object)(object)gameObject)) { return; } EffectArea[] componentsInChildren = gameObject.GetComponentsInChildren<EffectArea>(); foreach (EffectArea val in componentsInChildren) { if ((int)val.m_type == 4) { val.m_statusEffect = "SafeStatusEffect"; val.m_statusEffectHash = SafeEffectHash; } } } } [HarmonyPatch(typeof(Player))] internal static class PlayerPatch { [HarmonyPostfix] [HarmonyPatch("UpdateEnvStatusEffects")] private static void UpdateEnvStatusEffectsPostFix(Player __instance) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) EffectArea val = EffectArea.IsPointInsideArea(((Component)__instance).transform.position, (Type)4, 1f); if (((Character)__instance).m_seman.HaveStatusEffect(SafeEffectHash) && !Object.op_Implicit((Object)(object)val)) { ((Character)__instance).m_seman.RemoveStatusEffect(SafeEffectHash, false); } } } internal const string Author = "Searica"; public const string PluginName = "SafetyStatus"; public const string PluginGUID = "Searica.Valheim.SafetyStatus"; public const string PluginVersion = "1.2.1"; internal static CustomStatusEffect SafeEffect; internal const string SafeEffectName = "SafeStatusEffect"; internal static int SafeEffectHash; public void Awake() { Log.Init(((BaseUnityPlugin)this).Logger); Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "Searica.Valheim.SafetyStatus"); Game.isModded = true; PrefabManager.OnVanillaPrefabsAvailable += AddCustomStatusEffect; } private void AddCustomStatusEffect() { //IL_0032: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown try { StatusEffect obj = ScriptableObject.CreateInstance<StatusEffect>(); ((Object)obj).name = "SafeStatusEffect"; obj.m_name = "Safe"; obj.m_icon = Cache.GetPrefab<CraftingStation>("piece_workbench").m_icon; obj.m_startMessageType = (MessageType)1; obj.m_startMessage = "You feel safer"; obj.m_stopMessageType = (MessageType)1; obj.m_stopMessage = "You feel less safe"; SafeEffect = new CustomStatusEffect(obj, false); SafeEffectHash = SafeEffect.StatusEffect.NameHash(); ItemManager.Instance.AddStatusEffect(SafeEffect); } finally { PrefabManager.OnVanillaPrefabsAvailable -= AddCustomStatusEffect; } } } internal static class Log { internal static ManualLogSource _logSource; internal static void Init(ManualLogSource logSource) { _logSource = logSource; } internal static void LogDebug(object data) { _logSource.LogDebug(data); } internal static void LogError(object data) { _logSource.LogError(data); } internal static void LogFatal(object data) { _logSource.LogFatal(data); } internal static void LogInfo(object data) { _logSource.LogInfo(data); } internal static void LogMessage(object data) { _logSource.LogMessage(data); } internal static void LogWarning(object data) { _logSource.LogWarning(data); } } } namespace SafetyStatus.Extensions { internal static class EventExtensions { public static void SafeInvoke(this Action events) { if (events == null) { return; } Delegate[] invocationList = events.GetInvocationList(); for (int i = 0; i < invocationList.Length; i++) { Action action = (Action)invocationList[i]; try { action(); } catch (Exception ex) { Log.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {action.Method.DeclaringType.Name}.{action.Method.Name}:\n{ex}"); } } } public static void SafeInvoke<TArg1>(this Action<TArg1> events, TArg1 arg1) { if (events == null) { return; } Delegate[] invocationList = events.GetInvocationList(); for (int i = 0; i < invocationList.Length; i++) { Action<TArg1> action = (Action<TArg1>)invocationList[i]; try { action(arg1); } catch (Exception ex) { Log.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {action.Method.DeclaringType.Name}.{action.Method.Name}:\n{ex}"); } } } public static void SafeInvoke<TArg1, TArg2>(this Action<TArg1, TArg2> events, TArg1 arg1, TArg2 arg2) { if (events == null) { return; } Delegate[] invocationList = events.GetInvocationList(); for (int i = 0; i < invocationList.Length; i++) { Action<TArg1, TArg2> action = (Action<TArg1, TArg2>)invocationList[i]; try { action(arg1, arg2); } catch (Exception ex) { Log.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {action.Method.DeclaringType.Name}.{action.Method.Name}:\n{ex}"); } } } public static void SafeInvoke<TEventArg>(this EventHandler<TEventArg> events, object sender, TEventArg arg1) { if (events == null) { return; } Delegate[] invocationList = events.GetInvocationList(); for (int i = 0; i < invocationList.Length; i++) { EventHandler<TEventArg> eventHandler = (EventHandler<TEventArg>)invocationList[i]; try { eventHandler(sender, arg1); } catch (Exception ex) { Log.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {eventHandler.Method.DeclaringType.Name}.{eventHandler.Method.Name}:\n{ex}"); } } } } internal static class GameObjectExtensions { internal static GameObject DeepCopy(this GameObject obj) { bool activeSelf = obj.activeSelf; obj.SetActive(false); GameObject result = Object.Instantiate<GameObject>(obj); obj.SetActive(activeSelf); return result; } public static bool HasComponent<T>(this GameObject gameObject) where T : Component { return (Object)(object)gameObject.GetComponent<T>() != (Object)null; } public static bool HasComponent(this GameObject gameObject, string componentName) { return (Object)(object)gameObject.GetComponent(componentName) != (Object)null; } public static void DestroyComponentsInChildren<T>(this GameObject gameObject, bool includeInactive = false) where T : Component { T[] componentsInChildren = gameObject.GetComponentsInChildren<T>(includeInactive); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } } public static bool HasAnyComponent(this GameObject gameObject, params Type[] components) { foreach (Type type in components) { if ((Object)(object)gameObject.GetComponent(type) != (Object)null) { return true; } } return false; } public static bool HasAnyComponent(this GameObject gameObject, params string[] componentNames) { foreach (string text in componentNames) { if ((Object)(object)gameObject.GetComponent(text) != (Object)null) { return true; } } return false; } public static bool HasAllComponents(this GameObject gameObject, params string[] componentNames) { foreach (string text in componentNames) { if ((Object)(object)gameObject.GetComponent(text) == (Object)null) { return false; } } return true; } public static bool HasAllComponents(this GameObject gameObject, params Type[] components) { foreach (Type type in components) { if ((Object)(object)gameObject.GetComponent(type) == (Object)null) { return false; } } return true; } public static bool HasAnyComponentInChildren(this GameObject gameObject, bool includeInactive = false, params Type[] components) { foreach (Type type in components) { if ((Object)(object)gameObject.GetComponentInChildren(type, includeInactive) != (Object)null) { return true; } } return false; } public static bool HasComponentInChildren<T>(this GameObject gameObject, bool includeInactive = false) where T : Component { return (Object)(object)gameObject.GetComponentInChildren<T>(includeInactive) != (Object)null; } internal static T GetComponentInChildrenByName<T>(this GameObject gameObject, string name, bool includeInactive = false) where T : Component { T[] componentsInChildren = gameObject.GetComponentsInChildren<T>(includeInactive); foreach (T val in componentsInChildren) { if (((Object)(object)val).name == name) { return val; } } Log.LogWarning("No T with name " + name + " found for GameObject: " + ((Object)gameObject).name); return default(T); } internal static Mesh GetMesh(this GameObject gameObject, string meshName) { MeshFilter[] componentsInChildren = gameObject.GetComponentsInChildren<MeshFilter>(); for (int i = 0; i < componentsInChildren.Length; i++) { Mesh mesh = componentsInChildren[i].mesh; if (!((Object)(object)mesh == (Object)null) && ((Object)mesh).name.RemoveSuffix("Instance").Trim() == meshName) { return mesh; } } Log.LogWarning("Could not find Mesh: " + meshName + " for GameObject: " + ((Object)gameObject).name); return null; } } internal static class TypeExtensions { internal static List<T> GetAllPublicConstantValues<T>(this Type type) { return (from fi in type.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy) where fi.IsLiteral && !fi.IsInitOnly && fi.FieldType == typeof(T) select fi into x select (T)x.GetRawConstantValue()).ToList(); } internal static List<T> GetAllPublicStaticValues<T>(this Type type) { return (from fi in type.GetFields(BindingFlags.Static | BindingFlags.Public) where fi.FieldType == typeof(T) select fi into x select (T)x.GetValue(null)).ToList(); } } internal static class GenericExtensions { private const BindingFlags AllBindings = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty; public static void CopyFields(this object target, object source) { if (target == null || source == null) { throw new Exception("Target or/and Source Objects are null"); } Type type = source.GetType(); FieldInfo[] fields = target.GetType().GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty); foreach (FieldInfo fieldInfo in fields) { FieldInfo field = type.GetField(fieldInfo.Name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty); if (!(field == null) && field.IsInitOnly && field.FieldType.IsAssignableFrom(fieldInfo.FieldType)) { field.SetValue(source, fieldInfo.GetValue(target)); } } } internal static T Ref<T>(this T o) where T : Object { if (!Object.op_Implicit((Object)(object)o)) { return default(T); } return o; } } internal static class IEnumerableExtensions { internal static void Dispose(this IEnumerable<IDisposable> collection) { foreach (IDisposable item in collection) { if (item != null) { try { item.Dispose(); } catch (Exception) { Log.LogWarning("Could not dispose of item"); } } } } } internal static class ReflectionUtils { public const BindingFlags AllBindings = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty; internal static MethodInfo GetMethod(Type type, string name, Type[] types) { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name == name && HasMatchingParameterTypes(0, types, methodInfo.GetParameters())) { return methodInfo; } } return null; } internal static MethodInfo GetGenericMethod(Type type, string name, int genericParameterCount, Type[] types) { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty); foreach (MethodInfo methodInfo in methods) { if (methodInfo.IsGenericMethod && methodInfo.ContainsGenericParameters && methodInfo.Name == name && HasMatchingParameterTypes(genericParameterCount, types, methodInfo.GetParameters())) { return methodInfo; } } return null; } private static bool HasMatchingParameterTypes(int genericParameterCount, Type[] types, ParameterInfo[] parameters) { if (parameters.Length < genericParameterCount || parameters.Length != types.Length) { return false; } int num = 0; for (int i = 0; i < parameters.Length; i++) { if (parameters[i].ParameterType.IsGenericParameter) { num++; } else if (types[i] != parameters[i].ParameterType) { return false; } } if (num != genericParameterCount) { return false; } return true; } } internal static class StringExtensions { internal static bool ContainsAny(this string str, params string[] substrings) { foreach (string value in substrings) { if (str.Contains(value)) { return true; } } return false; } internal static bool EndsWithAny(this string str, params string[] suffixes) { foreach (string value in suffixes) { if (str.EndsWith(value)) { return true; } } return false; } internal static bool StartsWithAny(this string str, params string[] suffixes) { foreach (string value in suffixes) { if (str.StartsWith(value)) { return true; } } return false; } internal static string RemoveSuffix(this string s, string suffix) { if (s.EndsWith(suffix)) { return s.Substring(0, s.Length - suffix.Length); } return s; } internal static string RemovePrefix(this string s, string prefix) { if (s.StartsWith(prefix)) { return s.Substring(prefix.Length, s.Length - prefix.Length); } return s; } internal static string CapitalizeFirstLetter(this string s) { if (s.Length == 0) { return s; } if (s.Length == 1) { return $"{char.ToUpper(s[0])}"; } return char.ToUpper(s[0]) + s.Substring(1); } internal static string EmptyIfNull(this object value) { if (value == null) { return string.Empty; } return value.ToString(); } } internal static class TransformExtensions { public static Transform FindDeepChild(this Transform transform, string childName, bool breadthFirst = true) { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown if (breadthFirst) { Queue<Transform> queue = new Queue<Transform>(); queue.Enqueue(transform); while (queue.Count > 0) { Transform val = queue.Dequeue(); if (((Object)val).name == childName) { return val; } foreach (Transform item2 in val) { Transform item = item2; queue.Enqueue(item); } } return null; } foreach (Transform item3 in transform) { Transform val2 = item3; if (((Object)val2).name == childName) { return val2; } Transform val3 = val2.FindDeepChild(childName); if ((Object)(object)val3 != (Object)null) { return val3; } } return null; } } } namespace SafetyStatus.Configs { internal static class ConfigManager { internal enum LoggerLevel { Low, Medium, High } private static string ConfigFileName; private static string ConfigFileFullPath; private static ConfigFile configFile; private static BaseUnityPlugin ConfigurationManager; private const string ConfigManagerGUID = "com.bepis.bepinex.configurationmanager"; private const string MainSection = "Global"; private static readonly ConfigurationManagerAttributes AdminConfig = new ConfigurationManagerAttributes { IsAdminOnly = true }; private static readonly ConfigurationManagerAttributes ClientConfig = new ConfigurationManagerAttributes { IsAdminOnly = false }; private const char ZWS = '\u200b'; internal static ConfigEntry<LoggerLevel> Verbosity { get; private set; } internal static LoggerLevel VerbosityLevel => Verbosity.Value; internal static bool IsVerbosityLow => Verbosity.Value >= LoggerLevel.Low; internal static bool IsVerbosityMedium => Verbosity.Value >= LoggerLevel.Medium; internal static bool IsVerbosityHigh => Verbosity.Value >= LoggerLevel.High; internal static event Action OnConfigWindowClosed; internal static event Action OnConfigFileReloaded; private static void InvokeOnConfigWindowClosed() { ConfigManager.OnConfigWindowClosed?.SafeInvoke(); } private static void InvokeOnConfigFileReloaded() { ConfigManager.OnConfigFileReloaded?.SafeInvoke(); } internal static ConfigEntry<T> BindConfig<T>(string section, string name, T value, string description, AcceptableValueBase acceptVals = null, bool synced = true) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown string extendedDescription = GetExtendedDescription(description, synced); return configFile.Bind<T>(section, name, value, new ConfigDescription(extendedDescription, acceptVals, new object[1] { synced ? AdminConfig : ClientConfig })); } internal static string SetStringPriority(string sectionName, int priority) { if (priority == 0) { return sectionName; } return new string('\u200b', priority) + sectionName; } internal static string GetExtendedDescription(string description, bool synchronizedSetting) { return description + (synchronizedSetting ? " [Synced with Server]" : " [Not Synced with Server]"); } internal static void Init(string GUID, ConfigFile config) { configFile = config; configFile.SaveOnConfigSet = false; ConfigFileName = GUID + ".cfg"; ConfigFileFullPath = Paths.ConfigPath + Path.DirectorySeparatorChar + ConfigFileName; } internal static void SetUpConfig() { Verbosity = BindConfig("Global", "Verbosity", LoggerLevel.Low, "Low will log basic information about the mod. Medium will log information that is useful for troubleshooting. High will log a lot of information, do not set it to this without good reason as it will slow down your game.", null, synced: false); Save(); } private static bool DisableSaveOnConfigSet() { bool saveOnConfigSet = configFile.SaveOnConfigSet; configFile.SaveOnConfigSet = false; return saveOnConfigSet; } internal static void SaveOnConfigSet(bool value) { configFile.SaveOnConfigSet = value; } internal static void Save() { configFile.Save(); } internal static void SetupWatcher() { FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, ConfigFileName); fileSystemWatcher.Changed += ReloadConfigFile; fileSystemWatcher.Created += ReloadConfigFile; fileSystemWatcher.Renamed += ReloadConfigFile; fileSystemWatcher.IncludeSubdirectories = true; fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher.EnableRaisingEvents = true; } private static void ReloadConfigFile(object sender, FileSystemEventArgs e) { if (!File.Exists(ConfigFileFullPath)) { return; } try { Log.LogInfo("Reloading config file"); bool value = DisableSaveOnConfigSet(); configFile.Reload(); SaveOnConfigSet(value); InvokeOnConfigFileReloaded(); } catch { Log.LogError("There was an issue loading your " + ConfigFileName); Log.LogError("Please check your config entries for spelling and format!"); } } internal static void CheckForConfigManager() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if ((int)SystemInfo.graphicsDeviceType != 4 && Chainloader.PluginInfos.TryGetValue("com.bepis.bepinex.configurationmanager", out var value) && Object.op_Implicit((Object)(object)value.Instance)) { ConfigurationManager = value.Instance; Log.LogDebug("Configuration manager found, hooking DisplayingWindowChanged"); EventInfo @event = ((object)ConfigurationManager).GetType().GetEvent("DisplayingWindowChanged"); if (@event != null) { Action<object, object> action = OnConfigManagerDisplayingWindowChanged; Delegate handler = Delegate.CreateDelegate(@event.EventHandlerType, action.Target, action.Method); @event.AddEventHandler(ConfigurationManager, handler); } } } private static void OnConfigManagerDisplayingWindowChanged(object sender, object e) { if (!(bool)((object)ConfigurationManager).GetType().GetProperty("DisplayingWindow").GetValue(ConfigurationManager, null)) { InvokeOnConfigWindowClosed(); } } } }