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 Timber v0.2.2
plugins/Timber/Timber.Core.dll
Decompiled 18 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using Microsoft.CodeAnalysis; [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("ExtraPotions")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright (C) 2026 expDARE (ExtraPotions Meadworks)")] [assembly: AssemblyFileVersion("0.2.2.0")] [assembly: AssemblyInformationalVersion("0.2.2")] [assembly: AssemblyProduct("Timber.Core")] [assembly: AssemblyTitle("Timber.Core")] [assembly: AssemblyVersion("0.2.2.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 ExtraPotions.Timber { public static class ReferenceCameraValues { public const float NativeReach = 5f; public const float DefaultExtraReach = 95f; public const float DefaultPickupRange = 10f; private static readonly Dictionary<string, string> Direct = new Dictionary<string, string>(StringComparer.Ordinal) { ["General.Camera Range Multiplier"] = "Range Multiplier", ["General.Camera Terrain Clearance"] = "Terrain Clearance", ["General.Resource Pickup Range"] = "Pickup Range", ["General.Move With Respect To World"] = "Move With Respect To World", ["Controls.Invert Mouse Look Horizontal"] = "Invert Mouse Horizontal", ["Controls.Invert Mouse Look Vertical"] = "Invert Mouse Vertical", ["Controls.Invert Controller Look Horizontal"] = "Invert Pad Horizontal", ["Controls.Invert Controller Look Vertical"] = "Invert Pad Vertical", ["Helmet Light.Follow Dvergr Circlet Light"] = "Circlet Light", ["Helmet Light.Camera Light Color"] = "Circlet Color", ["Helmet Light.Camera Light Shadows"] = "Circlet Shadows", ["Hotkeys.Toggle build mode"] = "Toggle Key", ["Mist.Demister Follow Camera"] = "Demister Follow Camera", ["Mist.Demister Range Multiplier"] = "Demister Range Multiplier" }; public static IReadOnlyDictionary<string, string> Map(IReadOnlyDictionary<string, string> source, float width, float height, ICollection<string> notes, ICollection<string> errors) { Dictionary<string, string> values = new Dictionary<string, string>(StringComparer.Ordinal); foreach (KeyValuePair<string, string> item in Direct) { if (source.TryGetValue(item.Key, out string value)) { values["Build Camera." + item.Value] = value; } } Try("General.Distance Can Build From Avatar", delegate(string text) { values["Build Camera.Extra Reach"] = Text(Clamp(Number(text) - 5f, 0f, 95f)); notes.Add("Extra Reach = avatar reach minus native 5 m, clamped to 0–95 m; Timber measures reach from the camera."); }); if (source.ContainsKey("General.Distance Can Build From Workbench")) { notes.Add("Workbench distance is not imported: Timber's camera area uses the station's real range times Range Multiplier."); } Try("General.Camera Move Speed Multiplier", delegate(string text) { values["Build Camera.Speed"] = Text(Clamp(10f * Number(text) / 3f, 1f, 100f)); notes.Add("Camera speed = 10 × reference multiplier / 3, clamped to 1–100 m/s."); }); Try("General.Restriction Mode", delegate(string text) { string text2 = text.Trim(); if (text2 != "Off" && text2 != "CameraNeedsCoziness" && text2 != "CameraPickUpNeedsCoziness") { throw new FormatException("Unknown restriction mode"); } string value3; int num2 = ((!source.TryGetValue("General.Minimum Comfort Level", out value3)) ? 1 : int.Parse(value3, CultureInfo.InvariantCulture)); if (num2 < 0 || num2 > 50) { throw new FormatException("Comfort must be 0–50"); } values["Build Camera.Entry Needs Resting"] = "false"; values["Build Camera.Pickup Needs Resting"] = "false"; values["Build Camera.Entry Min Comfort"] = ((text2 == "CameraNeedsCoziness") ? num2.ToString(CultureInfo.InvariantCulture) : "0"); values["Build Camera.Pickup Min Comfort"] = ((text2 == "Off") ? "0" : num2.ToString(CultureInfo.InvariantCulture)); notes.Add("Reference restriction mode maps to entry/pickup comfort; Timber checks entry needs only on entry."); }); if (source.ContainsKey("Helmet Light.Camera Light Left/Right Offset") || source.ContainsKey("Helmet Light.Camera Light Up/Down Offset") || source.ContainsKey("Helmet Light.Camera Light Forward/Back Offset")) { Try("circlet offset", delegate { float num2 = Read("Helmet Light.Camera Light Left/Right Offset", 0f); float num3 = Read("Helmet Light.Camera Light Up/Down Offset", -0.08f); float num4 = Read("Helmet Light.Camera Light Forward/Back Offset", 0.65f); if (Math.Abs(num2) > 5f || Math.Abs(num3) > 5f || Math.Abs(num4) > 5f) { throw new FormatException("Circlet offsets must be -5–5 m"); } values["Build Camera.Circlet Offset"] = Vector(num2, num3, num4); }, always: true); } if (source.ContainsKey("HUD.Pickup Blocked HUD X") || source.ContainsKey("HUD.Pickup Blocked HUD Y")) { Try("pickup HUD position", delegate { float num2 = Read("HUD.Pickup Blocked HUD X", 0.3f); float num3 = Read("HUD.Pickup Blocked HUD Y", 0.3f); if (num2 < 0f || num2 > 1f || num3 < 0f || num3 > 1f || width <= 0f || height <= 0f) { throw new FormatException("Invalid source ratio or HUD size"); } values["Build Camera.Pickup Panel Position"] = "{\"x\":" + Text((num2 - 0.5f) * width) + ",\"y\":" + Text((num3 - 1f) * height) + "}"; notes.Add("HUD screen ratios converted to top-center offset at " + Text(width) + " × " + Text(height) + " UI units; kit font size retained."); }, always: true); } string[] array = new string[2] { "Intensity", "Range" }; foreach (string axis in array) { Try("Helmet Light.Camera Light " + axis + " Multiplier", delegate(string text) { if (Number(text) == 1f) { values["Build Camera.Circlet " + axis] = "0"; } else { errors.Add("Circlet " + axis + " multiplier " + text + " cannot map exactly to an absolute/native value. Choose a Timber absolute value; source is preserved."); } }); } if (source.TryGetValue("General.Verbose Logging", out string value2) && Toggle(value2)) { notes.Add("Verbose logging is not imported. Set Crucible's per-product logging override to timber=Verbose if wanted."); } return values; float Read(string key, float fallback) { if (!source.TryGetValue(key, out string value3)) { return fallback; } return Number(value3); } void Try(string key, Action<string> apply, bool always = false) { if (!source.TryGetValue(key, out string value3) && !always) { return; } try { apply(value3 ?? ""); } catch (Exception ex) when (ex is FormatException || ex is OverflowException) { errors.Add(key + ": " + ex.Message); } } } public static bool Toggle(string value) { if (string.Equals(value.Trim(), "On", StringComparison.OrdinalIgnoreCase)) { return true; } if (string.Equals(value.Trim(), "Off", StringComparison.OrdinalIgnoreCase)) { return false; } return bool.Parse(value.Trim()); } private static float Number(string value) { float num = float.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); if (float.IsNaN(num) || float.IsInfinity(num)) { throw new FormatException("Nonfinite value"); } return num; } private static string Text(float value) { return value.ToString("R", CultureInfo.InvariantCulture); } private static float Clamp(float value, float min, float max) { return Math.Max(min, Math.Min(max, value)); } private static string Vector(float x, float y, float z) { return "{\"x\":" + Text(x) + ",\"y\":" + Text(y) + ",\"z\":" + Text(z) + "}"; } } public static class TimberCore { public const string PluginGuid = "com.meadworks.timber"; public const string ProductName = "Timber"; public const string ProductVersion = "0.2.2"; public const string Family = "Forge"; public const string ProtectedPieceKey = "timber.ignoreSupport"; } } namespace ExtraPotions.Timber.Config { public readonly struct LockTarget { public string Id { get; } public bool Lockable { get; } public LockTarget(string id, bool lockable) { Id = id; Lockable = lockable; } } public sealed class LockList { private readonly HashSet<string> locked; public static LockList Empty { get; } = new LockList(Array.Empty<string>(), Array.Empty<string>(), Array.Empty<string>()); public IReadOnlyList<string> Locked { get; } public IReadOnlyList<string> Unknown { get; } public IReadOnlyList<string> NotLockable { get; } private LockList(IReadOnlyList<string> lockedIds, IReadOnlyList<string> unknown, IReadOnlyList<string> notLockable) { Locked = lockedIds; Unknown = unknown; NotLockable = notLockable; locked = new HashSet<string>(lockedIds, StringComparer.OrdinalIgnoreCase); } public static LockList Parse(string? text, Func<string, LockTarget?> find) { List<string> list = new List<string>(); List<string> list2 = new List<string>(); List<string> list3 = new List<string>(); string[] array = (text ?? "").Split(','); for (int i = 0; i < array.Length; i++) { string text2 = array[i].Trim(); if (text2.Length != 0) { LockTarget? lockTarget = find(text2); List<string> list4 = ((!lockTarget.HasValue) ? list2 : (lockTarget.Value.Lockable ? list : list3)); string text3 = lockTarget?.Id ?? text2; if (!list4.Contains<string>(text3, StringComparer.OrdinalIgnoreCase)) { list4.Add(text3); } } } if (list.Count + list2.Count + list3.Count != 0) { return new LockList(list, list2, list3); } return Empty; } public bool IsLocked(string? id) { if (id != null) { return locked.Contains(id.Trim()); } return false; } public string Describe() { string text = Locked.Count + " locked"; if (Unknown.Count > 0) { text = text + "; unknown: " + string.Join(", ", Unknown); } if (NotLockable.Count > 0) { text = text + "; not lockable: " + string.Join(", ", NotLockable); } return text; } } public static class LockedValues { public static string Encode(IEnumerable<KeyValuePair<string, string>> values) { if (values == null) { throw new ArgumentNullException("values"); } return string.Join(";", values.Select<KeyValuePair<string, string>, string>((KeyValuePair<string, string> v) => Escape(v.Key) + "=" + Escape(v.Value ?? ""))); } public static IReadOnlyDictionary<string, string> Decode(string? text) { Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); if (string.IsNullOrEmpty(text)) { return dictionary; } foreach (string item in Split(text, ';')) { List<string> list = Split(item, '=').ToList(); if (list.Count == 2) { string text2 = Unescape(list[0]); string text3 = Unescape(list[1]); if (!string.IsNullOrWhiteSpace(text2) && text3 != null && !dictionary.ContainsKey(text2.Trim())) { dictionary.Add(text2.Trim(), text3); } } } return dictionary; } public static string Compose(LockList list, Func<string, string?> ownText) { if (list == null) { throw new ArgumentNullException("list"); } if (ownText == null) { throw new ArgumentNullException("ownText"); } return Encode(from id in list.Locked select new KeyValuePair<string, string>(id, ownText(id)) into p where p.Value != null select new KeyValuePair<string, string>(p.Key, p.Value)); } private static string Escape(string text) { StringBuilder stringBuilder = new StringBuilder(text.Length); foreach (char c in text) { if (c == '\\' || c == ';' || c == '=') { stringBuilder.Append('\\'); } stringBuilder.Append(c); } return stringBuilder.ToString(); } private static IEnumerable<string> Split(string text, char separator) { int num = 0; for (int i = 0; i < text.Length; i++) { if (text[i] == '\\') { i++; } else if (text[i] == separator) { yield return text.Substring(num, i - num); num = i + 1; } } yield return text.Substring(num); } private static string? Unescape(string text) { StringBuilder stringBuilder = new StringBuilder(text.Length); for (int i = 0; i < text.Length; i++) { if (text[i] == '\\' && ++i >= text.Length) { return null; } stringBuilder.Append(text[i]); } return stringBuilder.ToString(); } } public readonly struct PlayerLock { public bool Locked { get; } public string? ServerText { get; } public PlayerLock(bool locked, string? serverText) { Locked = locked; ServerText = (locked ? serverText : null); } public override string ToString() { if (!Locked) { return "Own"; } return "Locked (" + ServerText + ")"; } } public static class PlayerLocks { public static PlayerLock Evaluate(string id, bool serverBinds, LockList list, IReadOnlyDictionary<string, string> values) { if (list == null) { throw new ArgumentNullException("list"); } if (values == null) { throw new ArgumentNullException("values"); } if (!serverBinds || !list.IsLocked(id) || !values.TryGetValue(id.Trim(), out string value)) { return new PlayerLock(locked: false, null); } return new PlayerLock(locked: true, value); } } } namespace ExtraPotions.Timber.Adopted { public static class SupportWearKernel { public static bool Swap(ref bool field, bool noSupportWear) { bool result = field; field = noSupportWear; return result; } public static void Restore(ref bool field, bool original) { if (!field) { field = original; } } } }
plugins/Timber/Timber.dll
Decompiled 18 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using ExtraPotions.Meadworks.Contracts; using ExtraPotions.Meadworks.Crucible; using ExtraPotions.Meadworks.Crucible.UI; using ExtraPotions.Timber.Adopted; using ExtraPotions.Timber.Config; using ExtraPotions.Timber.Runtime; using HarmonyLib; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using TMPro; using Timber.Camera; using Timber.Flooring; using Timber.Repair; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_guiutils")] [assembly: IgnoresAccessChecksTo("assembly_utils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("ExtraPotions")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright (C) 2026 expDARE (ExtraPotions Meadworks)")] [assembly: AssemblyFileVersion("0.2.2.0")] [assembly: AssemblyInformationalVersion("0.2.2")] [assembly: AssemblyProduct("Timber")] [assembly: AssemblyTitle("Timber")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.2.2.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 Timber.Repair { internal static class AreaRepairModule { internal const int MaxRepairs = 64; private static CameraBindings? bindings; private static CameraValue<bool>? enabled; internal static void Initialize(ConfigFile config) { Reset(); bindings = new CameraBindings(config); enabled = bindings.Bind("Repair", "Area Repair", value: false, "After one successful hammer repair, repair damaged pieces touching that piece (at most 64), without spreading through the building. Each neighbor needs its native crafting station and ward access. Only the original swing costs stamina, eitr and hammer wear. A healthy or refused center repairs no neighbors. Timber steps aside while OpenKeep's Area Repair is active."); } internal static void Reset() { bindings?.Dispose(); bindings = null; enabled = null; RepairNeighbours.Reset(); } internal static bool Allowed(Player player) { if (!Plugin.Active || !Plugin.AllowsUi || enabled == null || !enabled.Value || !Object.op_Implicit((Object)(object)player) || (Object)(object)player != (Object)(object)Player.m_localPlayer || ((Character)player).IsDead() || ((Character)player).InCutscene() || ((Character)player).IsTeleporting()) { return false; } ZNetView component = ((Component)player).GetComponent<ZNetView>(); if (!Object.op_Implicit((Object)(object)component) || !component.IsValid() || !component.IsOwner()) { return false; } if (!Chainloader.PluginInfos.TryGetValue("milkyteam.openkeep", out var value)) { return true; } BaseUnityPlugin instance = value.Instance; return SourceAllows(Object.op_Implicit((Object)(object)instance) ? instance.Config : null); } internal static bool SourceAllows(ConfigFile? source) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown ConfigEntry<bool> val = default(ConfigEntry<bool>); if (source != null && source.TryGetEntry<bool>(new ConfigDefinition("8. Homestead", "Area Repair"), ref val)) { return !val.Value; } return false; } internal static void Run(Player player, WearNTear center) { //IL_0070: 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_00a8: 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) int num = 0; foreach (WearNTear item in RepairNeighbours.Around(center)) { if (num >= 64) { break; } if (!Object.op_Implicit((Object)(object)item) || !Object.op_Implicit((Object)(object)item.m_piece) || !Object.op_Implicit((Object)(object)item.m_nview) || !item.m_nview.IsValid()) { continue; } Piece piece = item.m_piece; if (StationAllows(player, piece) && PrivateArea.CheckAccess(((Component)piece).transform.position, 0f, false, false) && item.Repair()) { EffectList placeEffect = piece.m_placeEffect; if (placeEffect != null) { placeEffect.Create(((Component)piece).transform.position, ((Component)piece).transform.rotation, (Transform)null, 1f, -1, ((Character)player).GetZDOID()); } num++; } } if (num > 0) { ((Character)player).Message((MessageType)1, TimberText.Format("area_repair_done", num), 0, (Sprite)null, false); } } private static bool StationAllows(Player player, Piece piece) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) if (!player.PlacementCostDisabled && Object.op_Implicit((Object)(object)piece.m_craftingStation) && !Object.op_Implicit((Object)(object)CraftingStation.HaveBuildStationInRange(piece.m_craftingStation.m_name, ((Component)player).transform.position))) { if (Object.op_Implicit((Object)(object)ZoneSystem.instance)) { return ZoneSystem.instance.GetGlobalKey((GlobalKeys)27); } return false; } return true; } } [HarmonyPatch(typeof(Player), "Repair")] internal static class AreaRepairPatch { internal struct Attempt { internal WearNTear Center; internal float Stamp; } [HarmonyPrefix] private static void Prefix(Player __instance, out Attempt __state) { __state = default(Attempt); if (AreaRepairModule.Allowed(__instance)) { Piece hoveringPiece = __instance.GetHoveringPiece(); WearNTear val = (Object.op_Implicit((Object)(object)hoveringPiece) ? ((Component)hoveringPiece).GetComponent<WearNTear>() : null); if (Object.op_Implicit((Object)(object)val)) { __state = new Attempt { Center = val, Stamp = val.m_lastRepair }; } } } [HarmonyPostfix] private static void Postfix(Player __instance, Attempt __state, bool __runOriginal) { if (!__runOriginal || !Object.op_Implicit((Object)(object)__state.Center) || !AreaRepairModule.Allowed(__instance)) { return; } Piece hoveringPiece = __instance.GetHoveringPiece(); if (!Object.op_Implicit((Object)(object)hoveringPiece) || (Object)(object)((Component)hoveringPiece).GetComponent<WearNTear>() != (Object)(object)__state.Center || __state.Center.m_lastRepair <= __state.Stamp) { return; } try { AreaRepairModule.Run(__instance, __state.Center); } catch (Exception ex) { Debug.LogWarning((object)("Timber area repair: " + ex.GetType().Name + ": " + ex.Message)); } } } internal static class RepairNeighbours { public const float Margin = 0.3f; private const int MaxOwnColliders = 64; private const int MaxCandidates = 256; private static readonly Collider[] hits = (Collider[])(object)new Collider[256]; private static readonly List<Collider> own = new List<Collider>(); private static int mask; public static List<WearNTear> Around(WearNTear piece) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) HashSet<WearNTear> hashSet = new HashSet<WearNTear>(); try { ((Component)piece).GetComponentsInChildren<Collider>(false, own); for (int i = 0; i < own.Count && i < 64; i++) { if (hashSet.Count >= 256) { break; } Collider val = own[i]; if (Object.op_Implicit((Object)(object)val) && val.enabled && ((Component)val).gameObject.activeInHierarchy && Solid(val)) { Overlap(piece, val, hashSet); } } List<WearNTear> list = new List<WearNTear>(hashSet); Vector3 centre = ((Component)piece).transform.position; list.Sort((WearNTear a, WearNTear b) => Distance(a, centre).CompareTo(Distance(b, centre))); return list; } finally { Reset(); } } internal static void Reset() { own.Clear(); Array.Clear(hits, 0, hits.Length); } private static void Overlap(WearNTear piece, Collider collider, HashSet<WearNTear> found) { //IL_000c: 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) Box(collider, out var centre, out var rotation, out var half); int num = Physics.OverlapBoxNonAlloc(centre, half, hits, rotation, Mask(), (QueryTriggerInteraction)1); for (int i = 0; i < num; i++) { if (found.Count >= 256) { break; } if (Solid(hits[i])) { WearNTear componentInParent = ((Component)hits[i]).GetComponentInParent<WearNTear>(); if ((Object)(object)componentInParent != (Object)null && (Object)(object)componentInParent != (Object)(object)piece) { found.Add(componentInParent); } } } } private static void Box(Collider collider, out Vector3 centre, out Quaternion rotation, out Vector3 half) { //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_005b: 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) //IL_0063: 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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: 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_0046: 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) //IL_007d: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: 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_00a1: Unknown result type (might be due to invalid IL or missing references) BoxCollider val = (BoxCollider)(object)((collider is BoxCollider) ? collider : null); Vector3 v; if (val != null) { Transform transform = ((Component)val).transform; rotation = transform.rotation; centre = transform.position + transform.TransformVector(val.center); v = Vector3.Scale(transform.lossyScale, val.size); } else { rotation = Quaternion.identity; Bounds bounds = collider.bounds; centre = ((Bounds)(ref bounds)).center; bounds = collider.bounds; v = ((Bounds)(ref bounds)).size; } half = (Abs(v) + Vector3.one * 0.3f) * 0.5f; } private static bool Solid(Collider collider) { if (!collider.isTrigger) { return (Object)(object)collider.attachedRigidbody == (Object)null; } return false; } private static Vector3 Abs(Vector3 v) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) return new Vector3(Mathf.Abs(v.x), Mathf.Abs(v.y), Mathf.Abs(v.z)); } private static float Distance(WearNTear piece, Vector3 centre) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //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) //IL_0011: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ((Component)piece).transform.position - centre; return ((Vector3)(ref val)).sqrMagnitude; } private static int Mask() { if (mask == 0) { mask = LayerMask.GetMask(new string[5] { "piece", "piece_nonsolid", "Default", "static_solid", "Default_small" }); } return mask; } } } namespace Timber.Flooring { public static class FirePlacement { private readonly struct PlacementFlags { private readonly bool notOnWood; private readonly bool groundOnly; private readonly bool groundPiece; public PlacementFlags(Piece piece) { notOnWood = piece.m_notOnWood; groundOnly = piece.m_groundOnly; groundPiece = piece.m_groundPiece; } public void Restore(Piece piece) { if (!piece.m_notOnWood) { piece.m_notOnWood = notOnWood; } if (!piece.m_groundOnly) { piece.m_groundOnly = groundOnly; } if (!piece.m_groundPiece) { piece.m_groundPiece = groundPiece; } } } private static readonly Dictionary<string, PlacementFlags> original = new Dictionary<string, PlacementFlags>(StringComparer.Ordinal); public static void ApplyAll() { if ((Object)(object)ZNetScene.instance == (Object)null) { return; } Dictionary<string, Piece> dictionary = FirePrefabs.Listed(); foreach (KeyValuePair<string, Piece> item in dictionary) { Allow(item.Key, item.Value); } foreach (KeyValuePair<string, PlacementFlags> item2 in original) { if (!dictionary.ContainsKey(item2.Key)) { Restore(item2.Key, item2.Value); } } RefreshGhost(); } public static void Reset() { foreach (KeyValuePair<string, PlacementFlags> item in original) { Restore(item.Key, item.Value); } RefreshGhost(); original.Clear(); } private static void Allow(string name, Piece piece) { if (!original.ContainsKey(name)) { original[name] = new PlacementFlags(piece); } piece.m_notOnWood = false; piece.m_groundOnly = false; piece.m_groundPiece = false; } private static void Restore(string name, PlacementFlags flags) { Piece val = FirePrefabs.Exact(name); if ((Object)(object)val != (Object)null) { flags.Restore(val); } } private static void RefreshGhost() { Player localPlayer = Player.m_localPlayer; GameObject val = (((Object)(object)localPlayer != (Object)null) ? localPlayer.m_placementGhost : null); Piece val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<Piece>() : null); Piece val3 = (((Object)(object)val2 != (Object)null) ? FirePrefabs.Exact(((Object)val).name) : null); if ((Object)(object)val3 != (Object)null && original.ContainsKey(((Object)val3).name)) { val2.m_notOnWood = val3.m_notOnWood; val2.m_groundOnly = val3.m_groundOnly; val2.m_groundPiece = val3.m_groundPiece; } } } public static class FirePrefabs { public static Dictionary<string, Piece> Listed() { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Invalid comparison between Unknown and I4 Dictionary<string, Piece> dictionary = new Dictionary<string, Piece>(StringComparer.Ordinal); if ((!FiresRuntime.Active && !FiresRuntime.SmeltersActive) || (Object)(object)ZNetScene.instance == (Object)null) { return dictionary; } foreach (GameObject value in ZNetScene.instance.m_namedPrefabs.Values) { if (!((Object)(object)value == (Object)null)) { Piece component = value.GetComponent<Piece>(); if ((Object)(object)component != (Object)null && ((FiresRuntime.Active && ((int)component.m_comfortGroup == 1 || (Object)(object)value.GetComponent<Fireplace>() != (Object)null)) || (FiresRuntime.SmeltersActive && (Object)(object)value.GetComponent<Smelter>() != (Object)null))) { dictionary[((Object)value).name] = component; } } } return dictionary; } public static Piece? Exact(string name) { GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(name) : null); if (!((Object)(object)val != (Object)null)) { return null; } return val.GetComponent<Piece>(); } } public static class FiresRuntime { [HarmonyPatch(typeof(ZNetScene), "Awake")] private static class SceneReady { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix() { if (Plugin.Ready) { FirePlacement.ApplyAll(); FloorRoofTags.ApplyAll(); } } } [HarmonyPatch(typeof(ZNetScene), "OnDestroy")] private static class SceneEnding { [HarmonyPrefix] private static void Prefix() { FirePlacement.Reset(); FloorRoofTags.Reset(); sceneId = 0; prefabCount = -1; next = 0f; } } private static CameraBindings? bindings; private static CameraValue<bool>? enabled; private static CameraValue<bool>? roofs; private static CameraValue<bool>? smelters; private static CameraValue<bool>? rainProtection; private static bool appliedRoofs; private static bool appliedSmelters; private static bool resolved; private static bool flooringPresent; private static bool applied; private static bool openkeepPresent; private static ConfigEntry<string>? openkeepWood; private static int sceneId; private static int prefabCount = -1; private static float next; private static long noticed = -1L; private static SourceMod? source; public static bool Active { get { if (resolved && Plugin.Active && !flooringPresent && (!openkeepPresent || (openkeepWood != null && string.IsNullOrWhiteSpace(openkeepWood.Value))) && enabled != null) { return enabled.Value; } return false; } } public static bool RoofsActive { get { if (resolved && Plugin.Active && !flooringPresent && roofs != null) { return roofs.Value; } return false; } } public static bool SmeltersActive { get { if (resolved && Plugin.Active && !flooringPresent && smelters != null) { return smelters.Value; } return false; } } public static bool RainProtectionActive { get { if (resolved && Plugin.Active && !flooringPresent && rainProtection != null) { return rainProtection.Value; } return false; } } public static void Initialize(ConfigFile config) { bindings = new CameraBindings(config); enabled = bindings.Bind("Flooring", "Fires On Floors", value: true, "Allow Fireplace and Fire comfort-group pieces on floors. Other placement, support, smoke and fire-spread rules remain native."); roofs = bindings.Bind("Flooring", "Floors Are Roofs", value: true, "Floors count as a roof for the space below them, sheltering it from rain. Off: floors work as in the game."); smelters = bindings.Bind("Flooring", "Smelters On Floors", value: true, "Smelters can be placed on floors, and a smelter on a floor does not break from lack of support. Other damage and material costs are unchanged."); rainProtection = bindings.Bind("Flooring", "Floors Dont Decay", value: true, "Floors do not take rain damage. They still look wet, need support, and can burn or be damaged by fire, ash and attacks."); } public static void ResolveSources() { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown flooringPresent = Chainloader.PluginInfos.ContainsKey("com.jekkle.valheim.carturflooring"); openkeepPresent = Chainloader.PluginInfos.TryGetValue("milkyteam.openkeep", out var value); BaseUnityPlugin val = (openkeepPresent ? value.Instance : null); if ((Object)(object)val != (Object)null) { val.Config.TryGetEntry<string>(new ConfigDefinition("8. Homestead", "Build On Wood"), ref openkeepWood); } resolved = true; } public static void Tick() { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown //IL_0050: Unknown result type (might be due to invalid IL or missing references) if (Time.unscaledTime < next) { return; } next = Time.unscaledTime + 0.5f; SourceMod val = ((!flooringPresent) ? ((openkeepPresent && (openkeepWood == null || !string.IsNullOrWhiteSpace(openkeepWood.Value))) ? new SourceMod("milkyteam.openkeep", "OpenKeep Build On Wood") : ((SourceMod)null)) : new SourceMod("com.jekkle.valheim.carturflooring", "Cartur's Flooring")); SourceMod? obj = source; if (((obj != null) ? obj.Guid : null) != ((val != null) ? val.Guid : null)) { source = val; noticed = -1L; if (source == null) { MeadworksStepAside.WithdrawModule("com.meadworks.timber", "fires_on_floors"); } } if (source != null && ((Object)(object)Player.m_localPlayer != (Object)null || !Plugin.AllowsUi) && noticed != Plugin.Session.Generation) { noticed = Plugin.Session.Generation; MeadworksStepAside.ReportModule("com.meadworks.timber", flooringPresent ? "flooring" : "fires_on_floors", source, "timber", flooringPresent ? "step_aside_flooring" : "step_aside_fires"); } ZNetScene instance = ZNetScene.instance; int num = (((Object)(object)instance != (Object)null) ? ((Object)instance).GetInstanceID() : 0); int num2 = (((Object)(object)instance != (Object)null) ? instance.m_namedPrefabs.Count : 0); bool active = Active; bool roofsActive = RoofsActive; bool smeltersActive = SmeltersActive; if (num != sceneId || num2 != prefabCount || active != applied || roofsActive != appliedRoofs || smeltersActive != appliedSmelters) { sceneId = num; prefabCount = num2; applied = active; appliedRoofs = roofsActive; appliedSmelters = smeltersActive; FirePlacement.ApplyAll(); FloorRoofTags.ApplyAll(); } } public static void Reset() { FirePlacement.Reset(); FloorRoofTags.Reset(); bindings?.Dispose(); bindings = null; enabled = null; roofs = null; smelters = null; rainProtection = null; appliedRoofs = (appliedSmelters = false); if (Plugin.IsReady) { MeadworksStepAside.WithdrawModule("com.meadworks.timber", "fires_on_floors"); MeadworksStepAside.WithdrawModule("com.meadworks.timber", "flooring"); } resolved = (flooringPresent = (openkeepPresent = (applied = false))); openkeepWood = null; source = null; sceneId = 0; prefabCount = -1; next = 0f; noticed = -1L; } } [HarmonyPatch(typeof(WearNTear), "UpdateWear")] public static class FloorRainWear { [HarmonyPrefix] public static void Prefix(WearNTear __instance, float time) { if (FiresRuntime.RainProtectionActive && !((Object)(object)__instance.m_piece == (Object)null) && FloorRoofTags.IsFloor(__instance.m_piece)) { ZNetView nview = __instance.m_nview; if (!((Object)(object)nview == (Object)null) && nview.IsValid() && nview.IsOwner()) { __instance.m_rainTimer = time; } } } } public static class FloorRoofTags { [HarmonyPatch(typeof(Piece), "Awake")] private static class Created { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(Piece __instance) { if (Plugin.Ready) { Apply(__instance, prefab: false); } } } [HarmonyPatch(typeof(Piece), "OnDestroy")] private static class Destroyed { [HarmonyPrefix] private static void Prefix(Piece __instance) { Collider[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<Collider>(true); foreach (Collider val in componentsInChildren) { if ((Object)(object)val != (Object)null) { originals.Remove(((Component)val).gameObject); } } } } private static readonly Dictionary<GameObject, string> originals = new Dictionary<GameObject, string>(); public static bool IsFloor(Piece piece) { //IL_0001: 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_0009: Invalid comparison between Unknown and I4 return (piece.m_usage & 8) > 0; } public static void ApplyAll() { if (!FiresRuntime.RoofsActive) { Reset(); } else { if ((Object)(object)ZNetScene.instance == (Object)null) { return; } foreach (GameObject value in ZNetScene.instance.m_namedPrefabs.Values) { Piece val = (((Object)(object)value != (Object)null) ? value.GetComponent<Piece>() : null); if ((Object)(object)val != (Object)null) { Apply(val, prefab: true); } } foreach (Piece s_allPiece in Piece.s_allPieces) { if ((Object)(object)s_allPiece != (Object)null) { Apply(s_allPiece, prefab: false); } } } } public static void Apply(Piece piece, bool prefab) { if (!FiresRuntime.RoofsActive || !IsFloor(piece)) { return; } Piece val = (prefab ? null : FirePrefabs.Exact(Utils.GetPrefabName(((Component)piece).gameObject))); Collider[] componentsInChildren = ((Component)piece).GetComponentsInChildren<Collider>(true); foreach (Collider val2 in componentsInChildren) { if ((Object)(object)val2 == (Object)null || (Object)(object)((Component)val2).GetComponentInParent<Piece>() != (Object)(object)piece) { continue; } GameObject gameObject = ((Component)val2).gameObject; if (!originals.ContainsKey(gameObject)) { string text = gameObject.tag; if (text == "Untagged" && (Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)piece) { Transform val3 = MatchingChild(((Component)piece).transform, gameObject.transform, ((Component)val).transform); if ((Object)(object)val3 != (Object)null && originals.TryGetValue(((Component)val3).gameObject, out string value)) { text = value; } } if (text != "leaky") { continue; } originals.Add(gameObject, text); } if (gameObject.CompareTag("leaky")) { gameObject.tag = "Untagged"; } } } private static Transform? MatchingChild(Transform root, Transform child, Transform template) { Stack<Transform> stack = new Stack<Transform>(); Transform val = child; while ((Object)(object)val != (Object)(object)root) { if ((Object)(object)val == (Object)null) { return null; } stack.Push(val); val = val.parent; } foreach (Transform item in stack) { int siblingIndex = item.GetSiblingIndex(); if (siblingIndex >= template.childCount) { return null; } template = template.GetChild(siblingIndex); if (((Object)template).name != ((Object)item).name) { return null; } } return template; } public static void Reset() { if (originals.Count == 0) { return; } HashSet<GameObject> hashSet = new HashSet<GameObject>(); foreach (KeyValuePair<GameObject, string> original in originals) { if (!((Object)(object)original.Key == (Object)null) && original.Key.CompareTag("Untagged")) { original.Key.tag = original.Value; hashSet.Add(original.Key); } } foreach (WearNTear allInstance in WearNTear.GetAllInstances()) { if ((Object)(object)allInstance != (Object)null && (Object)(object)allInstance.m_roof != (Object)null && hashSet.Contains(allInstance.m_roof)) { allInstance.m_roof = null; } } originals.Clear(); } } } namespace Timber.Camera { public static class CameraArea { private const float Inset = 0.99f; public static bool Contains(Vector3 point) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) foreach (CraftingStation allStation in CraftingStation.m_allStations) { if ((Object)(object)allStation != (Object)null && Outside(allStation, point) <= 0f) { return true; } } return false; } public static Vector3 Clamp(Vector3 point) { //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) return ClampToStations(point); } private static Vector3 ClampToStations(Vector3 point) { //IL_0027: 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_0039: 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_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) CraftingStation val = null; float num = float.MaxValue; foreach (CraftingStation allStation in CraftingStation.m_allStations) { if (!((Object)(object)allStation == (Object)null)) { float num2 = Outside(allStation, point); if (num2 <= 0f) { return point; } if (num2 < num) { num = num2; val = allStation; } } } if (!((Object)(object)val != (Object)null)) { return point; } return Into(val, point); } private static float Range(CraftingStation station) { return station.GetStationBuildRange() * CameraSettings.RangeMultiplier.Value; } private static float Outside(CraftingStation station, Vector3 point) { //IL_001b: 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_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_002b: 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) float num = Range(station); if (num <= 0f) { return float.MaxValue; } Vector3 position = ((Component)station).transform.position; float num2 = Utils.DistanceXZ(position, point) - num; float num3 = Mathf.Abs(point.y - position.y) - num; if (num2 <= 0f && num3 <= 0f) { return Mathf.Max(num2, num3); } return Mathf.Max(num2, 0f) + Mathf.Max(num3, 0f); } private static Vector3 Into(CraftingStation station, Vector3 point) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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_001f: 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_002c: 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_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_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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_0069: 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) //IL_0076: Unknown result type (might be due to invalid IL or missing references) float num = Range(station) * 0.99f; Vector3 position = ((Component)station).transform.position; Vector2 val = Vector2.ClampMagnitude(new Vector2(point.x - position.x, point.z - position.z), num); float num2 = Mathf.Clamp(point.y, position.y - num, position.y + num); return new Vector3(position.x + val.x, num2, position.z + val.y); } } public sealed class CameraValue<T> { private readonly ConfigEntry<T> entry; private readonly ConfigScope scope; private readonly T safe; public T Value { get { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) T val = MeadworksConfig.Effective<T>(entry, "com.meadworks.timber", scope, safe, true); if ((int)scope != 0 || Plugin.PlayerLocks == null) { return val; } return Plugin.PlayerLocks.Effective(entry, val); } } public CameraValue(ConfigEntry<T> entry, ConfigScope scope, T safe) { //IL_000e: 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) this.entry = entry; this.scope = scope; this.safe = safe; } } public sealed class CameraBindings { private readonly ConfigFile config; private readonly List<ConfigEntryBase> tracked = new List<ConfigEntryBase>(); public CameraBindings(ConfigFile config) { this.config = config; } public CameraValue<T> Bind<T>(string section, string key, T value, string description, bool synced = true, AcceptableValueBase? acceptableValues = null) { return Bind(section, key, value, description, synced, acceptableValues, new object[0]); } public CameraValue<T> Bind<T>(string section, string key, T value, string description, bool synced, AcceptableValueBase? acceptableValues, params object[] tags) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_002a: 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) ConfigScope val = (ConfigScope)(synced ? 1 : 0); ConfigEntry<T> val2 = MeadworksConfig.Bind<T>(config, section, key, value, new ConfigDescription(description, acceptableValues, tags), val); MeadworksBlockedOptions.Track("com.meadworks.timber", (ConfigEntryBase)(object)val2, val, true); tracked.Add((ConfigEntryBase)(object)val2); return new CameraValue<T>(val2, val, value); } public void Dispose() { foreach (ConfigEntryBase item in tracked) { MeadworksBlockedOptions.Untrack(item); } tracked.Clear(); } } public static class CameraCollision { private const float Skin = 0.05f; private const float MinMove = 0.0001f; private static int mask; private static Vector3 lastSafe; private static bool hasLastSafe; private static float Radius => CameraSettings.TerrainClearance.Value; private static int Mask { get { if (mask == 0) { return mask = LayerMask.GetMask(new string[2] { "terrain", "static_solid" }); } return mask; } } public static Vector3 Move(Vector3 from, Vector3 to) { //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_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) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_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_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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_006e: 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) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0066: 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_0068: Unknown result type (might be due to invalid IL or missing references) Vector3 normal; Vector3 val = Sweep(from, to, out normal); if (normal != Vector3.zero) { Vector3 val2 = Vector3.ProjectOnPlane(to - val, normal); val = Sweep(val, val + val2, out var _); } if (Physics.CheckSphere(val, Radius, Mask, (QueryTriggerInteraction)1)) { if (!hasLastSafe || Physics.CheckSphere(lastSafe, Radius, Mask, (QueryTriggerInteraction)1)) { return from; } return lastSafe; } lastSafe = val; hasLastSafe = true; return val; } public static void Reset() { hasLastSafe = false; } private static Vector3 Sweep(Vector3 from, Vector3 to, out Vector3 normal) { //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_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) //IL_000d: 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) //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_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_0033: 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_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_005a: 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_0077: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) normal = Vector3.zero; Vector3 val = to - from; float magnitude = ((Vector3)(ref val)).magnitude; if (magnitude < 0.0001f) { return from; } Vector3 val2 = val / magnitude; RaycastHit val3 = default(RaycastHit); if (!Physics.SphereCast(from, Radius, val2, ref val3, magnitude + 0.05f, Mask, (QueryTriggerInteraction)1)) { return to; } normal = ((RaycastHit)(ref val3)).normal; return from + val2 * Mathf.Max(0f, ((RaycastHit)(ref val3)).distance - 0.05f); } } [HarmonyPatch(typeof(Player), "SetMouseLook")] public static class CameraLookPatch { [HarmonyPrefix] public static void Prefix(Player __instance, ref Vector2 mouseLook) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0012: 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) if (CameraState.IsOut(__instance)) { if (MeadworksInput.Allows((InputContext)0)) { CameraState.Look(CarturLook.Adjust(mouseLook)); } mouseLook = Vector2.zero; } } } [HarmonyPatch(typeof(Player), "SetControls")] public static class CameraControlsPatch { [HarmonyPrefix] public static void Prefix(Player __instance, ref Vector3 movedir, ref bool block, ref bool blockHold, ref bool jump, ref bool crouch, ref bool run, ref bool autoRun, ref bool dodge) { //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) if (CameraState.IsOut(__instance)) { movedir = Vector3.zero; block = (blockHold = (jump = (crouch = (run = (autoRun = (dodge = false)))))); } } } public static class CameraModule { public const string Section = "Build Camera"; public const string NoStation = "camera_no_station"; public const string EntryNeeds = "camera_entry_needs"; public const string Resting = "camera_resting"; public const string Comfort = "camera_comfort"; private static CameraBindings? bindings; private static bool sourcesReady; private static SourceMod? blocked; private static SourceMod? openkeepSource; private static ConfigEntry<bool>? openkeepEnabled; private static bool carturPresent; private static long noticedSession = -1L; public static bool Allowed { get { if (sourcesReady && blocked == null && Plugin.Active && Plugin.AllowsUi) { return CameraSettings.Enabled.Value; } return false; } } public static void Initialize(ConfigFile config) { bindings = new CameraBindings(config); CameraSettings.Bind(bindings); CameraPrefs.Bind(bindings); } public static void ResolveSources() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Expected O, but got Unknown SourceMod val = new SourceMod("com.jekkle.valheim.carturbuildcamera", "Cartur's Build Camera"); SourceMod val2 = new SourceMod("Azumatt.BuildCameraCHE", "Build Camera Custom Hammers Edition"); SourceMod val3 = new SourceMod("milkyteam.openkeep", "OpenKeep Build Camera"); if (Plugin.Services.StepAside.Declared("com.meadworks.timber").Count == 0) { MeadworksStepAside.Declare("com.meadworks.timber", "Timber", (IEnumerable<SourceMod>)(object)new SourceMod[4] { val, val2, val3, new SourceMod("com.jekkle.valheim.carturflooring", "Cartur's Flooring") }); } bool flag = Chainloader.PluginInfos.ContainsKey(val.Guid); bool flag2 = Chainloader.PluginInfos.ContainsKey(val2.Guid); carturPresent = flag || flag2; PluginInfo value; if (carturPresent) { blocked = (flag ? val : val2); } else if (Chainloader.PluginInfos.TryGetValue(val3.Guid, out value)) { BaseUnityPlugin instance = value.Instance; openkeepSource = val3; if ((Object)(object)instance != (Object)null) { instance.Config.TryGetEntry<bool>(new ConfigDefinition("11. Build Camera", "Enabled"), ref openkeepEnabled); } if (openkeepEnabled == null || openkeepEnabled.Value) { blocked = val3; } } sourcesReady = true; } public static void Tick() { if (!carturPresent && openkeepSource != null) { SourceMod val = ((openkeepEnabled == null || openkeepEnabled.Value) ? openkeepSource : null); if (val != blocked) { blocked = val; noticedSession = -1L; if (blocked == null) { MeadworksStepAside.WithdrawModule("com.meadworks.timber", "camera"); } } } if (!Allowed || (Object)(object)Player.m_localPlayer == (Object)null) { CameraState.Exit(); } if (blocked != null && (Object)(object)Player.m_localPlayer != (Object)null && noticedSession != Plugin.Session.Generation) { noticedSession = Plugin.Session.Generation; MeadworksStepAside.ReportModule("com.meadworks.timber", "camera", blocked, "timber", "step_aside_camera"); } } public static void Center(string text) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown if (Plugin.AllowsUi && (Object)(object)MessageHud.instance != (Object)null) { ProductRegistration source = Plugin.Source; if (source != null && source.IsActive && CrucibleUiPlugin.Active) { KitNotices.Show(source, new KitNotice(text, (KitNoticeKind)1, "", 0, (Sprite)null, true, false, true)); } else { MessageHud.instance.ShowMessage((MessageType)2, text, 0, (Sprite)null, false, true); } } } public static void Reset() { CameraState.Exit(); CameraPickupHud.Reset(); CircletLight.Reset(); CircletSource.Reset(); bindings?.Dispose(); bindings = null; if (Plugin.IsReady) { MeadworksStepAside.WithdrawModule("com.meadworks.timber", "camera"); } openkeepSource = null; openkeepEnabled = null; carturPresent = false; sourcesReady = false; blocked = null; noticedSession = -1L; } } [HarmonyPatch(typeof(Player), "Update")] public static class CameraPlayerUpdatePatch { [HarmonyPostfix] public static void Postfix(Player __instance) { if (Plugin.Ready && Plugin.AllowsUi) { CameraToggle.Tick(__instance); } } } public static class CameraMotion { public static void Step(Player player, float dt) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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_003d: 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_0052: 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_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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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) if (!((Object)(object)player == (Object)null) && MeadworksInput.Allows((InputContext)0) && ((Character)player).TakeInput() && !Hud.IsPieceSelectionVisible() && !Hud.InRadial()) { Vector3 val = Direction() * Speed() * dt; if (!(((Vector3)(ref val)).sqrMagnitude < 1E-08f)) { Vector3 position = CameraState.Position; Vector3 to = CameraArea.Clamp(position + val); CameraState.Position = CameraCollision.Move(position, to); } } } private static Vector3 Direction() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0096: 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_00c5: 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_00dc: Unknown result type (might be due to invalid IL or missing references) Vector3 zero = Vector3.zero; if (ZInput.GetButton("Forward")) { zero.z += 1f; } if (ZInput.GetButton("Backward")) { zero.z -= 1f; } if (ZInput.GetButton("Left")) { zero.x -= 1f; } if (ZInput.GetButton("Right")) { zero.x += 1f; } Vector2 joyLeftStick = ZInput.GetJoyLeftStick(); zero.x += joyLeftStick.x; zero.z += joyLeftStick.y; zero.y = Vertical(); return (CameraPrefs.WorldMotion.Value ? Quaternion.identity : Quaternion.Euler(0f, CameraState.Yaw, 0f)) * Vector3.ClampMagnitude(zero, 1f); } private static float Vertical() { float num = ZInput.GetJoyRTrigger() - ZInput.GetJoyLTrigger(); if (ZInput.GetButton("Jump")) { num += 1f; } if (ZInput.GetButton("Crouch")) { num -= 1f; } return Mathf.Clamp(num, -1f, 1f); } private static float Speed() { bool flag = ZInput.GetButton("Run") || ZInput.GetButton("JoyRun"); return CameraPrefs.Speed.Value * (flag ? CameraPrefs.RunMultiplier.Value : 1f); } } public static class CameraNeeds { public static bool Met(Player player, CameraValue<bool> resting, CameraValue<int> comfort) { if (!MissesResting(player, resting)) { return player.GetComfortLevel() >= comfort.Value; } return false; } public static string Describe(Player player, CameraValue<bool> resting, CameraValue<int> comfort) { if (Met(player, resting, comfort)) { return null; } List<string> list = new List<string>(); if (MissesResting(player, resting)) { list.Add(TimberText.Text("camera_resting")); } int comfortLevel = player.GetComfortLevel(); if (comfortLevel < comfort.Value) { list.Add(string.Format(TimberText.Text("camera_comfort"), comfort.Value, comfortLevel)); } return string.Join(", ", list); } public static int Key(Player player, CameraValue<bool> resting, CameraValue<int> comfort) { return (int)((MissesResting(player, resting) ? 1u : 0u) | (uint)((player.GetComfortLevel() & 0xFFF) << 1)) | ((comfort.Value & 0xFFF) << 13); } private static bool MissesResting(Player player, CameraValue<bool> resting) { if (resting.Value) { return !((Character)player).GetSEMan().HaveStatusEffect(SEMan.s_statusEffectResting); } return false; } } [HarmonyPatch(typeof(Player), "FixedUpdate")] public static class CameraPickup { private const float PullSpeed = 15f; private const float TakeDistance = 0.3f; private static readonly Collider[] hits = (Collider[])(object)new Collider[100]; private static readonly List<ItemDrop> items = new List<ItemDrop>(); private static readonly List<FloatingTerrainDummy> dummies = new List<FloatingTerrainDummy>(); private static int mask; [HarmonyPostfix] public static void Postfix(Player __instance) { if (!CameraState.IsOut(__instance) || !CameraSettings.CameraPickup.Value || !Player.m_enableAutoPickup || ((Character)__instance).IsDead() || ((Character)__instance).IsTeleporting()) { return; } MagpiePickup magpiePickup = MagpiePickup.Resolve(__instance); if ((magpiePickup != null && !magpiePickup.Current) || Collect(__instance, magpiePickup) == 0) { return; } if (!CameraNeeds.Met(__instance, CameraSettings.PickupNeedsResting, CameraSettings.PickupMinComfort)) { CameraPickupHud.Blocked(__instance); return; } for (int i = 0; i < items.Count; i++) { Pull(__instance, items[i], dummies[i], Time.fixedDeltaTime, magpiePickup); } } private static int Collect(Player player, MagpiePickup magpie) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) items.Clear(); dummies.Clear(); if (mask == 0) { mask = LayerMask.GetMask(new string[1] { "item" }); } int num = Physics.OverlapSphereNonAlloc(CameraState.Position, magpie?.Radius ?? PickupRange(player), hits, mask); for (int i = 0; i < num; i++) { FloatingTerrainDummy dummy; ItemDrop val = ItemOf(hits[i], out dummy); if (!((Object)(object)val == (Object)null) && !items.Contains(val) && Wanted(player, val) && (magpie == null || magpie.Wanted(val))) { items.Add(val); dummies.Add(dummy); } } return items.Count; } private static ItemDrop ItemOf(Collider collider, out FloatingTerrainDummy dummy) { dummy = null; Rigidbody attachedRigidbody = collider.attachedRigidbody; if ((Object)(object)attachedRigidbody == (Object)null) { return null; } ItemDrop component = ((Component)attachedRigidbody).GetComponent<ItemDrop>(); if ((Object)(object)component != (Object)null) { return component; } dummy = ((Component)attachedRigidbody).GetComponent<FloatingTerrainDummy>(); if (!((Object)(object)dummy != (Object)null) || !((Object)(object)dummy.m_parent != (Object)null)) { return null; } return ((Component)dummy.m_parent).GetComponent<ItemDrop>(); } private static bool Wanted(Player player, ItemDrop item) { if ((Object)(object)item == (Object)null || (Object)(object)player == (Object)null || item.m_itemData?.m_shared == null) { return false; } ZNetView component = ((Component)item).GetComponent<ZNetView>(); string text = item.m_itemData?.m_shared?.m_name; if (item.m_autoPickup && !item.IsPiece() && (Object)(object)component != (Object)null && component.IsValid()) { if (text != null) { return !((Humanoid)player).HaveUniqueKey(text); } return true; } return false; } private static void Pull(Player player, ItemDrop item, FloatingTerrainDummy dummy, float dt, MagpiePickup magpie) { //IL_0042: 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_008a: 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_00e0: 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_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: 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) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0117: 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_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || (Object)(object)item == (Object)null || item.m_itemData?.m_shared == null || (magpie != null && !magpie.Wanted(item)) || !WardAccess.Check(player.GetPlayerID(), ((Component)item).transform.position) || (magpie != null && !magpie.Current)) { return; } if (!item.CanPickup(true)) { item.RequestOwn(); } else { if (item.InTar() || !Fits(player, item)) { return; } Vector3 position = CameraState.Position; float num = Vector3.Distance(((Component)item).transform.position, position); if (num > (magpie?.Radius ?? PickupRange(player)) || (magpie != null && !magpie.Current)) { return; } if (num < 0.3f) { if (magpie != null) { magpie.TryTake(item); } else { ((Humanoid)player).Pickup(((Component)item).gameObject, true, true); } return; } Vector3 val = position - ((Component)item).transform.position; Vector3 val2 = ((Vector3)(ref val)).normalized * 15f * dt; Transform transform = ((Component)item).transform; transform.position += val2; if ((Object)(object)dummy != (Object)null) { Transform transform2 = ((Component)dummy).transform; transform2.position += val2; } } } private static float PickupRange(Player player) { if (!(CameraSettings.PickupRange.Value > 0f)) { return player.m_autoPickupRange; } return CameraSettings.PickupRange.Value; } private static bool Fits(Player player, ItemDrop item) { if ((Object)(object)player == (Object)null || (Object)(object)item == (Object)null || item.m_itemData?.m_shared == null) { return false; } item.Load(); if (item.m_itemData?.m_shared == null) { return false; } Inventory inventory = ((Humanoid)player).GetInventory(); if (inventory == null) { return false; } if (inventory.CanAddItem(item.m_itemData, -1)) { return item.m_itemData.GetWeight(-1) + inventory.GetTotalWeight() <= player.GetMaxCarryWeight(); } return false; } } public static class CameraPickupHud { private static KitHudPanel? panel; private static Transform? owner; private static TMP_Text? label; private static float expires; private static int shownNeeds = -1; private static string? shownLanguage; private static float measuredCanvasWidth = -1f; public static void Blocked(Player player) { if (CameraState.IsOut(player) && CameraPrefs.PickupPanel.Value) { expires = Time.unscaledTime + 1f; } } public static void Tick() { //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: 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_016f: 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_018f: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_02fe: Unknown result type (might be due to invalid IL or missing references) //IL_0309: Unknown result type (might be due to invalid IL or missing references) //IL_031b: Unknown result type (might be due to invalid IL or missing references) //IL_032a: Unknown result type (might be due to invalid IL or missing references) //IL_032f: Unknown result type (might be due to invalid IL or missing references) //IL_033c: Unknown result type (might be due to invalid IL or missing references) //IL_034d: Unknown result type (might be due to invalid IL or missing references) //IL_0355: Unknown result type (might be due to invalid IL or missing references) //IL_035d: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; Transform val = (((Object)(object)Hud.instance != (Object)null && (Object)(object)Hud.instance.m_rootObject != (Object)null) ? Hud.instance.m_rootObject.transform : null); if (panel != null && ((Object)(object)panel.Root == (Object)null || (Object)(object)owner != (Object)(object)val)) { Reset(); } if (!CrucibleUiPlugin.Active || !CameraState.Active || !CameraSettings.CameraPickup.Value || !Player.m_enableAutoPickup || !CameraPrefs.PickupPanel.Value || !((Object)(object)localPlayer != (Object)null) || !(Time.unscaledTime < expires) || CameraNeeds.Met(localPlayer, CameraSettings.PickupNeedsResting, CameraSettings.PickupMinComfort) || (Object)(object)val == (Object)null || (Object)(object)KitCanvas.Font == (Object)null) { KitHudPanel? obj = panel; if (obj != null) { obj.Update(false, false, 1f, 1f); } return; } if (panel == null) { panel = KitHudPanel.Create(val, "Timber_CameraPickup", new Vector2(320f, 64f), Vector2.zero, "com.meadworks.timber", "Timber_CameraPickup"); if (panel == null) { return; } owner = val; label = KitCanvas.Text((Transform)(object)panel.Content, "Timber_CameraPickupText", "", 20f, KitAppearance.Color((KitColorRole)6), (TextAlignmentOptions)514, false); RectTransform rectTransform = label.rectTransform; rectTransform.anchorMin = Vector2.zero; rectTransform.anchorMax = Vector2.one; rectTransform.offsetMin = new Vector2(16f, 12f); rectTransform.offsetMax = new Vector2(-16f, -12f); panel.SetInteractive((Graphic)(object)label, false); } TMP_Text val2 = label; KitHudPanel val3 = panel; if ((Object)(object)val2 == (Object)null || val3 == null) { Reset(); return; } RectTransform root = val3.Root; if ((Object)(object)root == (Object)null) { Reset(); return; } string text = MeadworksTranslations.GameLanguage(); int num = CameraNeeds.Key(localPlayer, CameraSettings.PickupNeedsResting, CameraSettings.PickupMinComfort); RectTransform val4 = (RectTransform)(object)((val is RectTransform) ? val : null); float num2; if (val4 == null) { num2 = Screen.width; } else { Rect rect = val4.rect; num2 = ((Rect)(ref rect)).width; } float num3 = num2; if (shownNeeds != num || shownLanguage != text || !Mathf.Approximately(measuredCanvasWidth, num3)) { shownNeeds = num; shownLanguage = text; measuredCanvasWidth = num3; val2.text = TimberText.Text("camera_pickup_needs") + ": " + CameraNeeds.Describe(localPlayer, CameraSettings.PickupNeedsResting, CameraSettings.PickupMinComfort); val2.textWrappingMode = (TextWrappingModes)0; Vector2 preferredValues = val2.GetPreferredValues(val2.text); float num4 = Mathf.Min(Mathf.Max(160f, preferredValues.x + 32f), Mathf.Max(160f, num3 - 32f)); val2.textWrappingMode = (TextWrappingModes)1; Vector2 preferredValues2 = val2.GetPreferredValues(val2.text, num4 - 32f, 0f); root.sizeDelta = new Vector2(num4, Mathf.Max(48f, preferredValues2.y + 24f)); } Vector2 value = CameraPrefs.PickupPanelPosition.Value; val3.SetPosition(new Vector2(num3 * 0.5f - root.sizeDelta.x * 0.5f + value.x, 0f - value.y)); val3.Update(true, false, 1f, 1f); } public static void Reset() { KitHudPanel? obj = panel; if (obj != null) { obj.Dispose(); } panel = null; owner = null; label = null; expires = 0f; shownNeeds = -1; shownLanguage = null; measuredCanvasWidth = -1f; } } public static class CameraPrefs { public const string Section = "Build Camera"; public static CameraValue<KeyboardShortcut> ToggleKey { get; private set; } public static CameraValue<string> GamepadToggle { get; private set; } public static CameraValue<float> Speed { get; private set; } public static CameraValue<float> RunMultiplier { get; private set; } public static CameraValue<bool> WorldMotion { get; private set; } public static CameraValue<bool> InvertMouseHorizontal { get; private set; } public static CameraValue<bool> InvertMouseVertical { get; private set; } public static CameraValue<bool> InvertPadHorizontal { get; private set; } public static CameraValue<bool> InvertPadVertical { get; private set; } public static CameraValue<Vector3> CircletOffset { get; private set; } public static CameraValue<string> CircletColour { get; private set; } public static CameraValue<CameraLightShadows> CircletShadows { get; private set; } public static CameraValue<bool> CircletLight { get; private set; } public static CameraValue<float> CircletIntensity { get; private set; } public static CameraValue<float> CircletRange { get; private set; } public static CameraValue<float> CircletSpotAngle { get; private set; } public static CameraValue<bool> PickupPanel { get; private set; } public static CameraValue<Vector2> PickupPanelPosition { get; private set; } public static void Bind(CameraBindings synced) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) ToggleKey = synced.Bind<KeyboardShortcut>("Build Camera", "Toggle Key", new KeyboardShortcut((KeyCode)98, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Brings the build camera out and back while a hammer, hoe or cultivator is in hand.", synced: false); GamepadToggle = synced.Bind("Build Camera", "Gamepad Toggle", "JoyAltKeys + JoyRStick", "The same on a gamepad: the game's button names joined with +, the last pressed while the others are held (by default hold the left trigger and click the right stick). Empty: none.", synced: false); Speed = synced.Bind("Build Camera", "Speed", 10f, "Meters per second the camera flies.", synced: false, (AcceptableValueBase?)(object)new AcceptableValueRange<float>(1f, 100f)); RunMultiplier = synced.Bind("Build Camera", "Run Multiplier", 3f, "How much faster the camera flies while Run (Shift) is held.", synced: false, (AcceptableValueBase?)(object)new AcceptableValueRange<float>(1f, 10f)); WorldMotion = synced.Bind("Build Camera", "Move With Respect To World", value: false, "Movement follows world axes instead of camera heading.", synced: false); InvertMouseHorizontal = synced.Bind("Build Camera", "Invert Mouse Horizontal", value: false, "Reverse horizontal mouse look while the build camera is detached.", synced: false); InvertMouseVertical = synced.Bind("Build Camera", "Invert Mouse Vertical", value: false, "Reverse vertical mouse look while the build camera is detached.", synced: false); InvertPadHorizontal = synced.Bind("Build Camera", "Invert Pad Horizontal", value: false, "Reverse horizontal gamepad look while the build camera is detached.", synced: false); InvertPadVertical = synced.Bind("Build Camera", "Invert Pad Vertical", value: false, "Reverse vertical gamepad look while the build camera is detached.", synced: false); BindLight(synced); PickupPanel = synced.Bind("Build Camera", "Pickup Panel", value: true, "Show unmet camera pickup Resting and comfort needs in the shared Meadworks HUD panel.", synced: false); PickupPanelPosition = synced.Bind<Vector2>("Build Camera", "Pickup Panel Position", new Vector2(0f, -120f), "Pickup panel offset from the top center of the HUD in UI units: x right, y up.", synced: false); } private static void BindLight(CameraBindings synced) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) CircletLight = synced.Bind("Build Camera", "Circlet Light", value: true, "A light worn on the head (the Dvergr circlet, also in another mod's extra slot) shines from the camera too while it is out, with the circlet's own settings unless the three below change them.", synced: false); CircletOffset = synced.Bind<Vector3>("Build Camera", "Circlet Offset", new Vector3(0f, -0.08f, 0.65f), "Camera light offset: right, up, forward; each clamped to -5 to 5 meters.", synced: false); CircletColour = synced.Bind("Build Camera", "Circlet Color", "Original", "Original or a hexadecimal RRGGBB[AA] color.", synced: false); CircletShadows = synced.Bind("Build Camera", "Circlet Shadows", CameraLightShadows.Original, "Original, Off, Hard or Soft shadows.", synced: false); CircletIntensity = synced.Bind("Build Camera", "Circlet Intensity", 0f, "Brightness of the camera's copy. 0: the circlet's own.", synced: false, (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0f, 10f)); CircletRange = synced.Bind("Build Camera", "Circlet Range", 0f, "Meters the camera's copy reaches. 0: the circlet's own.", synced: false, (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0f, 100f)); CircletSpotAngle = synced.Bind("Build Camera", "Circlet Spot Angle", 0f, "Width of the camera's copy's beam in degrees. 0: the circlet's own.", synced: false, (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0f, 179f)); } } [HarmonyPatch] internal static class CameraRayPatches { private static readonly MethodInfo native = AccessTools.Method(typeof(Physics), "Raycast", new Type[5] { typeof(Vector3), typeof(Vector3), typeof(RaycastHit).MakeByRefType(), typeof(float), typeof(int) }, (Type[])null); private static readonly MethodInfo replacement = AccessTools.Method(typeof(CameraReach), "Raycast", (Type[])null, (Type[])null); private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(Player), "PieceRayTest", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(Player), "RemovePiece", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(Player), "CopyPiece", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(Player), "UpdateWearNTearHover", (Type[])null, (Type[])null); } [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase original) { List<CodeInstruction> list = instructions.ToList(); if (list.Count((CodeInstruction i) => CodeInstructionExtensions.Calls(i, native)) != 1) { throw new InvalidOperationException("Timber camera ray site changed: " + original.Name); } foreach (CodeInstruction instruction in list) { if (CodeInstructionExtensions.Calls(instruction, native)) { yield return CodeInstructionExtensions.MoveLabelsFrom(new CodeInstruction(OpCodes.Ldarg_0, (object)null), instruction); instruction.opcode = OpCodes.Call; instruction.operand = replacement; } yield return instruction; } } } public static class CameraReach { public readonly struct Scope { internal readonly bool Changed; internal readonly float Distance; internal readonly float RayLength; internal Scope(float distance, float length) { Changed = true; Distance = distance; RayLength = length; } } private const float GameRayLength = 50f; private const float Unbounded = 100000f; private static float rayLength = 50f; public static Scope Open(Player player, int mask, float extra) { if (!CameraState.IsOut(player) || (Object)(object)GameCamera.instance == (Object)null) { return default(Scope); } float maxPlaceDistance = player.m_maxPlaceDistance; float num = maxPlaceDistance + extra + CameraSettings.ExtraReach.Value; Scope result = new Scope(maxPlaceDistance, rayLength); rayLength = Mathf.Max(50f, num); try { player.m_maxPlaceDistance = (InReach(mask, num) ? 100000f : (-100000f)); return result; } catch { rayLength = result.RayLength; throw; } } public static void Close(Player player, Scope saved) { if (saved.Changed) { player.m_maxPlaceDistance = saved.Distance; rayLength = saved.RayLength; } } internal static bool Raycast(Vector3 origin, Vector3 direction, out RaycastHit hit, float distance, int mask, Player player) { //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) return Physics.Raycast(origin, direction, ref hit, CameraState.IsOut(player) ? Mathf.Max(distance, rayLength) : distance, mask); } private static bool InReach(int mask, float reach) { //IL_000c: 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) Transform transform = ((Component)GameCamera.instance).transform; RaycastHit val = default(RaycastHit); if (Physics.Raycast(transform.position, transform.forward, ref val, rayLength, mask)) { return ((RaycastHit)(ref val)).distance < reach; } return false; } } [HarmonyPatch(typeof(Player), "PieceRayTest")] public static class CameraPlaceReachPatch { [HarmonyPrefix] public static void Prefix(Player __instance, bool water, out CameraReach.Scope __state) { int mask = (water ? __instance.m_placeWaterRayMask : __instance.m_placeRayMask); __state = CameraReach.Open(__instance, mask, ExtraDistance(__instance)); } [HarmonyFinalizer] public static void Finalizer(Player __instance, CameraReach.Scope __state) { CameraReach.Close(__instance, __state); } private static float ExtraDistance(Player player) { Piece val = (((Object)(object)player.m_placementGhost != (Object)null) ? player.m_placementGhost.GetComponent<Piece>() : null); if (!((Object)(object)val != (Object)null)) { return 0f; } return val.m_extraPlacementDistance; } } [HarmonyPatch] public static class CameraRemoveReachPatch { public static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(Player), "RemovePiece", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(Player), "CopyPiece", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(Player), "UpdateWearNTearHover", (Type[])null, (Type[])null); } [HarmonyPrefix] public static void Prefix(Player __instance, out CameraReach.Scope __state) { __state = CameraReach.Open(__instance, __instance.m_removeRayMask, 0f); } [HarmonyFinalizer] public static void Finalizer(Player __instance, CameraReach.Scope __state) { CameraReach.Close(__instance, __state); } } public static class CameraSettings { public const string Section = "Build Camera"; public static CameraValue<bool> Enabled { get; private set; } public static CameraValue<float> RangeMultiplier { get; private set; } public static CameraValue<float> ExtraReach { get; private set; } public static CameraValue<bool> CameraPickup { get; private set; } public static CameraValue<float> TerrainClearance { get; private set; } public static CameraValue<float> PickupRange { get; private set; } public static CameraValue<bool> DemisterFollow { get; private set; } public static CameraValue<float> DemisterRange { get; private set; } public static CameraValue<bool> EntryNeedsResting { get; private set; } public static CameraValue<int> EntryMinComfort { get; private set; } public static CameraValue<bool> PickupNeedsResting { get; private set; } public static CameraValue<int> PickupMinComfort { get; private set; } public static void Bind(CameraBindings synced) { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Expected O, but got Unknown //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Expected O, but got Unknown //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Expected O, but got Unknown //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Expected O, but got Unknown //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Expected O, but got Unknown //IL_02d1: Unknown result type (might be due to invalid IL or missing references) //IL_02d7: Expected O, but got Unknown Enabled = synced.Bind("Build Camera", "Enabled", value: true, "With a hammer, hoe or cultivator in hand near a crafting station (a workbench, forge, stonecutter...), Toggle Key detaches the camera from you. Fly it with the movement keys, Jump up, Crouch down, Run faster; build, remove and repair from it as usual. Toggle Key again, Hide (R) or putting the tool away brings it back."); RangeMultiplier = synced.Bind("Build Camera", "Range Multiplier", 1f, "The camera comes out and stays within this many times a station's build range around any crafting station (measured flat as the game does, and as far above or below it). Only the camera's area: pieces still need the station's real range, and the station's base area (raids, comfort) is unchanged.", true, (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0.1f, 10f), (object)new ConfigDependency((Func<bool>)(() => Enabled.Value), (Func<string>)(() => "Requires Build Camera: Enabled."), (Func<bool>)null)); ExtraReach = synced.Bind("Build Camera", "Extra Reach", 95f, "Meters the camera reaches beyond your own building reach (the game's 5 m, or what another mod makes it), measured from the camera, for placing, removing and repairing.", true, (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0f, 95f), (object)new ConfigDependency((Func<bool>)(() => Enabled.Value), (Func<string>)(() => "Requires Build Camera: Enabled."), (Func<bool>)null)); CameraPickup = synced.Bind("Build Camera", "Camera Pickup", true, "While the camera is out, items lying within the game's auto pickup range of it come into your inventory, as they do around you (only with the game's auto pickup on).", true, null, (object)new ConfigDependency((Func<bool>)(() => Enabled.Value), (Func<string>)(() => "Requires Build Camera: Enabled."), (Func<bool>)null)); TerrainClearance = synced.Bind("Build Camera", "Terrain Clearance", 1f, "Camera collision probe radius in meters.", true, (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0.1f, 2f), (object)new ConfigDependency((Func<bool>)(() => Enabled.Value), (Func<string>)(() => "Requires Build Camera: Enabled."), (Func<bool>)null)); PickupRange = synced.Bind("Build Camera", "Pickup Range", 10f, "Camera auto pickup range in meters. 0: the player's native range.", true, (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0f, 100f), (object)new ConfigDependency((Func<bool>)(() => Enabled.Value && CameraPickup.Value), (Func<string>)(() => "Requires Build Camera: Enabled and Camera Pickup."), (Func<bool>)null)); DemisterFollow = synced.Bind("Build Camera", "Demister Follow Camera", true, "The equipped Wisplight follows the detached camera.", true, null, (object)new ConfigDependency((Func<bool>)(() => Enabled.Value), (Func<string>)(() => "Requires Build Camera: Enabled."), (Func<bool>)null)); DemisterRange = synced.Bind("Build Camera", "Demister Range Multiplier", 2.5f, "Wisplight clearing radius while the camera is detached.", synced: true, (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0.1f, 10f)); BindNeeds(synced); } private static void BindNeeds(CameraBindings synced) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Expected O, but got Unknown //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Expected O, but got Unknown //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Expected O, but got Unknown EntryNeedsResting = synced.Bind("Build Camera", "Entry Needs Resting", false, "The camera comes out only while you have the game's Resting effect (by a fire, under a roof).", true, null, (object)new ConfigDependency((Func<bool>)(() => Enabled.Value), (Func<string>)(() => "Requires Build Camera: Enabled."), (Func<bool>)null)); EntryMinComfort = synced.Bind("Build Camera", "Entry Min Comfort", 0, "The comfort level you need where you stand to bring the camera out. 0: none.", true, (AcceptableValueBase?)(object)new AcceptableValueRange<int>(0, 50), (object)new ConfigDependency((Func<bool>)(() => Enabled.Value), (Func<string>)(() => "Requires Build Camera: Enabled."), (Func<bool>)null)); PickupNeedsResting = synced.Bind("Build Camera", "Pickup Needs Resting", false, "Camera Pickup works only while you have the game's Resting effect.", true, null, (object)new ConfigDependency((Func<bool>)(() => Enabled.Value && CameraPickup.Value), (Func<string>)(() => "Requires Build Camera: Enabled and Camera Pickup."), (Func<bool>)null)); PickupMinComfort = synced.Bind("Build Camera", "Pickup Min Comfort", 0, "The comfort level you need where you stand for Camera Pickup. 0: none.", true, (AcceptableValueBase?)(object)new AcceptableValueRange<int>(0, 50), (object)new ConfigDependency((Func<bool>)(() => Enabled.Value && CameraPickup.Value), (Func<string>)(() => "Requires Build Camera: Enabled and Camera Pickup."), (Func<bool>)null)); } } public static class CameraState { private const float MaxPitch = 89f; private static Player owner; public static Vector3 Position { get; set; } public static float Yaw { get; private set; } public static float Pitch { get; private set; } public static bool Active { get { if (CameraModule.Allowed && (Object)(object)owner != (Object)null) { return (Object)(object)owner == (Object)(object)Player.m_localPlayer; } return false; } } public static Quaternion Rotation => Quaternion.Euler(Pitch, Yaw, 0f); public static bool IsOut(Player player) { if (Active) { return (Object)(object)player == (Object)(object)owner; } return false; } public static void Enter(Player player, Transform from) { //IL_0007: 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) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_0030: Unknown result type (might be due to invalid IL or missing references) owner = player; Position = from.position; Quaternion rotation = from.rotation; Vector3 eulerAngles = ((Quaternion)(ref rotation)).eulerAngles; Yaw = eulerAngles.y; Pitch = Mathf.Clamp(Mathf.DeltaAngle(0f, eulerAngles.x), -89f, 89f); } public static void Exit() { owner = null; CameraZoom.Restore(); SE_DemisterCameraPatch.Cleanup(); CameraCollision.Reset(); } public static void Look(Vector2 delta) { //IL_0005: 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) Yaw += delta.x; Pitch = Mathf.Clamp(Pitch - delta.y, -89f, 89f); } } public static class CameraToggle { public static void Tick(Player __instance) { if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } if (!CameraModule.Allowed) { CameraState.Exit(); return; } bool flag = TogglePressed(__instance); if (CameraState.Active) { if (flag || MustEnd(__instance)) { CameraState.Exit(); } } else if (flag && CameraSettings.Enabled.Value && CanUse(__instance)) { TryEnter(__instance); } } private static bool TogglePressed(Player player) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) if (!MeadworksInput.Allows((InputContext)0) || !((Character)player).TakeInput() || Hud.InRadial() || Hud.IsPieceSelectionVisible()) { return false; } if (!MeadworksInput.Pressed(CameraPrefs.ToggleKey.Value, (InputContext)0)) { return PadToggle.Pressed(); } return true; } public static bool CanUse(Player player) { if (((Character)player).InPlaceMode() && !((Character)player).IsDead() && !((Character)player).IsTeleporting() && (Object)(object)player.GetAttachCameraPoint() == (Object)null && (Object)(object)GameCamera.instance != (Object)null) { return !GameCamera.InFreeFly(); } return false; } private static bool MustEnd(Player player) { //IL_0021: 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) if (CameraSettings.Enabled.Value && !InventoryGui.IsVisible() && CanUse(player) && CameraArea.Contains(((Component)player).transform.position)) { return !CameraArea.Contains(CameraState.Position); } return true; } private static void TryEnter(Player player) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) if (!CameraArea.Contains(((Component)player).transform.position)) { CameraModule.Center(TimberText.Text("camera_no_station")); return; } string text = CameraNeeds.Describe(player, CameraSettings.EntryNeedsResting, CameraSettings.EntryMinComfort); if (text != null) { CameraModule.Center(TimberText.Text("camera_entry_needs") + ": " + text); return; } Transform transform = ((Component)GameCamera.instance).transform; CameraState.Enter(player, transform); CameraState.Position = CameraArea.Clamp(transform.position); } } [HarmonyPatch(typeof(GameCamera), "GetCameraPosition")] public static class CameraViewPatch { [HarmonyPrefix] public static bool Prefix(GameCamera __instance, float dt, ref Vector3 pos, ref Quaternion rot) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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) if (!CameraState.Active) { return true; } CameraMotion.Step(Player.m_localPlayer, dt); pos = CameraState.Position; rot = CameraState.Rotation; __instance.m_camera.nearClipPlane = __instance.m_nearClipPlaneMin; return false; } } [HarmonyPatch(typeof(GameCamera), "UpdateListner")] public static class CameraListenerPatch { [HarmonyPostfix] public static void Postfix(GameCamera __instance) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (CameraState.Active && (Object)(object)__instance.m_listner != (Object)null) { ((Component)__instance.m_listner).transform.localPosition = Vector3.zero; } } } [HarmonyPatch(typeof(LightLod), "GetLightReferencePoint")] public static class CameraLightLodPatch { [HarmonyPrefix] public static bool Prefix(ref Vector3 __result) { //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) if (!CameraState.Active) { return true; } __result = CameraState.Position; return false; } } [HarmonyPatch(typeof(GameCamera), "LateUpdate")] public static class CameraFramePatch { [HarmonyPostfix] public static void Postfix(GameCamera __instance) { CircletLight.Update(__instance); } } [HarmonyPatch(typeof(GameCamera), "UpdateCamera")] internal static class CameraZoom { private static GameCamera? owner; private static float original; private static float held; [HarmonyPrefix] [HarmonyPriority(800)] [HarmonyBefore(new string[] { "Azumatt.FirstPersonMode" })] internal static void Prefix(GameCamera __instance) { if (!CameraState.Active) { Restore(); return; } if ((Object)(object)owner != (Object)(object)__instance) { Restore(); owner = __instance; original = __instance.m_distance; } else if (!Mathf.Approximately(__instance.m_distance, held)) { original = __instance.m_distance; } held = Mathf.Max(1f, __instance.m_minDistance); __instance.m_distance = held; } [HarmonyPostfix] [HarmonyPriority(0)] internal static void Postfix(GameCamera __instance) { if (CameraState.Active && (Object)(object)owner == (Object)(object)__instance) { __instance.m_distance = held; } } internal static void Restore() { if ((Object)(object)owner != (Object)null && Mathf.Approximately(owner.m_distance, held)) { owner.m_distance = original; } owner = null; } } internal static class CarturLook { internal static Vector2 Adjust(Vector2 look) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) bool num = ZInput.IsMouseActive(); bool flag = (num ? CameraPrefs.InvertMouseHorizontal.Value : CameraPrefs.InvertPadHorizontal.Value); bool num2 = (num ? CameraPrefs.InvertMouseVertical.Value : CameraPrefs.InvertPadVertical.Value); if (flag) { look.x *= -1f; } if (num2) { look.y *= -1f; } return look; } } public static class CircletLight { private static Light copy; public static void Update(GameCamera camera) { Light val = ((CameraState.Active && CameraPrefs.CircletLight.Value) ? CircletSource.Find(Player.m_localPlayer) : null); if ((Object)(object)val == (Object)null) { if ((Object)(object)copy != (Object)null) { ((Behaviour)copy).enabled = false; } } else { Light obj = Get(camera); Copy(obj, val); ((Behaviour)obj).enabled = true; } } public static void Reset() { if ((Object)(object)copy != (Object)null) { Object.Destroy((Object)(object)((Component)copy).gameObject); } copy = null; } private static Light Get(GameCamera camera) { //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) if ((Object)(object)copy != (Object)null && (Object)(object)((Component)copy).transform.parent == (Object)(object)((Component)camera).transform) { return copy; } Reset(); GameObject val = new GameObject("Timber_CameraCirclet"); val.transform.SetParent(((Component)camera).transform, false); copy = val.AddComponent<Light>(); return copy; } private static void Copy(Light light, Light source) { //IL_0002: 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_0017: 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_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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_009b: 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_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) light.type = source.type; light.color = (CircletSettings.TryGetConfiguredColor(out var color) ? color : source.color); light.colorTemperature = source.colorTemperature; light.useColorTemperature = source.useColorTemperature && !CircletSettings.TryGetConfiguredColor(out var _); Vector3 value = CameraPrefs.CircletOffset.Value; ((Component)light).transform.localPosition = new Vector3(Mathf.Clamp(value.x, -5f, 5f), Mathf.Clamp(value.y, -5f, 5f), Mathf.Clamp(value.z, -5f, 5f)); light.cookie = source.cookie; light.renderMode = source.renderMode; light.cullingMask = source.cullingMask; light.shadows = CircletSettings.GetConfiguredShadows(source.shadows); light.shadowStrength = source.shadowStrength; light.intensity = Own(CameraPrefs.CircletIntensity.Value, source.intensity); light.range = Own(CameraPrefs.CircletRange.Value, CircletSource.BaseRange(source)); light.spotAngle = Own(CameraPrefs.CircletSpotAngle.Value, source.spotAngle); light.innerSpotAngle = Mathf.Min(source.innerSpotAngle, light.spotAngle); } private static float Own(float setting, float own) { if (!(setting > 0f)) { return own; } return setting; } } public enum CameraLightShadows { Original, Off, Hard, Soft } internal static class CircletSettings { private const string OriginalColor = "Original"; private static string _cachedColorSetting = string.Empty; private static bool _cachedColorOverride; private static Color _cachedColor; internal static bool TryGetConfiguredColor(out Color color) { //IL_0028: 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) string text = CameraPrefs.CircletColour.Value ?? string.Empty; if (text != _cachedColorSetting) { CacheConfiguredColor(text); } color = _cachedColor; return _cachedColorOverride; } private static void CacheConfiguredColor(string setting) { _cachedColorSetting = setting; string text = setting.Trim(); if (string.IsNullOrEmpty(text) || text.Equals("Original", StringComparison.OrdinalIgnoreCase)) { _cachedColorOverride = false; return; } if (!text.StartsWith("#", StringComparison.Ordinal)) { text = "#" + text; } _cachedColorOverride = ColorUtility.TryParseHtmlString(text, ref _cachedColor); } internal static LightShadows GetConfiguredShadows(LightShadows sourceShadows) { //IL_0022: 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_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_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) return (LightShadows)(CameraPrefs.CircletShadows.Value switch { CameraLightShadows.Off => 0, CameraLightShadows.Hard => 1, CameraLightShadows.Soft => 2, _ => sourceShadows, }); } } public static class CircletSource { private const float LookupSeconds = 0.5f; private const string HeadBone = "Head"; private static Light found; private static float nextLookup; public static void Reset() { found = null; nextLookup = 0f; } public static Light Find(Player player) { if ((Object)(object)found != (Object)null && Lit(found) && Time.time < nextLookup) { return found; } nextLookup = Time.time + 0.5f; Transform val = Head(player); found = (((Object)(object)val != (Object)null) ? Strongest(val) : null); return found; } public static bool Lit(Light light) { if (((Component)light).gameObject.activeInHierarchy) { if (!((Behaviour)light).enabled) { return (Object)(object)((Component)light).GetComponent<LightLod>() != (Object)null; } return true; } return false; } private static Transform Head(Player player) { Transform val = (((Object)(object)player != (Object)null && (Object)(object)((Humanoid)player).m_visEquipment != (Object)null) ? ((Humanoid)player).m_visEquipment.m_helmet : null); if ((Object)(object)val == (Object)null) { return null; } Transform val2 = val; while ((Object)(object)val2 != (Object)null && (Object)(object)val2 != (Object)(object)((Component)player).transform) { if (((Object)val2).name == "Head") { return val2; } val2 = val2.parent; } return val.parent; } private static Light Strongest(Transform head) { Light val = null; Light[] componentsInChildren = ((Component)head).GetComponentsInChildren<Light>(); foreach (Light val2 in componentsInChildren) { if (Lit(val2) && ((Object)(object)val == (Object)null || Strength(val2) > Strength(val))) { val = val2; } } return val; } private static float Strength(Light light) { return light.intensity * BaseRange(light); } public static float BaseRange(Light light) { LightLod component = ((Component)light).GetComponent<LightLod>(); if (!((Object)(object)component != (Object)null) || !(component.m_baseRange > 0f)) { return light.range; } return component.m_baseRange; } } internal sealed class MagpiePickup { private readonly Tuple<Func<object, float>, Func<object, object, bool>, Func<object, object, bool>> contract; private readonly Player player; private readonly ZNet network; private readonly long generation; private readonly long world; private readonly string session; internal float Radius { get; private set; } internal bool Current { get { if (Plugin.IsReady && Plugin.Session.AuthorityReady && world != 0L && Plugin.Session.Generation == generation && Plugi