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 SnapPoints v1.1.1
BepInEx/plugins/SnapPoints/SnapPoints.dll
Decompiled 5 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Kriona.Shared; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Kriona")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright (c) 2026 Kriona Hagen - MIT License")] [assembly: AssemblyFileVersion("1.1.1.0")] [assembly: AssemblyInformationalVersion("1.1.1")] [assembly: AssemblyProduct("Snap Points")] [assembly: AssemblyTitle("Snap Points")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace SnapPoints { internal static class PieceConfig { private const string FileName = "kriona.SnapPoints.cfg"; private const string Comment = "##"; private const string Inherit = "inherit"; private const string NotLoadedGroup = "Not loaded"; private static readonly string[] header = new string[9] { "## Snap Points", "## Changes take effect as soon as this file is saved; you don't need to restart Valheim or rejoin the world", "", "## Each line is: Prefab = true/false/inherit ## Name in game", "## - true adds a snap point at each corner of the piece, keeping any it has from the game", "## - false takes away all of the piece's snap points, so it never snaps", "## - inherit leaves the piece's snap points as the game has them", "", "## Chests, resource stacks and piles, tables, benches, banners, armor stands, item stands and portals start as true, and everything else starts as inherit" }; private static readonly HashSet<string> defaultOn = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "piece_chest_wood", "piece_chest", "piece_chest_private", "piece_chest_blackmetal", "piece_chest_barrel", "piece_chest_grausten", "piece_chest_warderobe", "wood_stack", "wood_fine_stack", "wood_core_stack", "wood_frost_stack", "wood_yggdrasil_stack", "blackwood_stack", "stone_pile", "coal_pile", "flint_pile", "obsidian_pile", "grausten_pile", "blackmarble_pile", "bone_stack", "skull_pile", "bar_copper_stack", "bar_tin_stack", "bar_bronze_stack", "bar_iron_stack", "bar_silver_stack", "bar_blackmetal_stack", "bar_flametal_stack", "bar_gold_stack", "piece_table", "piece_table_oak", "piece_blackmarble_table", "piece_table_runed", "piece_table_runed_small", "piece_bench01", "piece_blackwood_bench", "piece_blackwood_bench01", "piece_blackmarble_bench", "piece_bench_runed", "piece_logbench01", "piece_banner01", "piece_banner02", "piece_banner03", "piece_banner04", "piece_banner05", "piece_banner06", "piece_banner07", "piece_banner08", "piece_banner09", "piece_banner10", "piece_banner11", "ArmorStand", "ArmorStand_Female", "ArmorStand_Male", "itemstand", "itemstandh", "portal_wood", "portal_stone", "portal" }; private static readonly Dictionary<string, bool> states = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase); private static ConfigMirror mirror; private static StateEntries pieceEntries; private static SortedDictionary<string, SortedDictionary<string, string>> lastGroups; private static SortedDictionary<string, string> lastNotLoaded; public static bool AnyOff { get; private set; } public static string FilePath => Path.Combine(Paths.ConfigPath, "kriona.SnapPoints.cfg"); public static void Init(ConfigFile file) { mirror = new ConfigMirror(file, OnEntryChanged); pieceEntries = new StateEntries(mirror, "true adds a snap point at each corner, false takes away all of its snap points, inherit leaves them as the game has them"); } public static bool? GetState(string prefabName) { if (states.TryGetValue(prefabName, out var value)) { return value; } return null; } public static void Reload() { if ((Object)(object)ZNetScene.instance != (Object)null) { Load(ZNetScene.instance); Snapping.ApplyAll(); } } public static void Load(ZNetScene scene) { string filePath = FilePath; Dictionary<string, string> dictionary; try { dictionary = Read(filePath); } catch (IOException ex) { Plugin.Log.LogWarning((object)("Couldn't read " + filePath + ": " + ex.Message)); return; } SortedDictionary<string, SortedDictionary<string, string>> buildPieces = GetBuildPieces(scene); HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); foreach (SortedDictionary<string, string> value in buildPieces.Values) { hashSet.UnionWith(value.Keys); } SortedDictionary<string, string> sortedDictionary = new SortedDictionary<string, string>(StringComparer.OrdinalIgnoreCase); foreach (string key in dictionary.Keys) { if (!hashSet.Contains(key)) { sortedDictionary[key] = ""; } } Dictionary<string, bool?> dictionary2 = new Dictionary<string, bool?>(StringComparer.OrdinalIgnoreCase); foreach (SortedDictionary<string, string> value2 in buildPieces.Values) { foreach (string key2 in value2.Keys) { dictionary2[key2] = GetLineState(dictionary, key2); } } foreach (string key3 in sortedDictionary.Keys) { dictionary2[key3] = GetLineState(dictionary, key3); } SetStates(dictionary2); lastGroups = buildPieces; lastNotLoaded = sortedDictionary; Write(filePath, buildPieces, sortedDictionary, dictionary2); SyncEntries(dictionary2); } private static void SetStates(Dictionary<string, bool?> lineStates) { states.Clear(); foreach (KeyValuePair<string, bool?> lineState in lineStates) { if (lineState.Value.HasValue) { states[lineState.Key] = lineState.Value.Value; } } AnyOff = states.ContainsValue(value: false); } private static void SyncEntries(Dictionary<string, bool?> lineStates) { if (mirror == null) { return; } mirror.Sync(delegate { foreach (KeyValuePair<string, SortedDictionary<string, string>> lastGroup in lastGroups) { foreach (KeyValuePair<string, string> item in lastGroup.Value) { pieceEntries.Set(lastGroup.Key, item.Key, item.Value, lineStates[item.Key]); } } foreach (string key in lastNotLoaded.Keys) { pieceEntries.Set("Not loaded", key, "", lineStates[key]); } pieceEntries.RemoveUnset(); }); } private static void OnEntryChanged() { if (lastGroups == null) { return; } Dictionary<string, bool?> dictionary = new Dictionary<string, bool?>(StringComparer.OrdinalIgnoreCase); foreach (SortedDictionary<string, string> value in lastGroups.Values) { foreach (string key in value.Keys) { dictionary[key] = GetEntryState(key); } } foreach (string key2 in lastNotLoaded.Keys) { dictionary[key2] = GetEntryState(key2); } SetStates(dictionary); Write(FilePath, lastGroups, lastNotLoaded, dictionary); Plugin.Watcher?.Remember(); Snapping.ApplyAll(); } private static bool? GetEntryState(string key) { if (pieceEntries.TryGetState(key, out var state)) { return state; } return GetState(key); } private static SortedDictionary<string, SortedDictionary<string, string>> GetBuildPieces(ZNetScene scene) { SortedDictionary<string, PieceTable> sortedDictionary = new SortedDictionary<string, PieceTable>(StringComparer.OrdinalIgnoreCase); foreach (GameObject prefab in scene.m_prefabs) { ItemDrop val = (((Object)(object)prefab == (Object)null) ? null : prefab.GetComponent<ItemDrop>()); PieceTable val2 = val?.m_itemData?.m_shared?.m_buildPieces; if (!((Object)(object)val2 == (Object)null)) { string text = Clean(Localize(val.m_itemData.m_shared.m_name)); if (sortedDictionary.ContainsKey(text)) { text = text + " (" + ((Object)prefab).name + ")"; } sortedDictionary[text] = val2; } } SortedDictionary<string, SortedDictionary<string, string>> sortedDictionary2 = new SortedDictionary<string, SortedDictionary<string, string>>(StringComparer.OrdinalIgnoreCase); HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); foreach (KeyValuePair<string, PieceTable> item in sortedDictionary) { SortedDictionary<string, string> sortedDictionary3 = new SortedDictionary<string, string>(StringComparer.OrdinalIgnoreCase); foreach (GameObject piece in item.Value.m_pieces) { if (!((Object)(object)piece == (Object)null) && !((Object)(object)piece.GetComponent<TerrainModifier>() != (Object)null) && !((Object)(object)piece.GetComponent<TerrainOp>() != (Object)null)) { Piece component = piece.GetComponent<Piece>(); if (!((Object)(object)component == (Object)null) && hashSet.Add(((Object)piece).name)) { sortedDictionary3[((Object)piece).name] = Clean(Localize(component.m_name)); } } } if (sortedDictionary3.Count > 0) { sortedDictionary2[item.Key] = sortedDictionary3; } } return sortedDictionary2; } private static bool? GetLineState(Dictionary<string, string> values, string key) { if (!values.TryGetValue(key, out var value)) { if (!defaultOn.Contains(key)) { return null; } return true; } if (bool.TryParse(value, out var result)) { return result; } if (!value.Equals("inherit", StringComparison.OrdinalIgnoreCase)) { Plugin.Log.LogWarning((object)("Couldn't read " + key + " = " + value + ", using inherit")); } return null; } private static Dictionary<string, string> Read(string path) { Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); if (!File.Exists(path)) { return dictionary; } string[] array = File.ReadAllLines(path); for (int i = 0; i < array.Length; i++) { string text = array[i]; int num = text.IndexOf("##", StringComparison.Ordinal); if (num >= 0) { text = text.Substring(0, num); } int num2 = text.IndexOf('='); if (num2 > 0) { string text2 = text.Substring(0, num2).Trim(); if (text2.Length > 0) { dictionary[text2] = text.Substring(num2 + 1).Trim(); } } } return dictionary; } private static void Write(string path, SortedDictionary<string, SortedDictionary<string, string>> groups, SortedDictionary<string, string> notLoaded, Dictionary<string, bool?> lineStates) { StringBuilder stringBuilder = new StringBuilder(); string[] array = header; foreach (string value in array) { stringBuilder.Append(value).Append("\r\n"); } foreach (KeyValuePair<string, SortedDictionary<string, string>> group in groups) { AppendGroup(stringBuilder, group.Key, group.Value, lineStates); } if (notLoaded.Count > 0) { AppendGroup(stringBuilder, "Not loaded", notLoaded, lineStates); } string text = stringBuilder.ToString(); try { if (!File.Exists(path) || !(File.ReadAllText(path) == text)) { File.WriteAllText(path, text); } } catch (IOException ex) { Plugin.Log.LogWarning((object)("Couldn't write " + path + ": " + ex.Message)); } } private static void AppendGroup(StringBuilder builder, string heading, SortedDictionary<string, string> pieces, Dictionary<string, bool?> lineStates) { builder.Append("\r\n").Append("##").Append(" ") .Append(heading) .Append("\r\n"); foreach (KeyValuePair<string, string> piece in pieces) { builder.Append(piece.Key).Append(" = ").Append(StateEntries.Format(lineStates[piece.Key])); if (piece.Value.Length > 0) { builder.Append(" ").Append("##").Append(" ") .Append(piece.Value); } builder.Append("\r\n"); } } private static string Localize(string token) { if (Localization.instance == null) { return token; } return Localization.instance.Localize(token); } private static string Clean(string name) { return name.Replace("\r", "").Replace("\n", " ").Replace("#", "") .Trim(); } } [BepInPlugin("kriona.SnapPoints", "Snap Points", "1.1.1")] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "kriona.SnapPoints"; public const string PluginName = "Snap Points"; public const string PluginVersion = "1.1.1"; internal static ManualLogSource Log; internal static ConfigWatcher Watcher; private Harmony harmony; private void Awake() { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; PieceConfig.Init(((BaseUnityPlugin)this).Config); Watcher = new ConfigWatcher(PieceConfig.FilePath, PieceConfig.Reload, ((BaseUnityPlugin)this).Logger, "Snap Points"); harmony = new Harmony("kriona.SnapPoints"); harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Snap Points 1.1.1 loaded"); } private void Update() { Watcher.Update(); } private void OnDestroy() { Watcher?.Dispose(); Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } } internal static class Snapping { private const string SnapPointTag = "snappoint"; private static readonly string[] CornerNames = new string[8] { "bottom corner 1", "bottom corner 2", "bottom corner 3", "bottom corner 4", "top corner 1", "top corner 2", "top corner 3", "top corner 4" }; private static readonly string[] InnerNames = new string[4] { "inner corner 1", "inner corner 2", "inner corner 3", "inner corner 4" }; private static readonly string[] OuterNames = new string[4] { "outer corner 1", "outer corner 2", "outer corner 3", "outer corner 4" }; private static readonly string[] LidNames = new string[4] { "lid corner 1", "lid corner 2", "lid corner 3", "lid corner 4" }; private const float MaxLidInset = 0.09f; private static readonly Dictionary<string, string> lidParts = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) { { "piece_chest_wood", "New/woodchesttop_closed" }, { "piece_chest", "New/ironchesttop_closed" }, { "piece_chest_private", "New/privatechesttop_closed" }, { "piece_chest_blackmetal", "New/Closed/blackmetalchesttop_closed" } }; private static readonly Dictionary<string, float> outerSquares = new Dictionary<string, float> { { "ArmorStand", 0.5f } }; private static readonly Dictionary<string, string> innerParts = new Dictionary<string, string> { { "piece_banner", "default" } }; private static readonly string[] surfacePieces = new string[3] { "itemstand", "rug_", "jute_carpet" }; private static readonly Dictionary<string, Vector3[]> cornersByPrefab = new Dictionary<string, Vector3[]>(); private static readonly Dictionary<string, Vector3[]> innerByPrefab = new Dictionary<string, Vector3[]>(); private static readonly Dictionary<string, Vector3[]> outerByPrefab = new Dictionary<string, Vector3[]>(); private static readonly Dictionary<string, Vector3[]> lidByPrefab = new Dictionary<string, Vector3[]>(); public static void ApplyAll() { if ((Object)(object)ZNetScene.instance == (Object)null) { return; } foreach (GameObject prefab in ZNetScene.instance.m_prefabs) { if ((Object)(object)prefab != (Object)null && (Object)(object)prefab.GetComponent<Piece>() != (Object)null) { Apply(prefab.transform, ((Object)prefab).name, PieceConfig.GetState(((Object)prefab).name) == true, isPrefab: true); } } foreach (Piece s_allPiece in Piece.s_allPieces) { if ((Object)(object)s_allPiece != (Object)null) { ApplyToInstance(((Component)s_allPiece).gameObject); } } if ((Object)(object)Player.m_localPlayer != (Object)null && (Object)(object)Player.m_localPlayer.m_placementGhost != (Object)null) { ApplyToInstance(Player.m_localPlayer.m_placementGhost); } } private static void ApplyToInstance(GameObject instance) { string prefabName = Utils.GetPrefabName(instance); GameObject prefab = ZNetScene.instance.GetPrefab(prefabName); if ((Object)(object)prefab != (Object)null) { Apply(instance.transform, prefabName, HasOwnSnapPoints(prefab.transform), isPrefab: false); } } private static void Apply(Transform root, string prefabName, bool want, bool isPrefab) { bool flag = HasOwnSnapPoints(root); if (want == flag) { return; } if (!want) { for (int num = root.childCount - 1; num >= 0; num--) { Transform child = root.GetChild(num); if (IsOwnSnapPoint(child)) { if (isPrefab) { Object.DestroyImmediate((Object)(object)((Component)child).gameObject, true); } else { child.SetParent((Transform)null, false); Object.Destroy((Object)(object)((Component)child).gameObject); } } } return; } if (!cornersByPrefab.TryGetValue(prefabName, out var value)) { GameObject val = (isPrefab ? ((Component)root).gameObject : ZNetScene.instance.GetPrefab(prefabName)); value = GetCorners(val.transform); cornersByPrefab[prefabName] = value; innerByPrefab[prefabName] = GetInnerCorners(val.transform, prefabName); outerByPrefab[prefabName] = GetOuterCorners(value, prefabName); lidByPrefab[prefabName] = GetLidCorners(val.transform, value, prefabName); if (value == null) { Plugin.Log.LogWarning((object)(prefabName + " has no collider to place snap points around")); } } if (value != null) { AddSnapPoints(root, CornerNames, value); Vector3[] array = innerByPrefab[prefabName]; if (array != null) { AddSnapPoints(root, InnerNames, array); } Vector3[] array2 = outerByPrefab[prefabName]; if (array2 != null) { AddSnapPoints(root, OuterNames, array2); } Vector3[] array3 = lidByPrefab[prefabName]; if (array3 != null) { AddSnapPoints(root, LidNames, array3); } } } private static Vector3[] GetLidCorners(Transform root, Vector3[] corners, string prefabName) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0078: 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_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: 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) //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_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0183: 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_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0198: 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) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) if (corners == null || !lidParts.TryGetValue(prefabName, out var value)) { return null; } Transform val = root.Find(value); MeshFilter val2 = (((Object)(object)val == (Object)null) ? null : ((Component)val).GetComponent<MeshFilter>()); if ((Object)(object)val2 == (Object)null || (Object)(object)val2.sharedMesh == (Object)null) { Plugin.Log.LogWarning((object)(prefabName + " has no lid at " + value)); return null; } bool any = false; Bounds bounds = default(Bounds); Encapsulate(ref bounds, ref any, val2.sharedMesh.bounds, root.worldToLocalMatrix * val.localToWorldMatrix); Vector3 val3 = corners[0]; Vector3 val4 = corners[6]; int num = ((!(val4.x - val3.x >= val4.z - val3.z)) ? 2 : 0); Vector3 val5 = ((Bounds)(ref bounds)).min; if (((Vector3)(ref val5))[num] <= ((Vector3)(ref val3))[num]) { val5 = ((Bounds)(ref bounds)).max; if (((Vector3)(ref val5))[num] >= ((Vector3)(ref val4))[num]) { return null; } } float num2 = ((Vector3)(ref val3))[num]; val5 = ((Bounds)(ref bounds)).min; ((Vector3)(ref val3))[num] = Mathf.Min(Mathf.Max(num2, ((Vector3)(ref val5))[num]), ((Vector3)(ref val3))[num] + 0.09f); float num3 = ((Vector3)(ref val4))[num]; val5 = ((Bounds)(ref bounds)).max; ((Vector3)(ref val4))[num] = Mathf.Max(Mathf.Min(num3, ((Vector3)(ref val5))[num]), ((Vector3)(ref val4))[num] - 0.09f); return (Vector3[])(object)new Vector3[4] { new Vector3(val3.x, val3.y, val3.z), new Vector3(val4.x, val3.y, val3.z), new Vector3(val4.x, val3.y, val4.z), new Vector3(val3.x, val3.y, val4.z) }; } private static Vector3[] GetOuterCorners(Vector3[] corners, string prefabName) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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) //IL_0076: 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_0091: 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_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: 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_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) if (corners == null) { return null; } float num = 0f; foreach (KeyValuePair<string, float> outerSquare in outerSquares) { if (prefabName.StartsWith(outerSquare.Key, StringComparison.OrdinalIgnoreCase)) { num = outerSquare.Value; break; } } if (num <= 0f) { return null; } Vector3 val = (corners[0] + corners[6]) * 0.5f; float y = corners[0].y; return (Vector3[])(object)new Vector3[4] { new Vector3(val.x - num, y, val.z - num), new Vector3(val.x + num, y, val.z - num), new Vector3(val.x + num, y, val.z + num), new Vector3(val.x - num, y, val.z + num) }; } private static void AddSnapPoints(Transform root, string[] names, Vector3[] positions) { //IL_0007: 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_0017: 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) for (int i = 0; i < positions.Length; i++) { GameObject val = new GameObject(names[i]) { tag = "snappoint" }; val.transform.SetParent(root, false); val.transform.localPosition = positions[i]; } } private static Vector3[] GetInnerCorners(Transform root, string prefabName) { //IL_008a: 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_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) string text = null; foreach (KeyValuePair<string, string> innerPart in innerParts) { if (prefabName.StartsWith(innerPart.Key, StringComparison.OrdinalIgnoreCase)) { text = innerPart.Value; break; } } Transform val = ((text == null) ? null : root.Find(text)); MeshFilter val2 = (((Object)(object)val == (Object)null) ? null : ((Component)val).GetComponent<MeshFilter>()); if ((Object)(object)val2 == (Object)null || (Object)(object)val2.sharedMesh == (Object)null) { return null; } bool any = false; Bounds bounds = default(Bounds); Encapsulate(ref bounds, ref any, val2.sharedMesh.bounds, root.worldToLocalMatrix * val.localToWorldMatrix); Vector3 size = ((Bounds)(ref bounds)).size; int num = 0; for (int i = 1; i < 3; i++) { if (((Vector3)(ref size))[i] < ((Vector3)(ref size))[num]) { num = i; } } int num2 = ((num == 0) ? 1 : 0); int num3 = ((num == 2) ? 1 : 2); Vector3[] array = (Vector3[])(object)new Vector3[4]; for (int j = 0; j < 4; j++) { Vector3 center = ((Bounds)(ref bounds)).center; Vector3 val3; float num4; if (j != 1 && j != 2) { val3 = ((Bounds)(ref bounds)).min; num4 = ((Vector3)(ref val3))[num2]; } else { val3 = ((Bounds)(ref bounds)).max; num4 = ((Vector3)(ref val3))[num2]; } ((Vector3)(ref center))[num2] = num4; float num5; if (j < 2) { val3 = ((Bounds)(ref bounds)).min; num5 = ((Vector3)(ref val3))[num3]; } else { val3 = ((Bounds)(ref bounds)).max; num5 = ((Vector3)(ref val3))[num3]; } ((Vector3)(ref center))[num3] = num5; array[j] = center; } return array; } private static void Encapsulate(ref Bounds bounds, ref bool any, Bounds local, Matrix4x4 toRoot) { //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) //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_0023: 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_0036: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0041: 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_0057: 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_007a: 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_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) Vector3 min = ((Bounds)(ref local)).min; Vector3 max = ((Bounds)(ref local)).max; Vector3 val = default(Vector3); for (int i = 0; i < 8; i++) { ((Vector3)(ref val))..ctor(((i & 1) == 0) ? min.x : max.x, ((i & 2) == 0) ? min.y : max.y, ((i & 4) == 0) ? min.z : max.z); Vector3 val2 = ((Matrix4x4)(ref toRoot)).MultiplyPoint3x4(val); if (!any) { bounds = new Bounds(val2, Vector3.zero); any = true; } else { ((Bounds)(ref bounds)).Encapsulate(val2); } } } private static Vector3[] GetCorners(Transform root) { //IL_0004: 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) //IL_008f: 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_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: 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_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: 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_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) bool any = false; Bounds bounds = default(Bounds); Collider[] componentsInChildren = ((Component)root).GetComponentsInChildren<Collider>(true); foreach (Collider val in componentsInChildren) { if (!val.isTrigger && IsActiveUnder(((Component)val).transform, root) && TryGetLocalBounds(val, out var bounds2)) { Encapsulate(ref bounds, ref any, bounds2, root.worldToLocalMatrix * ((Component)val).transform.localToWorldMatrix); } } if (!any) { return null; } Vector3 min = ((Bounds)(ref bounds)).min; Vector3 max = ((Bounds)(ref bounds)).max; return (Vector3[])(object)new Vector3[8] { new Vector3(min.x, min.y, min.z), new Vector3(max.x, min.y, min.z), new Vector3(max.x, min.y, max.z), new Vector3(min.x, min.y, max.z), new Vector3(min.x, max.y, min.z), new Vector3(max.x, max.y, min.z), new Vector3(max.x, max.y, max.z), new Vector3(min.x, max.y, max.z) }; } private static bool TryGetLocalBounds(Collider collider, out Bounds bounds) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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) //IL_0023: 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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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) //IL_006d: 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_0083: 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_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) bounds = default(Bounds); BoxCollider val = (BoxCollider)(object)((collider is BoxCollider) ? collider : null); if (val != null) { bounds = new Bounds(val.center, val.size); } else { SphereCollider val2 = (SphereCollider)(object)((collider is SphereCollider) ? collider : null); if (val2 != null) { bounds = new Bounds(val2.center, Vector3.one * (val2.radius * 2f)); } else { CapsuleCollider val3 = (CapsuleCollider)(object)((collider is CapsuleCollider) ? collider : null); if (val3 != null) { Vector3 val4 = Vector3.one * (val3.radius * 2f); ((Vector3)(ref val4))[val3.direction] = Mathf.Max(val3.height, val3.radius * 2f); bounds = new Bounds(val3.center, val4); } else { MeshCollider val5 = (MeshCollider)(object)((collider is MeshCollider) ? collider : null); if (val5 == null || !((Object)(object)val5.sharedMesh != (Object)null)) { return false; } bounds = val5.sharedMesh.bounds; } } } return true; } private static bool IsActiveUnder(Transform transform, Transform root) { Transform val = transform; while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)root) { if (!((Component)val).gameObject.activeSelf) { return false; } val = val.parent; } return true; } public static bool IsOwnSnapPoint(Transform child) { if (!((Component)child).CompareTag("snappoint")) { return false; } string name = ((Object)child).name; if (Array.IndexOf(CornerNames, name) < 0 && Array.IndexOf(InnerNames, name) < 0 && Array.IndexOf(OuterNames, name) < 0) { return Array.IndexOf(LidNames, name) >= 0; } return true; } public static bool IsOwnTopCorner(Transform child) { if (((Component)child).CompareTag("snappoint")) { return Array.IndexOf(CornerNames, ((Object)child).name) >= 4; } return false; } public static bool IsOwnLidCorner(Transform child) { if (((Component)child).CompareTag("snappoint")) { return Array.IndexOf(LidNames, ((Object)child).name) >= 0; } return false; } public static bool HasLidCorners(Transform root) { for (int i = 0; i < root.childCount; i++) { if (IsOwnLidCorner(root.GetChild(i))) { return true; } } return false; } public static bool IsSurfacePiece(string prefabName) { string[] array = surfacePieces; foreach (string value in array) { if (prefabName.StartsWith(value, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } public static bool Supports(GameObject piece) { WearNTear component = piece.GetComponent<WearNTear>(); if (!((Object)(object)component == (Object)null)) { return component.m_supports; } return true; } private static bool HasOwnSnapPoints(Transform root) { for (int i = 0; i < root.childCount; i++) { if (IsOwnSnapPoint(root.GetChild(i))) { return true; } } return false; } } [HarmonyPatch(typeof(ZNetScene), "Awake")] public static class ZNetSceneAwakePatch { private static void Postfix(ZNetScene __instance) { PieceConfig.Load(__instance); Plugin.Watcher?.Remember(); Snapping.ApplyAll(); } } [HarmonyPatch(typeof(Piece), "GetSnapPoints", new Type[] { typeof(List<Transform>) })] public static class PieceGetOwnSnapPointsPatch { private static void Prefix(List<Transform> points, out int __state) { __state = points.Count; } private static void Postfix(Piece __instance, List<Transform> points, int __state) { if (PieceConfig.AnyOff && points.Count > __state && PieceConfig.GetState(Utils.GetPrefabName(((Component)__instance).gameObject)) == false) { points.RemoveRange(__state, points.Count - __state); } } } [HarmonyPatch(typeof(Player), "FindClosestSnapPoints")] public static class PlayerFindClosestSnapPointsPatch { public static bool SkipUnsupportedTops; private static Transform surfacePoint; private static bool Prefix(Player __instance, Transform ghost, float maxSnapDistance, ref Transform a, ref Transform b, ref bool __result) { SkipUnsupportedTops = !Snapping.Supports(((Component)ghost).gameObject); if (!Snapping.HasLidCorners(ghost)) { return true; } __result = FindLidPairs(__instance, ghost, maxSnapDistance, out a, out b); return false; } private static bool FindLidPairs(Player player, Transform ghost, float maxSnapDistance, out Transform a, out Transform b) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_009c: 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) List<Transform> tempSnapPoints = player.m_tempSnapPoints1; List<Transform> tempSnapPoints2 = player.m_tempSnapPoints2; tempSnapPoints.Clear(); ((Component)ghost).GetComponent<Piece>().GetSnapPoints(tempSnapPoints); tempSnapPoints2.Clear(); player.m_tempPieces.Clear(); Piece.GetSnapPoints(ghost.position, 10f, tempSnapPoints2, player.m_tempPieces); a = null; b = null; float num = float.MaxValue; for (int i = 0; i < tempSnapPoints.Count; i++) { if (player.m_manualSnapPoint >= 0 && i != player.m_manualSnapPoint) { continue; } bool flag = Snapping.IsOwnLidCorner(tempSnapPoints[i]); foreach (Transform item in tempSnapPoints2) { if (Snapping.IsOwnLidCorner(item) == flag) { float num2 = Vector3.Distance(item.position, tempSnapPoints[i].position); if (num2 <= maxSnapDistance && num2 < num) { num = num2; a = tempSnapPoints[i]; b = item; } } } } return (Object)(object)a != (Object)null; } private static void Postfix(Transform ghost, ref Transform a, ref Transform b, bool __result) { //IL_0029: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0057: 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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown //IL_0096: Unknown result type (might be due to invalid IL or missing references) if (__result && !((Object)(object)b == (Object)null) && !Snapping.IsOwnSnapPoint(b) && Snapping.IsSurfacePiece(Utils.GetPrefabName(((Component)ghost).gameObject))) { Vector3 lastNormal = PlayerPieceRayTestPatch.LastNormal; Vector3 val = b.position - (a.position - ghost.position); Vector3 position = b.position + lastNormal * Vector3.Dot(ghost.position - val, lastNormal); if ((Object)(object)surfacePoint == (Object)null) { GameObject val2 = new GameObject("Snap Points surface point"); Object.DontDestroyOnLoad((Object)(object)val2); surfacePoint = new GameObject("surface point").transform; surfacePoint.SetParent(val2.transform, false); } surfacePoint.position = position; b = surfacePoint; } } private static void Finalizer() { SkipUnsupportedTops = false; } } [HarmonyPatch(typeof(Player), "PieceRayTest")] public static class PlayerPieceRayTestPatch { public static Vector3 LastNormal = Vector3.forward; private static void Postfix(ref Vector3 normal, bool __result) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (__result) { LastNormal = normal; } } } [HarmonyPatch(typeof(Piece), "GetSnapPoints", new Type[] { typeof(Vector3), typeof(float), typeof(List<Transform>), typeof(List<Piece>) })] public static class PieceGetSnapPointsPatch { private static void Postfix(List<Transform> points) { if (PlayerFindClosestSnapPointsPatch.SkipUnsupportedTops) { points.RemoveAll((Transform point) => Snapping.IsOwnTopCorner(point) && !Snapping.Supports(((Component)point.parent).gameObject)); } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } } namespace Kriona.Shared { internal class ConfigMirror { private readonly ConfigFile config; private readonly Action changed; private bool syncing; public ConfigMirror(ConfigFile config, Action changed) { this.config = config; this.changed = changed; config.SaveOnConfigSet = false; config.SettingChanged += OnSettingChanged; } public ConfigEntry<T> Bind<T>(string section, string key, T defaultValue, string description, AcceptableValueBase acceptableValues, int? order, string displayName) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes(); configurationManagerAttributes.Order = order; configurationManagerAttributes.DispName = displayName; return config.Bind<T>(section, key, defaultValue, new ConfigDescription(description, acceptableValues, new object[1] { configurationManagerAttributes })); } public void Remove(ConfigEntryBase entry) { config.Remove(entry.Definition); } public void Sync(Action apply) { syncing = true; try { apply(); } finally { syncing = false; } } public static void SetDisplayName(ConfigEntryBase entry, string displayName) { object[] tags = entry.Description.Tags; for (int i = 0; i < tags.Length; i++) { if (tags[i] is ConfigurationManagerAttributes configurationManagerAttributes) { configurationManagerAttributes.DispName = displayName; } } } private void OnSettingChanged(object sender, SettingChangedEventArgs args) { if (!syncing) { changed(); } } } internal sealed class ConfigurationManagerAttributes { public int? Order; public string DispName; } internal class ConfigWatcher : IDisposable { private const float ReloadDelay = 0.5f; private readonly string path; private readonly Action reload; private readonly ManualLogSource log; private readonly string pluginName; private readonly FileSystemWatcher watcher; private string knownContents; private volatile bool fileChanged; private float reloadTime = -1f; public ConfigWatcher(string path, Action reload, ManualLogSource log, string pluginName) { this.path = path; this.reload = reload; this.log = log; this.pluginName = pluginName; Remember(); try { watcher = new FileSystemWatcher(Path.GetDirectoryName(path), Path.GetFileName(path)); watcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite; watcher.Changed += delegate { fileChanged = true; }; watcher.Created += delegate { fileChanged = true; }; watcher.Renamed += delegate { fileChanged = true; }; watcher.EnableRaisingEvents = true; } catch (Exception ex) { watcher = null; log.LogWarning((object)("Couldn't watch " + path + " for changes, so changes made to it while Valheim is running aren't read: " + ex.Message)); } } public ConfigWatcher(ConfigFile config, ManualLogSource log, string pluginName) : this(config.ConfigFilePath, delegate { ReloadConfig(config); }, log, pluginName) { } private static void ReloadConfig(ConfigFile config) { bool saveOnConfigSet = config.SaveOnConfigSet; config.SaveOnConfigSet = false; try { config.Reload(); } finally { config.SaveOnConfigSet = saveOnConfigSet; } if (saveOnConfigSet && !MatchesFile(config)) { config.Save(); } } private static bool MatchesFile(ConfigFile config) { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown Dictionary<ConfigDefinition, string> dictionary = new Dictionary<ConfigDefinition, string>(); string text = string.Empty; string[] array = File.ReadAllLines(config.ConfigFilePath); for (int i = 0; i < array.Length; i++) { string text2 = array[i].Trim(); if (text2.StartsWith("#")) { continue; } if (text2.StartsWith("[") && text2.EndsWith("]")) { text = text2.Substring(1, text2.Length - 2); continue; } string[] array2 = text2.Split(new char[1] { '=' }, 2); if (array2.Length == 2) { dictionary[new ConfigDefinition(text, array2[0].Trim())] = array2[1].Trim(); } } foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in config) { if (!dictionary.TryGetValue(item.Key, out var value)) { return false; } try { if (!object.Equals(TomlTypeConverter.ConvertToValue(value, item.Value.SettingType), item.Value.BoxedValue)) { return false; } } catch (Exception) { return false; } } return true; } public void Update() { if (fileChanged) { fileChanged = false; reloadTime = Time.realtimeSinceStartup + 0.5f; } if (reloadTime < 0f || Time.realtimeSinceStartup < reloadTime) { return; } reloadTime = -1f; string text; try { text = File.ReadAllText(path); } catch (FileNotFoundException) { return; } catch (IOException) { reloadTime = Time.realtimeSinceStartup + 0.5f; return; } if (text == knownContents) { return; } reload(); Remember(); if (pluginName != null) { log.LogInfo((object)("Reloaded " + Path.GetFileName(path))); MessageHud instance = MessageHud.instance; if (instance != null) { instance.ShowMessage((MessageType)1, pluginName + ": config reloaded", 0, (Sprite)null, false, true); } } } public void Remember() { try { knownContents = File.ReadAllText(path); } catch (IOException) { knownContents = null; } } public void Dispose() { watcher?.Dispose(); } } internal class StateEntries { public const string Inherit = "inherit"; private static readonly AcceptableValueList<string> values = new AcceptableValueList<string>(new string[3] { "inherit", "true", "false" }); private readonly ConfigMirror mirror; private readonly string help; private readonly Dictionary<string, ConfigEntry<string>> entries = new Dictionary<string, ConfigEntry<string>>(StringComparer.OrdinalIgnoreCase); private readonly HashSet<string> set = new HashSet<string>(StringComparer.OrdinalIgnoreCase); public StateEntries(ConfigMirror mirror, string help) { this.mirror = mirror; this.help = help; } public void Set(string section, string key, string displayName, bool? state) { string entryName = GetEntryName(key, displayName); if (entries.TryGetValue(key, out var value) && ((ConfigEntryBase)value).Definition.Section != section) { mirror.Remove((ConfigEntryBase)(object)value); entries.Remove(key); value = null; } if (value == null) { try { value = mirror.Bind(section, key, "inherit", "Prefab " + key + " - " + help, (AcceptableValueBase)(object)values, null, entryName); } catch (ArgumentException) { return; } entries[key] = value; } else { ConfigMirror.SetDisplayName((ConfigEntryBase)(object)value, entryName); } value.Value = Format(state); set.Add(key); } public void RemoveUnset() { List<string> list = new List<string>(); foreach (KeyValuePair<string, ConfigEntry<string>> entry in entries) { if (!set.Contains(entry.Key)) { mirror.Remove((ConfigEntryBase)(object)entry.Value); list.Add(entry.Key); } } foreach (string item in list) { entries.Remove(item); } set.Clear(); } public bool TryGetState(string key, out bool? state) { state = null; if (!entries.TryGetValue(key, out var value)) { return false; } if (bool.TryParse(value.Value, out var result)) { state = result; } return true; } public static string Format(bool? state) { if (!state.HasValue) { return "inherit"; } if (!state.Value) { return "false"; } return "true"; } private static string GetEntryName(string key, string displayName) { string text = displayName.Trim(); if (text.Length == 0 || text.Equals(key, StringComparison.OrdinalIgnoreCase)) { return key; } return text + " (" + key + ")"; } } }