using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using JetBrains.Annotations; using Jotunn.Entities; using Jotunn.Managers; using Microsoft.CodeAnalysis; using ServerSync; using Splatform; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.Rendering; using UnityEngine.UI; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Core.ObjectPool; using YamlDotNet.Core.Tokens; using YamlDotNet.Helpers; using YamlDotNet.Serialization; using YamlDotNet.Serialization.BufferedDeserialization; using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators; using YamlDotNet.Serialization.Callbacks; using YamlDotNet.Serialization.Converters; using YamlDotNet.Serialization.EventEmitters; using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization.NodeDeserializers; using YamlDotNet.Serialization.NodeTypeResolvers; using YamlDotNet.Serialization.ObjectFactories; using YamlDotNet.Serialization.ObjectGraphTraversalStrategies; using YamlDotNet.Serialization.ObjectGraphVisitors; using YamlDotNet.Serialization.Schemas; using YamlDotNet.Serialization.TypeInspectors; using YamlDotNet.Serialization.TypeResolvers; using YamlDotNet.Serialization.Utilities; using YamlDotNet.Serialization.ValueDeserializers; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Homestead")] [assembly: AssemblyDescription("Player-facing construction tools, native blueprints, blueprint trading, build camera controls, placement helpers, and Dvergr circlet QoL for Valheim.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("sighsorry")] [assembly: AssemblyProduct("Homestead")] [assembly: AssemblyCopyright("Copyright 2026 sighsorry")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("4358610B-F3F4-4843-B7AF-98B7BC60DCDE")] [assembly: AssemblyFileVersion("1.0.5")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.5.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class ExtensionMarkerAttribute : Attribute { private readonly string k__BackingField; public string Name => k__BackingField; public ExtensionMarkerAttribute(string name) { k__BackingField = name; } } } namespace Homestead { internal static class AzuCraftyBoxesCompat { private const string ApiTypeName = "AzuCraftyBoxes.API"; private const string PluginTypeName = "AzuCraftyBoxes.AzuCraftyBoxesPlugin"; private const string MiscFunctionsTypeName = "AzuCraftyBoxes.Util.Functions.MiscFunctions"; private const string BoxesTypeName = "AzuCraftyBoxes.Util.Functions.Boxes"; private const float FallbackRange = 20f; private const float PatchRetryIntervalSeconds = 2f; private static readonly HashSet ProtectedContainerPrefabs = new HashSet(StringComparer.OrdinalIgnoreCase) { "piece_chest_wood_blueprint", "piece_chest_barrel_blueprint_store_price", "piece_chest_blueprint_store_purchase", "piece_chest_blackmetal_blueprint_store_payout" }; private static bool _initialized; private static ManualLogSource? _logger; private static Harmony? _harmony; private static Type? _apiType; private static Type? _pluginType; private static Type? _miscFunctionsType; private static Type? _boxesType; private static Type? _queryFrameType; private static MethodInfo? _getNearbyContainersDefinition; private static MethodInfo? _canItemBePulled; private static MethodInfo? _apiRemoveContainer; private static MethodInfo? _boxesRemoveContainer; private static MethodInfo? _shouldPrevent; private static MethodInfo? _checkAndDecrement; private static FieldInfo? _rangeField; private static bool _pullFilterPatchApplied; private static bool _loggedPullFilterPatchFailure; private static float _nextPatchRetryAt; internal static bool IsLoaded { get { EnsureInitialized(); if (_apiType != null) { return InvokeStaticBool(_apiType.GetMethod("IsLoaded", BindingFlags.Static | BindingFlags.Public), fallback: true); } return false; } } internal static void Initialize(ManualLogSource logger, Harmony harmony) { _logger = logger; _harmony = harmony; EnsureInitialized(force: true); TryPatchPullFilter(); } internal static void Update() { if (!_pullFilterPatchApplied && Time.realtimeSinceStartup >= _nextPatchRetryAt) { TryPatchPullFilter(); } } internal static int PullMissingMaterials(Component source, IReadOnlyList missingRequirements, Action acceptPulledMaterial) { if ((Object)(object)source == (Object)null || missingRequirements.Count == 0 || acceptPulledMaterial == null) { return 0; } EnsureInitialized(); if (!IsUsable()) { return 0; } if (InvokeStaticBool(_shouldPrevent, fallback: false)) { return 0; } IEnumerable nearbyContainers = GetNearbyContainers(source, GetPullRange()); if (nearbyContainers == null) { return 0; } int num = 0; foreach (ZoneBlueprintRequirement item in missingRequirements.Where((ZoneBlueprintRequirement requirement) => requirement.Amount > 0)) { int num2 = item.Amount; foreach (object item2 in nearbyContainers) { if (num2 <= 0) { break; } string text = InvokeString(item2, "GetPrefabName"); if (!string.IsNullOrWhiteSpace(text) && !string.Equals(text, "piece_chest_wood_blueprint", StringComparison.OrdinalIgnoreCase) && !ZoneBlueprintStoreChestPrefab.IsStorePrefabName(text) && CanItemBePulled(text, item.PrefabName)) { int amount = InvokeInt(item2, "ItemCount", item.ItemName); int num3 = Mathf.Max(0, CheckAndDecrement(amount)); int num4 = Mathf.Min(num2, num3); if (num4 > 0) { InvokeVoid(item2, "RemoveItem", item.ItemName, num4); InvokeVoid(item2, "Save"); acceptPulledMaterial(item, num4); num2 -= num4; num += num4; } } } } return num; } internal static void RemoveContainer(Container? container, string source) { if (!Object.op_Implicit((Object)(object)container)) { return; } EnsureInitialized(_apiType == null || _boxesType == null); int num = 0 | (InvokeStaticVoid(_apiRemoveContainer, container) ? 1 : 0) | (InvokeStaticVoid(_boxesRemoveContainer, container) ? 1 : 0) | (RemoveContainerFromAzuSets(container) ? 1 : 0); InvalidateNearbyContainerCache(); if (num != 0) { ManualLogSource? logger = _logger; if (logger != null) { logger.LogDebug((object)("Removed Homestead container from AzuCraftyBoxes registry/cache (" + source + "): " + NormalizePrefabName(((Object)container).name ?? ""))); } } } private static void EnsureInitialized(bool force = false) { if (!_initialized || force) { _initialized = true; _apiType = FindType("AzuCraftyBoxes.API"); _pluginType = FindType("AzuCraftyBoxes.AzuCraftyBoxesPlugin"); _miscFunctionsType = FindType("AzuCraftyBoxes.Util.Functions.MiscFunctions"); _boxesType = FindType("AzuCraftyBoxes.Util.Functions.Boxes"); _queryFrameType = _boxesType?.GetNestedType("QueryFrame", BindingFlags.Public | BindingFlags.NonPublic); _getNearbyContainersDefinition = _apiType?.GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault((MethodInfo method) => method.Name == "GetNearbyContainers" && method.IsGenericMethodDefinition); _canItemBePulled = _apiType?.GetMethod("CanItemBePulled", BindingFlags.Static | BindingFlags.Public, null, new Type[2] { typeof(string), typeof(string) }, null); _apiRemoveContainer = _apiType?.GetMethod("RemoveContainer", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(Container) }, null); _boxesRemoveContainer = _boxesType?.GetMethod("RemoveContainer", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(Container) }, null); _shouldPrevent = _miscFunctionsType?.GetMethod("ShouldPrevent", BindingFlags.Static | BindingFlags.NonPublic); _checkAndDecrement = _boxesType?.GetMethod("CheckAndDecrement", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); _rangeField = _pluginType?.GetField("mRange", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } } private static void TryPatchPullFilter() { //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Expected O, but got Unknown if (_pullFilterPatchApplied || _harmony == null) { return; } EnsureInitialized(_boxesType == null); _nextPatchRetryAt = Time.realtimeSinceStartup + 2f; if (_boxesType == null) { return; } MethodInfo methodInfo = _boxesType.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault(delegate(MethodInfo method) { if (method.Name != "CanItemBePulled") { return false; } ParameterInfo[] parameters = method.GetParameters(); return parameters.Length >= 2 && parameters[0].ParameterType == typeof(string) && parameters[1].ParameterType == typeof(string); }); MethodInfo method2 = typeof(AzuCraftyBoxesCompat).GetMethod("CanItemBePulledPrefix", BindingFlags.Static | BindingFlags.NonPublic); if (methodInfo == null || method2 == null) { if (!_loggedPullFilterPatchFailure) { _loggedPullFilterPatchFailure = true; ManualLogSource? logger = _logger; if (logger != null) { logger.LogDebug((object)"AzuCraftyBoxes CanItemBePulled patch target is not available yet."); } } return; } try { _harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _pullFilterPatchApplied = true; ManualLogSource? logger2 = _logger; if (logger2 != null) { logger2.LogInfo((object)"AzuCraftyBoxes pull filter patched for Homestead blueprint containers."); } } catch (Exception ex) { if (!_loggedPullFilterPatchFailure) { _loggedPullFilterPatchFailure = true; ManualLogSource? logger3 = _logger; if (logger3 != null) { logger3.LogDebug((object)("Could not patch AzuCraftyBoxes pull filter: " + ex.Message)); } } } } private static bool CanItemBePulledPrefix(string container, ref bool __result) { if (!IsProtectedContainerPrefab(container)) { return true; } __result = false; return false; } private static bool IsProtectedContainerPrefab(string? prefabName) { string text = prefabName ?? ""; if (string.IsNullOrWhiteSpace(text)) { return false; } return ProtectedContainerPrefabs.Contains(NormalizePrefabName(text)); } private static string NormalizePrefabName(string prefabName) { int num = prefabName.IndexOfAny(new char[2] { '(', ' ' }); if (num >= 0) { return prefabName.Substring(0, num); } return prefabName; } private static bool InvokeStaticVoid(MethodInfo? method, Container container) { try { method?.Invoke(null, new object[1] { container }); return method != null; } catch { return false; } } private static bool RemoveContainerFromAzuSets(Container container) { return false | RemoveContainerFromSet("Containers", container) | RemoveContainerFromSet("ContainersToAdd", container) | RemoveContainerFromSet("ContainersToRemove", container); } private static bool RemoveContainerFromSet(string fieldName, Container container) { try { object obj = _boxesType?.GetField(fieldName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(null); object obj2 = (obj?.GetType().GetMethod("Remove", new Type[1] { typeof(Container) }))?.Invoke(obj, new object[1] { container }); bool flag = default(bool); int num; if (obj2 is bool) { flag = (bool)obj2; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch { return false; } } private static void InvalidateNearbyContainerCache() { //IL_00e3: Unknown result type (might be due to invalid IL or missing references) try { _queryFrameType?.GetField("FrameId", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(null, -1); _queryFrameType?.GetField("Nearby", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(null, null); ClearListField(_boxesType, "_cachedAll"); ClearListField(_boxesType, "_scratchNearby"); _boxesType?.GetField("_lastQueryTime", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(null, float.NegativeInfinity); _boxesType?.GetField("_lastQueryRange", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(null, -1f); _boxesType?.GetField("_lastQueryPos", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(null, Vector3.positiveInfinity); } catch { } } private static void ClearListField(Type? type, string fieldName) { try { if (type?.GetField(fieldName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(null) is IList list) { list.Clear(); } } catch { } } private static bool IsUsable() { if (_apiType != null && _getNearbyContainersDefinition != null) { return _canItemBePulled != null; } return false; } private static IEnumerable? GetNearbyContainers(Component source, float range) { try { return _getNearbyContainersDefinition.MakeGenericMethod(((object)source).GetType()).Invoke(null, new object[2] { source, range }) as IEnumerable; } catch { return null; } } private static float GetPullRange() { try { object obj = _rangeField?.GetValue(null); object obj2 = obj?.GetType().GetProperty("Value")?.GetValue(obj, null); if (obj2 != null) { return Mathf.Max(1f, Convert.ToSingle(obj2, CultureInfo.InvariantCulture)); } } catch { } return 20f; } private static bool CanItemBePulled(string containerPrefab, string itemPrefab) { try { object obj = _canItemBePulled?.Invoke(null, new object[2] { containerPrefab, itemPrefab }); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch { return false; } } private static int CheckAndDecrement(int amount) { try { return (_checkAndDecrement?.Invoke(null, new object[1] { amount }) is int num) ? num : amount; } catch { return amount; } } private static Type? FindType(string fullName) { string fullName2 = fullName; return (from assembly in AppDomain.CurrentDomain.GetAssemblies() select assembly.GetType(fullName2, throwOnError: false)).FirstOrDefault((Type type) => type != null); } private static string InvokeString(object target, string methodName) { try { return (target.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public)?.Invoke(target, Array.Empty()) as string) ?? ""; } catch { return ""; } } private static int InvokeInt(object target, string methodName, params object[] args) { try { return (target.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public)?.Invoke(target, args) is int num) ? num : 0; } catch { return 0; } } private static void InvokeVoid(object target, string methodName, params object[] args) { try { target.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public)?.Invoke(target, args); } catch { } } private static bool InvokeStaticBool(MethodInfo? method, bool fallback) { try { return (method?.Invoke(null, Array.Empty()) is bool flag) ? flag : fallback; } catch { return fallback; } } private static Exception Unwrap(Exception ex) { if (!(ex is TargetInvocationException) || ex.InnerException == null) { return ex; } return ex.InnerException; } } internal static class AzuExtendedPlayerInventoryCompat { private const string PluginGuid = "Azumatt.AzuExtendedPlayerInventory"; private const string CustomEquipVisualsTypeName = "AzuEPI.Game.PlayerPreview.CustomEquipVisuals"; private static readonly BindingFlags StaticFieldFlags = BindingFlags.Static | BindingFlags.NonPublic; private static readonly BindingFlags InstanceFieldFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private static bool _initialized; private static bool _loaded; private static FieldInfo? _statesField; public static bool IsLoaded { get { EnsureInitialized(); return _loaded; } } public static bool TryGetCustomEquippedItem(Player player, Func predicate, out ItemData? item) { item = null; if (!IsLoaded || !Object.op_Implicit((Object)(object)player)) { return false; } Inventory inventory = ((Humanoid)player).GetInventory(); if (inventory == null) { return false; } foreach (ItemData allItem in inventory.GetAllItems()) { if (allItem != null && allItem.m_equipped && allItem != ((Humanoid)player).m_helmetItem && allItem != ((Humanoid)player).m_chestItem && allItem != ((Humanoid)player).m_legItem && allItem != ((Humanoid)player).m_shoulderItem && allItem != ((Humanoid)player).m_utilityItem && allItem != ((Humanoid)player).m_trinketItem && predicate(allItem)) { item = allItem; return true; } } return false; } public static bool TryGetCustomEquipVisualRoots(VisEquipment visEquipment, ItemData item, List roots) { roots.Clear(); if (!IsLoaded || !Object.op_Implicit((Object)(object)visEquipment) || item == null || _statesField == null) { return false; } try { if (!(_statesField.GetValue(null) is IDictionary dictionary) || !dictionary.Contains(visEquipment)) { return false; } object obj = dictionary[visEquipment]; if (obj == null) { return false; } if (!(obj.GetType().GetField("Equipped", InstanceFieldFlags)?.GetValue(obj) is IDictionary dictionary2)) { return false; } foreach (DictionaryEntry item2 in dictionary2) { object value = item2.Value; if (value == null) { continue; } Type type = value.GetType(); if (type.GetField("Item", InstanceFieldFlags)?.GetValue(value) != item || !(type.GetField("Instances", InstanceFieldFlags)?.GetValue(value) is IEnumerable enumerable)) { continue; } foreach (object item3 in enumerable) { GameObject val = (GameObject)((item3 is GameObject) ? item3 : null); if (val != null && Object.op_Implicit((Object)(object)val)) { roots.Add(val); } } } } catch { roots.Clear(); } return roots.Count > 0; } public static void ResetForWorldSession() { if (!_loaded) { _initialized = false; _statesField = null; } } private static void EnsureInitialized() { if (!_initialized) { _initialized = true; if (Chainloader.PluginInfos.TryGetValue("Azumatt.AzuExtendedPlayerInventory", out var value)) { _statesField = ((((object)value.Instance)?.GetType().Assembly)?.GetType("AzuEPI.Game.PlayerPreview.CustomEquipVisuals", throwOnError: false))?.GetField("_states", StaticFieldFlags); _loaded = true; } } } } internal static class BlueprintTerrainApplier { public static List CaptureContacts(Vector3 anchor, Quaternion inverseAnchorRotation, IEnumerable sources) { //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) List contacts = BlueprintTerrainContactSampler.CaptureWorldContacts(sources, BlueprintConfig.TerrainSupportContactTolerance); return BlueprintTerrainContactSampler.ToBlueprintContacts(anchor, inverseAnchorRotation, contacts); } public static bool ApplySupportContacts(IEnumerable supportContacts) { return HomesteadTerrainSupport.ApplyWorldSupportContacts(supportContacts); } public static IEnumerator ApplySupportContactsAsync(IEnumerable supportContacts, Action onComplete) { return HomesteadTerrainSupport.ApplyWorldSupportContactsAsync(supportContacts, onComplete); } } internal static class BlueprintTerrainContactSampler { public static List CaptureWorldContacts(IEnumerable sources, float tolerance) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) Dictionary dictionary = new Dictionary(); foreach (TerrainContactSource source in sources) { if (Object.op_Implicit((Object)(object)source.Prefab) && !((Object)(object)source.Prefab.GetComponent() == (Object)null) && HomesteadTerrainSupport.TryGetWearNTearBounds(source.Prefab, source.Position, source.Rotation, source.Scale, out var bounds)) { AddLowestBoundsFootprintContacts(bounds, dictionary); } } List list = new List(); foreach (TerrainWorldContact item in from contact in dictionary.Values orderby contact.WorldZ, contact.WorldX select contact) { if (HomesteadTerrainSupport.TryGetTerrainHeight(item.WorldX, item.WorldZ, out var height) && !(Mathf.Abs(height - item.WorldY) > tolerance)) { list.Add(item); } } return list; } public static List ToBlueprintContacts(Vector3 anchor, Quaternion inverseAnchorRotation, IEnumerable contacts) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //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) return (from contact in contacts.Select(delegate(TerrainWorldContact contact) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: 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_001d: 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_0035: 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) Vector3 val = inverseAnchorRotation * (contact.ToVector3() - anchor); return new ZoneBlueprintTerrainContact { LocalX = Round(val.x), LocalY = Round(val.y), LocalZ = Round(val.z) }; }) orderby contact.LocalZ, contact.LocalX select contact).ToList(); } private static void AddLowestBoundsFootprintContacts(Bounds bounds, Dictionary lowestByCell) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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_0044: Unknown result type (might be due to invalid IL or missing references) float y = ((Bounds)(ref bounds)).min.y; int num = Mathf.FloorToInt(((Bounds)(ref bounds)).min.x); int num2 = Mathf.CeilToInt(((Bounds)(ref bounds)).max.x); int num3 = Mathf.FloorToInt(((Bounds)(ref bounds)).min.z); int num4 = Mathf.CeilToInt(((Bounds)(ref bounds)).max.z); for (int i = num; i <= num2; i++) { for (int j = num3; j <= num4; j++) { long key = PackCell(i, j); TerrainWorldContact value = new TerrainWorldContact(i, j, y); if (!lowestByCell.TryGetValue(key, out var value2) || value.WorldY < value2.WorldY) { lowestByCell[key] = value; } } } } private static long PackCell(int x, int z) { return ((long)x << 32) ^ (uint)z; } private static float Round(float value) { return Mathf.Round(value * 1000f) / 1000f; } } internal readonly struct TerrainContactSource { public GameObject Prefab { get; } public Vector3 Position { get; } public Quaternion Rotation { get; } public Vector3 Scale { get; } public TerrainContactSource(GameObject prefab, Vector3 position, Quaternion rotation, Vector3 scale) { //IL_0008: 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_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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_0018: Unknown result type (might be due to invalid IL or missing references) Prefab = prefab; Position = position; Rotation = rotation; Scale = scale; } } internal readonly struct TerrainWorldContact { public float WorldX { get; } public float WorldZ { get; } public float WorldY { get; } public TerrainWorldContact(int cellX, int cellZ, float worldY) { WorldX = cellX; WorldZ = cellZ; WorldY = worldY; } public Vector3 ToVector3() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) return new Vector3(WorldX, WorldY, WorldZ); } } [BepInPlugin("sighsorry.Homestead", "Homestead", "1.0.5")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class HomesteadPlugin : BaseUnityPlugin { public enum Toggle { On = 1, Off = 0 } internal const string ModName = "Homestead"; internal const string ModVersion = "1.0.5"; internal const string Author = "sighsorry"; internal const string ModGUID = "sighsorry.Homestead"; internal const string DataStorageFolder = "Homestead"; internal const string BlueprintStorageFolder = "Blueprints"; internal const string ServerBlueprintStorageFolder = "ServerBlueprints"; internal const string PlanGhostStorageFolder = "PlanGhosts"; internal const string BlueprintStoreStorageFolder = "Store"; private const string ConfigFileName = "sighsorry.Homestead.cfg"; private const long ReloadDelay = 10000000L; private static readonly string ConfigFileFullPath = Path.Combine(Paths.ConfigPath, "sighsorry.Homestead.cfg"); internal static readonly string DataStorageFullPath = Path.Combine(Paths.ConfigPath, "Homestead"); internal static readonly string BlueprintStorageFullPath = Path.Combine(DataStorageFullPath, "Blueprints"); internal static readonly string ServerBlueprintStorageFullPath = Path.Combine(DataStorageFullPath, "ServerBlueprints"); internal static readonly string PlanGhostStorageFullPath = Path.Combine(ServerBlueprintStorageFullPath, "PlanGhosts"); internal static readonly string BlueprintStoreStorageFullPath = Path.Combine(ServerBlueprintStorageFullPath, "Store"); internal static readonly ManualLogSource HomesteadLogger = Logger.CreateLogSource("Homestead"); internal static readonly ConfigSync ConfigSync = new ConfigSync("sighsorry.Homestead") { DisplayName = "Homestead", CurrentVersion = "1.0.5", MinimumRequiredVersion = "1.0.5" }; internal static string ConnectionError = ""; private readonly Harmony _harmony = new Harmony("sighsorry.Homestead"); private readonly object _reloadLock = new object(); private FileSystemWatcher? _configWatcher; private DateTime _lastConfigReloadTime; internal static HomesteadPlugin Instance { get; private set; } = null; private void BindConfiguration() { BindSharedConfiguration(); BindConstructionConfiguration(); } private void BindSharedConfiguration() { GeneralConfig.Bind(this); ClientConfig.Bind(this); } private void BindConstructionConfiguration() { BlueprintConfig.Bind(this); BuildCameraConfig.Bind(this); PlacementControlConfig.Bind(this); DvergrCircletConfig.Bind(this); } public void Awake() { Instance = this; bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet; ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; BindConfiguration(); HomesteadLocalization.Load(HomesteadLogger); EnsureDataDirectories(); HomesteadFeatureBootstrap.Initialize(HomesteadLogger, _harmony); SetupWatchers(); SaveWithRespectToConfigSet(); if (saveOnConfigSet) { ((BaseUnityPlugin)this).Config.SaveOnConfigSet = true; } } private void OnDestroy() { SaveWithRespectToConfigSet(); HomesteadFeatureBootstrap.Shutdown(); _configWatcher?.Dispose(); } private void Update() { HomesteadFeatureBootstrap.Update(); } private void SetupWatchers() { EnsureDataDirectories(); _configWatcher = new FileSystemWatcher(Paths.ConfigPath, "sighsorry.Homestead.cfg"); _configWatcher.Changed += ReadConfigValues; _configWatcher.Created += ReadConfigValues; _configWatcher.Renamed += ReadConfigValues; _configWatcher.IncludeSubdirectories = false; _configWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; _configWatcher.EnableRaisingEvents = true; } private static void EnsureDataDirectories() { Directory.CreateDirectory(DataStorageFullPath); Directory.CreateDirectory(BlueprintStorageFullPath); Directory.CreateDirectory(PlanGhostStorageFullPath); Directory.CreateDirectory(BlueprintStoreStorageFullPath); } private void ReadConfigValues(object sender, FileSystemEventArgs e) { if (!CanReload(ref _lastConfigReloadTime)) { return; } lock (_reloadLock) { if (!File.Exists(ConfigFileFullPath)) { HomesteadLogger.LogWarning((object)"Config file does not exist. Skipping reload."); return; } try { HomesteadLogger.LogDebug((object)"Reloading configuration..."); ReloadConfigFromDisk(); HomesteadLogger.LogInfo((object)"Configuration reload complete."); } catch (Exception arg) { HomesteadLogger.LogError((object)$"Error reloading configuration: {arg}"); } } } private static bool CanReload(ref DateTime lastReloadTime) { DateTime now = DateTime.Now; if (now.Ticks - lastReloadTime.Ticks < 10000000) { return false; } lastReloadTime = now; return true; } private void SaveWithRespectToConfigSet(bool reload = false) { bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet; ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; if (reload) { ((BaseUnityPlugin)this).Config.Reload(); } ((BaseUnityPlugin)this).Config.Save(); ((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnConfigSet; } private void ReloadConfigFromDisk() { bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet; ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; ((BaseUnityPlugin)this).Config.Reload(); ((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnConfigSet; } internal ConfigEntry config(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown ConfigDescription val = new ConfigDescription(description.Description + (synchronizedSetting ? " [Synced with Server]" : " [Client Only]"), description.AcceptableValues, description.Tags); ConfigEntry val2 = ((BaseUnityPlugin)this).Config.Bind(group, name, value, val); ConfigSync.AddConfigEntry(val2).SynchronizedConfig = synchronizedSetting; return val2; } internal ConfigEntry config(string group, string name, T value, string description, bool synchronizedSetting = true) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty()), synchronizedSetting); } } internal sealed class HomesteadCommandResult { public bool Success { get; set; } public string Message { get; set; } = ""; public static HomesteadCommandResult Ok(string message) { return new HomesteadCommandResult { Success = true, Message = message }; } public static HomesteadCommandResult Fail(string message) { return new HomesteadCommandResult { Success = false, Message = message }; } } internal static class GeneralConfig { private static ConfigEntry _serverConfigLocked; public static void Bind(HomesteadPlugin plugin) { _serverConfigLocked = plugin.config("01 - General", "Lock Configuration", HomesteadPlugin.Toggle.On, "If on, the server controls synced settings."); HomesteadPlugin.ConfigSync.AddLockingConfigEntry(_serverConfigLocked); } } internal static class ClientConfig { private static ConfigEntry _counterVisibleSeconds; private static ConfigEntry _statusHudX; private static ConfigEntry _statusHudY; private static ConfigEntry _statusHudFontSize; public static float CounterVisibleSeconds => Mathf.Max(0.1f, _counterVisibleSeconds.Value); public static Vector2 StatusHudPosition => new Vector2(Mathf.Clamp(_statusHudX.Value, 0f, 3000f), 0f - Mathf.Clamp(_statusHudY.Value, 0f, 3000f)); public static int StatusHudFontSize => Mathf.Clamp(_statusHudFontSize.Value, 10, 64); public static void Bind(HomesteadPlugin plugin) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Expected O, but got Unknown _counterVisibleSeconds = plugin.config("02 - Client", "Build Counter Visible Seconds", 2.5f, new ConfigDescription("How long the top build counter stays visible after you place a build piece.", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 10f), Array.Empty()), synchronizedSetting: false); _statusHudX = plugin.config("02 - Client", "Status HUD X Offset", 28f, new ConfigDescription("Client-only X offset in pixels from the top-left corner for the unified status HUD.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 3000f), Array.Empty()), synchronizedSetting: false); _statusHudY = plugin.config("02 - Client", "Status HUD Y Offset", 116f, new ConfigDescription("Client-only Y offset in pixels from the top-left corner for the unified status HUD.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 3000f), Array.Empty()), synchronizedSetting: false); _statusHudFontSize = plugin.config("02 - Client", "Status HUD Font Size", 18, new ConfigDescription("Client-only font size for the unified status HUD. HUD width and height are calculated from this value.", (AcceptableValueBase)(object)new AcceptableValueRange(10, 64), Array.Empty()), synchronizedSetting: false); } } internal readonly struct BlueprintNetworkSettings { public int MaxUploadBytes { get; } public int MaxEntries { get; } public int MaxPreviewEntries { get; } public int MaxIconBytes { get; } public BlueprintNetworkSettings(int maxUploadBytes, int maxEntries, int maxPreviewEntries, int maxIconBytes) { MaxUploadBytes = maxUploadBytes; MaxEntries = maxEntries; MaxPreviewEntries = maxPreviewEntries; MaxIconBytes = maxIconBytes; } } internal readonly struct BlueprintStoreSettings { public int ListingDays { get; } public int AutoDelistMaxPurchases { get; } public int MaxListingsPerSteamId { get; } public BlueprintStoreIdentityMode IdentityMode { get; } public BlueprintStoreSettings(int listingDays, int autoDelistMaxPurchases, int maxListingsPerSteamId, BlueprintStoreIdentityMode identityMode) { ListingDays = listingDays; AutoDelistMaxPurchases = autoDelistMaxPurchases; MaxListingsPerSteamId = maxListingsPerSteamId; IdentityMode = identityMode; } } internal static class BlueprintConfig { private static ConfigEntry _terrainSupport = null; private static ConfigEntry _chestRows = null; private static ConfigEntry _chestConfirmHotkey = null; private static ConfigEntry _azuCraftyBoxesPullMode = null; private static ConfigEntry _terrainSupportContactTolerance = null; private static ConfigEntry _terrainSupportFeatherWidth = null; private static ConfigEntry _maxUploadKb = null; private static ConfigEntry _maxEntries = null; private static ConfigEntry _maxPreviewEntries = null; private static ConfigEntry _maxIconKb = null; private static ConfigEntry _storeListingDays = null; private static ConfigEntry _storeAutoDelistMaxPurchases = null; private static ConfigEntry _storeMaxListingsPerSteamId = null; private static ConfigEntry _storeIdentityMode = null; private static ConfigEntry _chestTimeoutMinutes = null; private static ConfigEntry _chestMapIconSize = null; private static ConfigEntry _maxActiveChestsPerPlayer = null; private static ConfigEntry _storeLargePanelScale = null; private static ConfigEntry _storeLargePanelX = null; private static ConfigEntry _storeLargePanelY = null; private static ConfigEntry _storeFormPanelScale = null; private static ConfigEntry _storeFormPanelX = null; private static ConfigEntry _storeFormPanelY = null; private static ConfigEntry _storeAnonymousNotifications = null; private static ConfigEntry _storeNotificationMode = null; private static ConfigEntry _storeDebugLogging = null; private static ConfigEntry _storeNotificationButtonX = null; private static ConfigEntry _storeNotificationButtonY = null; private static ConfigEntry _storeListModifierKey = null; private static ConfigEntry _storeBackHotkey = null; private static ConfigEntry _storeListingPreviewColor = null; private static ConfigEntry _storePurchasePreviewColor = null; private static ConfigEntry _areaSaveMaxSide = null; private static ConfigEntry _areaSaveDefaultWidth = null; private static ConfigEntry _areaSaveDefaultDepth = null; private static ConfigEntry _areaSaveCreatorMode = null; private static ConfigEntry _areaSaveBoundaryColor = null; private static ConfigEntry _areaDismantleMaxSide = null; private static ConfigEntry _areaDismantleDefaultWidth = null; private static ConfigEntry _areaDismantleDefaultDepth = null; private static ConfigEntry _areaDismantleBoundaryColor = null; private static ConfigEntry _areaDismantlePrefabBlacklist = null; private static ConfigEntry _areaToolDepthModifierKey = null; private static ConfigEntry _areaToolWidthModifierKey = null; private static ConfigEntry _previewGhostColor = null; private static ConfigEntry _previewGhostBrightness = null; private static readonly HashSet BuiltInAreaDismantleProtectedPrefabs = new HashSet(StringComparer.OrdinalIgnoreCase) { "piece_chest_wood_blueprint", "piece_chest_barrel_blueprint_store_price", "piece_chest_blueprint_store_purchase", "piece_chest_blackmetal_blueprint_store_payout" }; public static bool TerrainSupportEnabled => _terrainSupport.Value == BlueprintTerrainSupportMode.On; public static int ChestRows => Mathf.Clamp(_chestRows.Value, 10, 40); public static KeyboardShortcut ChestConfirmHotkey => _chestConfirmHotkey.Value; public static bool AzuCraftyBoxesPullOnConfirm => _azuCraftyBoxesPullMode.Value != BlueprintAzuCraftyBoxesPullMode.Off; public static bool AzuCraftyBoxesPullOnOpen => _azuCraftyBoxesPullMode.Value == BlueprintAzuCraftyBoxesPullMode.OpenAndConfirm; public static float TerrainSupportContactTolerance => Mathf.Clamp(_terrainSupportContactTolerance.Value, 0.01f, 2f); public static float TerrainSupportFeatherWidth => Mathf.Clamp(_terrainSupportFeatherWidth.Value, 0f, 64f); public static int MaxUploadKb => Mathf.Clamp(_maxUploadKb.Value, 64, 16384); public static int MaxUploadBytes => MaxUploadKb * 1024; public static int MaxEntries => Mathf.Clamp(_maxEntries.Value, 1, 20000); public static int MaxPreviewEntries => Mathf.Clamp(_maxPreviewEntries.Value, 1, MaxEntries); public static int MaxIconKb => Mathf.Clamp(_maxIconKb.Value, 0, 2048); public static int MaxIconBytes => MaxIconKb * 1024; public static BlueprintNetworkSettings NetworkSettings => new BlueprintNetworkSettings(MaxUploadBytes, MaxEntries, MaxPreviewEntries, MaxIconBytes); public static int StoreListingDays => Mathf.Clamp(_storeListingDays.Value, 0, 365); public static int StoreAutoDelistMaxPurchases => Mathf.Clamp(_storeAutoDelistMaxPurchases.Value, 0, 100000); public static int StoreMaxListingsPerSteamId => Mathf.Clamp(_storeMaxListingsPerSteamId.Value, 1, 200); public static BlueprintStoreIdentityMode StoreIdentityMode => _storeIdentityMode.Value; public static BlueprintStoreSettings StoreSettings => new BlueprintStoreSettings(StoreListingDays, StoreAutoDelistMaxPurchases, StoreMaxListingsPerSteamId, StoreIdentityMode); public static int ChestTimeoutMinutes => Mathf.Clamp(_chestTimeoutMinutes.Value, 0, 60); public static int ChestMapIconSize => Mathf.Clamp(_chestMapIconSize.Value, 0, 10); public static int MaxActiveChestsPerPlayer => Mathf.Clamp(_maxActiveChestsPerPlayer.Value, 0, 50); public static float StoreLargePanelScale => Mathf.Clamp(_storeLargePanelScale.Value, 0.75f, 2f); public static Vector2 StoreLargePanelOffset => new Vector2(Mathf.Clamp(_storeLargePanelX.Value, -2000f, 2000f), Mathf.Clamp(_storeLargePanelY.Value, -2000f, 2000f)); public static float StoreFormPanelScale => Mathf.Clamp(_storeFormPanelScale.Value, 0.75f, 2f); public static Vector2 StoreFormPanelOffset => new Vector2(Mathf.Clamp(_storeFormPanelX.Value, -2000f, 2000f), Mathf.Clamp(_storeFormPanelY.Value, -2000f, 2000f)); public static float StoreUiScale => StoreLargePanelScale; public static int StoreNotificationPollSeconds { get { if (!StoreNotificationsEnabled) { return 0; } return 900; } } public static BlueprintStoreNotificationMode StoreNotificationMode => _storeNotificationMode.Value; public static bool StoreNotificationsEnabled => StoreNotificationMode != BlueprintStoreNotificationMode.Off; public static bool StoreNotificationAutoOpen => StoreNotificationMode == BlueprintStoreNotificationMode.AutoOpenPanel; public static bool StoreAnonymousNotifications => _storeAnonymousNotifications.Value.IsOn(); public static bool StoreNotificationButtonEnabled => StoreNotificationsEnabled; public static bool StoreDebugLogging => _storeDebugLogging.Value.IsOn(); public static Vector2 StoreNotificationButtonOffset => new Vector2(Mathf.Clamp(_storeNotificationButtonX.Value, -3000f, 3000f), Mathf.Clamp(_storeNotificationButtonY.Value, -3000f, 3000f)); public static KeyboardShortcut StoreListModifierKey => _storeListModifierKey.Value; public static string StoreListModifierLabel => ConfigValueHelpers.FormatShortcut(StoreListModifierKey); public static KeyboardShortcut StoreBackHotkey => _storeBackHotkey.Value; public static string StoreBackHotkeyLabel => ConfigValueHelpers.FormatShortcut(StoreBackHotkey); public static Color StoreListingPreviewColor => GetStorePendingPreviewColor(_storeListingPreviewColor.Value, new Color(1f, 0.9f, 0.2f, 0.15f)); public static Color StorePurchasePreviewColor => GetStorePendingPreviewColor(_storePurchasePreviewColor.Value, new Color(1f, 0.54f, 0.12f, 0.15f)); public static float AreaSaveMaxSide => Mathf.Clamp(_areaSaveMaxSide.Value, 2f, 256f); public static float AreaSaveDefaultWidth => Mathf.Clamp(_areaSaveDefaultWidth.Value, 2f, AreaSaveMaxSide); public static float AreaSaveDefaultDepth => Mathf.Clamp(_areaSaveDefaultDepth.Value, 2f, AreaSaveMaxSide); public static BlueprintAreaSaveCreatorMode AreaSaveCreatorMode => _areaSaveCreatorMode.Value; public static string AreaSaveEligibleTargetLabel => AreaSaveCreatorMode switch { BlueprintAreaSaveCreatorMode.AllCreators => "WearNTear", BlueprintAreaSaveCreatorMode.OwnedAndCreatorless => "owned or creatorless WearNTear", _ => "owned WearNTear", }; public static Color AreaSaveBoundaryColor => _areaSaveBoundaryColor.Value; public static float AreaDismantleMaxSide => Mathf.Clamp(_areaDismantleMaxSide.Value, 1f, 128f); public static float AreaDismantleDefaultWidth => Mathf.Clamp(_areaDismantleDefaultWidth.Value, 1f, AreaDismantleMaxSide); public static float AreaDismantleDefaultDepth => Mathf.Clamp(_areaDismantleDefaultDepth.Value, 1f, AreaDismantleMaxSide); public static Color AreaDismantleBoundaryColor => _areaDismantleBoundaryColor.Value; public static HashSet AreaDismantlePrefabBlacklist => ConfigValueHelpers.SplitPrefabList(_areaDismantlePrefabBlacklist.Value); public static KeyboardShortcut AreaToolDepthModifierKey => _areaToolDepthModifierKey.Value; public static string AreaToolDepthModifierLabel => ConfigValueHelpers.FormatShortcut(AreaToolDepthModifierKey); public static string AreaToolDepthInputLabel { get { //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_0008: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut areaToolDepthModifierKey = AreaToolDepthModifierKey; if ((int)((KeyboardShortcut)(ref areaToolDepthModifierKey)).MainKey != 0) { return AreaToolDepthModifierLabel + "+Wheel"; } return ""; } } public static KeyboardShortcut AreaToolWidthModifierKey => _areaToolWidthModifierKey.Value; public static string AreaToolWidthModifierLabel => ConfigValueHelpers.FormatShortcut(AreaToolWidthModifierKey); public static string AreaToolWidthInputLabel { get { //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_0008: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut areaToolWidthModifierKey = AreaToolWidthModifierKey; if ((int)((KeyboardShortcut)(ref areaToolWidthModifierKey)).MainKey != 0) { return AreaToolWidthModifierLabel + "+Wheel"; } return ""; } } public static Color PreviewGhostColor { get { //IL_0005: 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_0027: 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_004f: 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_0073: Unknown result type (might be due to invalid IL or missing references) Color value = _previewGhostColor.Value; float num = Mathf.Clamp(_previewGhostBrightness.Value, 0.1f, 2f); value.r = Mathf.Clamp01(value.r * num); value.g = Mathf.Clamp01(value.g * num); value.b = Mathf.Clamp01(value.b * num); value.a = Mathf.Clamp01(value.a); return value; } } public static void SetStoreLargePanelOffset(Vector2 offset) { //IL_0005: 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) _storeLargePanelX.Value = Mathf.Clamp(offset.x, -2000f, 2000f); _storeLargePanelY.Value = Mathf.Clamp(offset.y, -2000f, 2000f); } public static void SetStoreFormPanelOffset(Vector2 offset) { //IL_0005: 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) _storeFormPanelX.Value = Mathf.Clamp(offset.x, -2000f, 2000f); _storeFormPanelY.Value = Mathf.Clamp(offset.y, -2000f, 2000f); } public static void SetStoreNotificationButtonOffset(Vector2 offset) { //IL_0005: 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) _storeNotificationButtonX.Value = Mathf.Clamp(offset.x, -3000f, 3000f); _storeNotificationButtonY.Value = Mathf.Clamp(offset.y, -3000f, 3000f); } public static bool IsStoreListModifierHeld() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return ConfigValueHelpers.IsShortcutHeld(StoreListModifierKey, allowUnbound: true); } public static bool IsStoreBackHotkeyDown() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return ConfigValueHelpers.IsShortcutDown(StoreBackHotkey); } public static bool AreaSaveAllowsCreator(long playerId, long creator) { if (creator == playerId) { return true; } return AreaSaveCreatorMode switch { BlueprintAreaSaveCreatorMode.AllCreators => true, BlueprintAreaSaveCreatorMode.OwnedAndCreatorless => creator == 0, _ => false, }; } public static bool ShouldApplyTerrainSupport(Player player) { return _terrainSupport.Value switch { BlueprintTerrainSupportMode.On => true, BlueprintTerrainSupportMode.AdminDebug => IsAdminDebugPlayer(player), _ => false, }; } public static void Bind(HomesteadPlugin plugin) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Expected O, but got Unknown //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Expected O, but got Unknown //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Expected O, but got Unknown //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Expected O, but got Unknown //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Expected O, but got Unknown //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Expected O, but got Unknown //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Expected O, but got Unknown //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Expected O, but got Unknown //IL_02ae: Unknown result type (might be due to invalid IL or missing references) //IL_02b9: Expected O, but got Unknown //IL_02dc: Unknown result type (might be due to invalid IL or missing references) //IL_02e7: Expected O, but got Unknown //IL_030a: Unknown result type (might be due to invalid IL or missing references) //IL_0315: Expected O, but got Unknown //IL_0343: Unknown result type (might be due to invalid IL or missing references) //IL_034e: Expected O, but got Unknown //IL_0391: Unknown result type (might be due to invalid IL or missing references) //IL_039c: Expected O, but got Unknown //IL_03df: Unknown result type (might be due to invalid IL or missing references) //IL_03ea: Expected O, but got Unknown //IL_0418: Unknown result type (might be due to invalid IL or missing references) //IL_0423: Expected O, but got Unknown //IL_0466: Unknown result type (might be due to invalid IL or missing references) //IL_0471: Expected O, but got Unknown //IL_04b4: Unknown result type (might be due to invalid IL or missing references) //IL_04bf: Expected O, but got Unknown //IL_0556: Unknown result type (might be due to invalid IL or missing references) //IL_0561: Expected O, but got Unknown //IL_05a4: Unknown result type (might be due to invalid IL or missing references) //IL_05af: Expected O, but got Unknown //IL_05c9: Unknown result type (might be due to invalid IL or missing references) //IL_05f3: Unknown result type (might be due to invalid IL or missing references) //IL_0627: Unknown result type (might be due to invalid IL or missing references) //IL_065b: Unknown result type (might be due to invalid IL or missing references) //IL_0699: Unknown result type (might be due to invalid IL or missing references) //IL_06a4: Expected O, but got Unknown //IL_06d2: Unknown result type (might be due to invalid IL or missing references) //IL_06dd: Expected O, but got Unknown //IL_070b: Unknown result type (might be due to invalid IL or missing references) //IL_0716: Expected O, but got Unknown //IL_0756: Unknown result type (might be due to invalid IL or missing references) //IL_0794: Unknown result type (might be due to invalid IL or missing references) //IL_079f: Expected O, but got Unknown //IL_07cd: Unknown result type (might be due to invalid IL or missing references) //IL_07d8: Expected O, but got Unknown //IL_0806: Unknown result type (might be due to invalid IL or missing references) //IL_0811: Expected O, but got Unknown //IL_0835: Unknown result type (might be due to invalid IL or missing references) //IL_0884: Unknown result type (might be due to invalid IL or missing references) //IL_08ae: Unknown result type (might be due to invalid IL or missing references) //IL_08e2: Unknown result type (might be due to invalid IL or missing references) //IL_0920: Unknown result type (might be due to invalid IL or missing references) //IL_092b: Expected O, but got Unknown _terrainSupport = plugin.config("03 - Blueprint", "Terrain Support", BlueprintTerrainSupportMode.Off, "Controls native blueprint terrain support. Off only places WearNTear. On restores saved terrain support contacts for everyone. AdminDebug restores terrain support only when the placing player is admin and has debug/no-cost build enabled."); _chestRows = plugin.config("03 - Blueprint", "Blueprint Chest Rows", 20, new ConfigDescription("Inventory rows for the Homestead blueprint chest. Width is always 8 columns.", (AcceptableValueBase)(object)new AcceptableValueRange(10, 40), Array.Empty())); _chestConfirmHotkey = plugin.config("03 - Blueprint", "Blueprint Chest Confirm Hotkey", new KeyboardShortcut((KeyCode)101, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Client-only hotkey for confirming a Homestead blueprint chest. The default is Alt+E.", synchronizedSetting: false); _azuCraftyBoxesPullMode = plugin.config("03 - Blueprint", "AzuCraftyBoxes Pull Mode", BlueprintAzuCraftyBoxesPullMode.ConfirmOnly, "If AzuCraftyBoxes is installed, pulls missing blueprint materials from nearby allowed containers. ConfirmOnly pulls when confirming the blueprint. OpenAndConfirm also pulls before opening the blueprint chest."); _terrainSupportContactTolerance = plugin.config("03 - Blueprint", "Blueprint Terrain Support Contact Tolerance", 0.5f, new ConfigDescription("How close terrain must be to the lowest WearNTear bottom at a 1m x/z cell to be saved as a blueprint terrain support contact.", (AcceptableValueBase)(object)new AcceptableValueRange(0.01f, 2f), Array.Empty())); _terrainSupportFeatherWidth = plugin.config("03 - Blueprint", "Blueprint Terrain Support Feather Width", 6f, new ConfigDescription("Meters around blueprint terrain support contact footprints that blend back to native terrain. Set to 0 to only change exact contact cells.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 64f), Array.Empty())); _maxUploadKb = plugin.config("03 - Blueprint", "Max Blueprint Upload KB", 2048, new ConfigDescription("Server-synced maximum uncompressed YAML size for a client blueprint upload. This is checked before YAML deserialization.", (AcceptableValueBase)(object)new AcceptableValueRange(64, 16384), Array.Empty())); _maxEntries = plugin.config("03 - Blueprint", "Max Blueprint Entries", 5000, new ConfigDescription("Server-synced maximum WearNTear entries accepted in one Homestead blueprint upload.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 20000), Array.Empty())); _maxPreviewEntries = plugin.config("03 - Blueprint", "Max Blueprint Preview Entries", 5000, new ConfigDescription("Server-synced maximum WearNTear entries returned in preview-only blueprint payloads.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 20000), Array.Empty())); _maxIconKb = plugin.config("04 - Blueprint Store", "Max Blueprint Store Icon KB", 256, new ConfigDescription("Server-synced maximum decoded PNG size accepted for blueprint store listing icons. Set to 0 to reject uploaded store icons.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 2048), Array.Empty())); _storeListingDays = plugin.config("04 - Blueprint Store", "Blueprint Store Listing Days", 0, new ConfigDescription("How many days a blueprint store listing stays visible from the time it is listed before the server can automatically hide it. Set to 0 to disable automatic delisting.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 365), Array.Empty())); _storeAutoDelistMaxPurchases = plugin.config("04 - Blueprint Store", "Blueprint Store Auto Delist Max Purchases", 0, new ConfigDescription("Only listings with this many purchases or fewer are automatically hidden after Blueprint Store Listing Days. Default 0 means only listings with no purchases are auto-delisted.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100000), Array.Empty())); _storeMaxListingsPerSteamId = plugin.config("04 - Blueprint Store", "Blueprint Store Max Listings Per SteamID", 10, new ConfigDescription("Server-synced maximum active blueprint store listings allowed for one SteamID/platform identity.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 200), Array.Empty())); _storeIdentityMode = plugin.config("04 - Blueprint Store", "Blueprint Store Identity Mode", BlueprintStoreIdentityMode.PlayerId, "Controls how Blueprint Store ownership and offer buyer permissions are matched. PlayerId treats each Valheim character separately. SteamId treats every character on the same Steam/platform account as the same store identity."); _chestTimeoutMinutes = plugin.config("03 - Blueprint", "Blueprint Chest Timeout Minutes", 30, new ConfigDescription("Minutes since last interaction before empty Homestead blueprint/build/store chests are removed. Set to 0 to disable automatic chest cleanup. A chest is kept while it has visible items, absorbed materials, price items, purchase deposits, or payout contents.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 60), Array.Empty())); _chestMapIconSize = plugin.config("03 - Blueprint", "Blueprint Chest Map Icon Size", 1, new ConfigDescription("Client-only icon size for your Homestead blueprint/build/store chests on the large map. Set to 0 to hide these map icons.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 10), Array.Empty()), synchronizedSetting: false); _maxActiveChestsPerPlayer = plugin.config("03 - Blueprint", "Max Active Blueprint Chests Per SteamID", 5, new ConfigDescription("Maximum active Homestead blueprint/build/store chests per Steam/platform identity. Set to 0 to disable this limit. If a platform identity cannot be resolved, Homestead falls back to the Valheim playerID.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 50), Array.Empty())); _storeLargePanelScale = plugin.config("04 - Blueprint Store", "Blueprint Store Large Panel Scale", 1.5f, new ConfigDescription("Client-only scale multiplier shared by the Blueprint Store listing and offers panels.", (AcceptableValueBase)(object)new AcceptableValueRange(0.75f, 2f), Array.Empty()), synchronizedSetting: false); _storeLargePanelX = plugin.config("04 - Blueprint Store", "Blueprint Store Large Panel X Offset", 0f, new ConfigDescription("Hidden client-only X offset from screen center for the Blueprint Store listing and offers panels. Use the in-game panel drag instead of editing this manually.", (AcceptableValueBase)(object)new AcceptableValueRange(-2000f, 2000f), new object[1] { new ConfigurationManagerAttributes { Browsable = false } }), synchronizedSetting: false); _storeLargePanelY = plugin.config("04 - Blueprint Store", "Blueprint Store Large Panel Y Offset", 0f, new ConfigDescription("Hidden client-only Y offset from screen center for the Blueprint Store listing and offers panels. Use the in-game panel drag instead of editing this manually.", (AcceptableValueBase)(object)new AcceptableValueRange(-2000f, 2000f), new object[1] { new ConfigurationManagerAttributes { Browsable = false } }), synchronizedSetting: false); _storeFormPanelScale = plugin.config("04 - Blueprint Store", "Blueprint Store Form Panel Scale", 1.5f, new ConfigDescription("Client-only scale multiplier shared by Blueprint Store offer, edit price, and price chest editor panels.", (AcceptableValueBase)(object)new AcceptableValueRange(0.75f, 2f), Array.Empty()), synchronizedSetting: false); _storeFormPanelX = plugin.config("04 - Blueprint Store", "Blueprint Store Form Panel X Offset", 0f, new ConfigDescription("Hidden client-only X offset from screen center for Blueprint Store form panels. Use the in-game panel drag instead of editing this manually.", (AcceptableValueBase)(object)new AcceptableValueRange(-2000f, 2000f), new object[1] { new ConfigurationManagerAttributes { Browsable = false } }), synchronizedSetting: false); _storeFormPanelY = plugin.config("04 - Blueprint Store", "Blueprint Store Form Panel Y Offset", 0f, new ConfigDescription("Hidden client-only Y offset from screen center for Blueprint Store form panels. Use the in-game panel drag instead of editing this manually.", (AcceptableValueBase)(object)new AcceptableValueRange(-2000f, 2000f), new object[1] { new ConfigurationManagerAttributes { Browsable = false } }), synchronizedSetting: false); _storeNotificationMode = plugin.config("04 - Blueprint Store", "Blueprint Store Notification Mode", BlueprintStoreNotificationMode.BadgeOnly, "Client-only display mode for Blueprint Store notifications. Off hides the notification button and disables fallback polling. BadgeOnly keeps the button and unread count visible without opening the panel automatically. AutoOpenPanel opens the notification panel when a new unread notification arrives.", synchronizedSetting: false); _storeAnonymousNotifications = plugin.config("04 - Blueprint Store", "Blueprint Store Anonymous Notifications", HomesteadPlugin.Toggle.Off, "Server-synced toggle for hiding player names in Blueprint Store notification messages. When on, notifications say Anonymous instead of the buyer, seller, or offer creator name."); _storeDebugLogging = plugin.config("04 - Blueprint Store", "Blueprint Store Debug Logging", HomesteadPlugin.Toggle.Off, "Client-only debug logging for Blueprint Store listing identity and button state. Enable when checking why a listing shows Edit/Buy/Offer/Hide for the current character.", synchronizedSetting: false); _storeNotificationButtonX = plugin.config("04 - Blueprint Store", "Blueprint Store Notification Button X Offset", -333f, new ConfigDescription("Hidden client-only default/current X offset for the floating Blueprint Store notification button from the top-right screen anchor. Dragging the in-game button also updates this value.", (AcceptableValueBase)(object)new AcceptableValueRange(-3000f, 3000f), new object[1] { new ConfigurationManagerAttributes { Browsable = false } }), synchronizedSetting: false); _storeNotificationButtonY = plugin.config("04 - Blueprint Store", "Blueprint Store Notification Button Y Offset", -55f, new ConfigDescription("Hidden client-only default/current Y offset for the floating Blueprint Store notification button from the top-right screen anchor. Dragging the in-game button also updates this value.", (AcceptableValueBase)(object)new AcceptableValueRange(-3000f, 3000f), new object[1] { new ConfigurationManagerAttributes { Browsable = false } }), synchronizedSetting: false); _storeListModifierKey = plugin.config("04 - Blueprint Store", "Blueprint Store List Modifier Key", new KeyboardShortcut((KeyCode)308, Array.Empty()), "Client-only modifier key held while left-clicking a blueprint in the Homestead build tab to place its Blueprint Store price chest. Set to None to use left-click without a modifier.", synchronizedSetting: false); _storeBackHotkey = plugin.config("04 - Blueprint Store", "Blueprint Store Back Hotkey", new KeyboardShortcut((KeyCode)326, Array.Empty()), "Client-only hotkey for returning from Blueprint Store sub-panels such as the offers view. Display uses the same Unity key names as Config Manager.", synchronizedSetting: false); _storeListingPreviewColor = plugin.config("04 - Blueprint Store", "Store Listing Pending Preview Color", new Color(1f, 0.9f, 0.2f, 0.15f), "Client-only color used for a blueprint preview after its store listing price chest has been placed but before the listing is confirmed. Alpha comes from this color's A value.", synchronizedSetting: false); _storePurchasePreviewColor = plugin.config("04 - Blueprint Store", "Store Purchase Pending Preview Color", new Color(1f, 0.54f, 0.12f, 0.15f), "Client-only color used for a blueprint preview after its purchase chest has been placed but before payment is confirmed. Alpha comes from this color's A value.", synchronizedSetting: false); _areaSaveMaxSide = plugin.config("03 - Blueprint", "Area Save Max Side Length", 64f, new ConfigDescription("Server-synced maximum side length in meters for the hammer Area Save blueprint rectangle.", (AcceptableValueBase)(object)new AcceptableValueRange(2f, 256f), Array.Empty())); _areaSaveDefaultWidth = plugin.config("03 - Blueprint", "Area Save Default Width", 8f, new ConfigDescription("Client-only default Area Save rectangle width. This is clamped by the server max side length.", (AcceptableValueBase)(object)new AcceptableValueRange(2f, 256f), Array.Empty()), synchronizedSetting: false); _areaSaveDefaultDepth = plugin.config("03 - Blueprint", "Area Save Default Depth", 8f, new ConfigDescription("Client-only default Area Save rectangle depth. Set a different value from width to start as a rectangle.", (AcceptableValueBase)(object)new AcceptableValueRange(2f, 256f), Array.Empty()), synchronizedSetting: false); _areaSaveCreatorMode = plugin.config("03 - Blueprint", "Area Save Creator Mode", BlueprintAreaSaveCreatorMode.OwnedAndCreatorless, "Controls which WearNTear objects the Area Save tool can select. AllCreators saves your own, creator=0, and other creators' WearNTear. OwnedAndCreatorless saves your own plus creator=0 WearNTear. OwnedOnly saves only WearNTear with your playerID."); _areaSaveBoundaryColor = plugin.config("03 - Blueprint", "Area Save Boundary Color", new Color(1f, 0.9f, 0.2f, 0.9f), "Client-only color for the Area Save rectangle line.", synchronizedSetting: false); _areaDismantleMaxSide = plugin.config("03 - Blueprint", "Area Dismantle Max Side Length", 8f, new ConfigDescription("Server-synced maximum side length in meters for the hammer Area Dismantle rectangle.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 128f), Array.Empty())); _areaDismantleDefaultWidth = plugin.config("03 - Blueprint", "Area Dismantle Default Width", 4f, new ConfigDescription("Client-only default Area Dismantle rectangle width. This is clamped by the server max side length.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 128f), Array.Empty()), synchronizedSetting: false); _areaDismantleDefaultDepth = plugin.config("03 - Blueprint", "Area Dismantle Default Depth", 4f, new ConfigDescription("Client-only default Area Dismantle rectangle depth. Set a different value from width to start as a rectangle.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 128f), Array.Empty()), synchronizedSetting: false); _areaDismantleBoundaryColor = plugin.config("03 - Blueprint", "Area Dismantle Boundary Color", new Color(1f, 0.3f, 0.12f, 0.9f), "Client-only color for the Area Dismantle rectangle line.", synchronizedSetting: false); _areaDismantlePrefabBlacklist = plugin.config("03 - Blueprint", "Area Dismantle Prefab Blacklist", "piece_stuward", "Comma-separated additional prefab names that Area Dismantle will never dismantle. Homestead blueprint/store chests are always protected internally."); PruneBuiltInAreaDismantleBlacklistEntries(); _areaToolDepthModifierKey = plugin.config("03 - Blueprint", "Area Tool Depth Modifier Key", new KeyboardShortcut((KeyCode)326, Array.Empty()), "Client-only modifier key held while using the mouse wheel to resize only the depth of Area Save and Area Dismantle rectangles. Set to None to disable depth-only wheel resizing.", synchronizedSetting: false); _areaToolWidthModifierKey = plugin.config("03 - Blueprint", "Area Tool Width Modifier Key", new KeyboardShortcut((KeyCode)327, Array.Empty()), "Client-only modifier key held while using the mouse wheel to resize only the width of Area Save and Area Dismantle rectangles. Set to None to disable width-only wheel resizing.", synchronizedSetting: false); _previewGhostColor = plugin.config("03 - Blueprint", "Preview Ghost Color", new Color(0.35f, 0.75f, 1f, 0.15f), "Client-only color for unfinished blueprint preview pieces.", synchronizedSetting: false); _previewGhostBrightness = plugin.config("03 - Blueprint", "Preview Ghost Brightness", 0.8f, new ConfigDescription("Client-only brightness multiplier for unfinished blueprint preview pieces.", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 2f), Array.Empty()), synchronizedSetting: false); } private static bool IsAdminDebugPlayer(Player player) { if ((Object)(object)player != (Object)null && player.NoCostCheat()) { return IsAdminPlayer(player); } return false; } private static bool IsAdminPlayer(Player player) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNet.instance == (Object)null || (Object)(object)player == (Object)null) { return false; } if ((Object)(object)player == (Object)(object)Player.m_localPlayer) { return ZNet.instance.LocalPlayerIsAdminOrHost(); } if (ZDOMan.instance == null) { return false; } long playerID = player.GetPlayerID(); if (playerID == 0L) { return false; } foreach (ZNetPeer peer in ZNet.instance.m_peers) { if (peer == null || !peer.IsReady() || ((ZDOID)(ref peer.m_characterID)).IsNone()) { continue; } ZDO zDO = ZDOMan.instance.GetZDO(peer.m_characterID); if (zDO != null && zDO.GetLong(ZDOVars.s_playerID, 0L) == playerID) { ZRpc rpc = peer.m_rpc; object obj; if (rpc == null) { obj = null; } else { ISocket socket = rpc.m_socket; obj = ((socket != null) ? socket.GetHostName() : null); } if (obj == null) { obj = ""; } string text = (string)obj; return text.Length > 0 && ZNet.instance.IsAdmin(text); } } return false; } private static void PruneBuiltInAreaDismantleBlacklistEntries() { List list = (from entry in (_areaDismantlePrefabBlacklist.Value ?? "").Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries) select entry.Trim() into entry where !string.IsNullOrWhiteSpace(entry) select entry).ToList(); List list2 = list.Where((string entry) => !BuiltInAreaDismantleProtectedPrefabs.Contains(entry)).Distinct(StringComparer.OrdinalIgnoreCase).ToList(); if (list2.Count != list.Count || !list2.SequenceEqual(list, StringComparer.OrdinalIgnoreCase)) { _areaDismantlePrefabBlacklist.Value = string.Join(",", list2); } } private static Color GetStorePendingPreviewColor(Color value, Color fallback) { //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_001e: 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_0046: 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_006a: Unknown result type (might be due to invalid IL or missing references) Color val = value; float num = Mathf.Clamp(_previewGhostBrightness.Value, 0.1f, 2f); val.r = Mathf.Clamp01(val.r * num); val.g = Mathf.Clamp01(val.g * num); val.b = Mathf.Clamp01(val.b * num); val.a = Mathf.Clamp01(val.a); return val; } } internal static class BuildCameraConfig { private static ConfigEntry _enabled; private static ConfigEntry _resourcePickupRange; private static ConfigEntry _distanceMode; private static ConfigEntry _maxDistanceFromAvatar; private static ConfigEntry _baseDistanceFromAvatar; private static ConfigEntry _distancePerComfortLevel; private static ConfigEntry _moveSpeedMultiplier; private static ConfigEntry _toggleHotkey; private static ConfigEntry _demisterFollowCamera; private static ConfigEntry _lookAtLockHotkey; private static ConfigEntry _restrictionMode; private static ConfigEntry _minimumComfortLevel; private static ConfigEntry _followDvergrCircletLight; private static ConfigEntry _helmetLightOffsetForward; private static ConfigEntry _helmetLightOffsetUp; public static bool Enabled => _enabled.Value.IsOn(); public static float ResourcePickupRange => Mathf.Clamp(_resourcePickupRange.Value, 0f, 100f); public static BuildCameraDistanceMode DistanceMode => _distanceMode.Value; public static float MaxDistanceFromAvatar => Mathf.Clamp(_maxDistanceFromAvatar.Value, 1f, 500f); public static float BaseDistanceFromAvatar => Mathf.Clamp(_baseDistanceFromAvatar.Value, 1f, 500f); public static float DistancePerComfortLevel => Mathf.Clamp(_distancePerComfortLevel.Value, 0f, 50f); public static float MoveSpeedMultiplier => Mathf.Clamp(_moveSpeedMultiplier.Value, 0.1f, 20f); public static KeyboardShortcut ToggleHotkey => _toggleHotkey.Value; public static bool DemisterFollowCamera => _demisterFollowCamera.Value.IsOn(); public static KeyboardShortcut LookAtLockHotkey => _lookAtLockHotkey.Value; public static BuildCameraRestrictionMode RestrictionMode => _restrictionMode.Value; public static int MinimumComfortLevel => Mathf.Clamp(_minimumComfortLevel.Value, 1, 30); public static bool FollowDvergrCircletLight => _followDvergrCircletLight.Value.IsOn(); public static float HelmetLightOffsetForward => Mathf.Clamp(_helmetLightOffsetForward.Value, -5f, 5f); public static float HelmetLightOffsetUp => Mathf.Clamp(_helmetLightOffsetUp.Value, -5f, 5f); public static void Bind(HomesteadPlugin plugin) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Expected O, but got Unknown //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Expected O, but got Unknown //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Expected O, but got Unknown //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Expected O, but got Unknown //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Expected O, but got Unknown //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Expected O, but got Unknown //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Expected O, but got Unknown _enabled = plugin.config("05 - Build Camera", "Enabled", HomesteadPlugin.Toggle.On, new ConfigDescription("If on, Homestead includes BuildCameraCHE-style free build camera mode. Disable this if the standalone BuildCameraCHE mod is installed.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 1000 } })); _resourcePickupRange = plugin.config("05 - Build Camera", "Resource Pickup Range", 10f, new ConfigDescription("Distance from which build camera mode can pick up resources on the ground. Valheim default is 2.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 100f), Array.Empty())); _distanceMode = plugin.config("05 - Build Camera", "Camera Distance Mode", BuildCameraDistanceMode.ComfortScaled, "Fixed: use Camera Distance(Max) In Fixed Mode. ComfortScaled: use Base Camera Distance From Avatar + current comfort level * Camera Distance Per Comfort Level."); _maxDistanceFromAvatar = plugin.config("05 - Build Camera", "Camera Distance(Max) In Fixed Mode", 32f, new ConfigDescription("Fixed build camera distance in meters when Camera Distance Mode is Fixed.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 500f), Array.Empty())); _baseDistanceFromAvatar = plugin.config("05 - Build Camera", "Base Camera Distance From Avatar", 32f, new ConfigDescription("Base distance in meters that the build camera can move away from your player avatar before comfort scaling is added.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 500f), Array.Empty())); _distancePerComfortLevel = plugin.config("05 - Build Camera", "Camera Distance Per Comfort Level", 2f, new ConfigDescription("Extra build camera distance in meters added for each current comfort level.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 50f), Array.Empty())); _moveSpeedMultiplier = plugin.config("05 - Build Camera", "Camera Move Speed Multiplier", 3f, new ConfigDescription("Multiplies build camera panning speed.", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 20f), Array.Empty())); _toggleHotkey = plugin.config("05 - Build Camera", "Toggle Build Camera Hotkey", new KeyboardShortcut((KeyCode)98, Array.Empty()), "Client-only hotkey that toggles build camera mode while a build tool is equipped.", synchronizedSetting: false); _demisterFollowCamera = plugin.config("05 - Build Camera", "Demister Follow Camera", HomesteadPlugin.Toggle.On, "If on, the Wisplight demister ball follows the build camera while build camera mode is active."); _lookAtLockHotkey = plugin.config("05 - Build Camera", "Look At Lock Hotkey", new KeyboardShortcut((KeyCode)113, Array.Empty()), "Client-only hotkey that toggles build camera look-at lock while build camera mode is active.", synchronizedSetting: false); _restrictionMode = plugin.config("05 - Build Camera", "Restriction Mode", BuildCameraRestrictionMode.Off, "Off: no cozy restriction. CameraNeedsCoziness: cozy required to enter and stay in build camera. CameraPickUpNeedsCoziness: camera entry is allowed, but camera item pickup requires cozy."); _minimumComfortLevel = plugin.config("05 - Build Camera", "Restriction Mode Minimum Comfort Level", 1, new ConfigDescription("Minimum comfort level required by the build camera comfort restriction.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 30), Array.Empty())); _followDvergrCircletLight = plugin.config("05 - Build Camera", "Dvergr Circlet Light Follow Camera", HomesteadPlugin.Toggle.On, "If on, Dvergr circlet light follows the build camera while build camera mode is active."); _helmetLightOffsetForward = plugin.config("05 - Build Camera", "Dvergr Circlet Light Forward Offset", 0.65f, new ConfigDescription("Client-only Dvergr circlet light offset along the build camera forward axis.", (AcceptableValueBase)(object)new AcceptableValueRange(-5f, 5f), Array.Empty()), synchronizedSetting: false); _helmetLightOffsetUp = plugin.config("05 - Build Camera", "Dvergr Circlet Light Up Offset", -0.08f, new ConfigDescription("Client-only Dvergr circlet light offset along the build camera up axis.", (AcceptableValueBase)(object)new AcceptableValueRange(-5f, 5f), Array.Empty()), synchronizedSetting: false); } } internal static class PlacementControlConfig { private static ConfigEntry _gridSnapToggleHotkey; private static ConfigEntry _gridSnapSize; private static ConfigEntry _placementAdjustEnabled; private static ConfigEntry _placementAdjustHeightStep; private static ConfigEntry _placementAdjustHorizontalStep; private static ConfigEntry _placementRotationStep; private static ConfigEntry _placementXAxisRotation; private static ConfigEntry _placementZAxisRotation; private static ConfigEntry _placementAdjustModifierKey; public static KeyboardShortcut GridSnapToggleHotkey => _gridSnapToggleHotkey.Value; public static float GridSnapSize => Mathf.Round(Mathf.Clamp(_gridSnapSize.Value, 0.05f, 1f) * 20f) / 20f; public static bool PlacementAdjustEnabled => _placementAdjustEnabled.Value.IsOn(); public static float HeightStep => Mathf.Clamp(_placementAdjustHeightStep.Value, 0.01f, 10f); public static float HorizontalStep => Mathf.Clamp(_placementAdjustHorizontalStep.Value, 0.01f, 10f); public static float RotationStep => Mathf.Clamp(_placementRotationStep.Value, 1f, 90f); public static float XAxisRotation => Mathf.Clamp(_placementXAxisRotation.Value, -180f, 180f); public static float ZAxisRotation => Mathf.Clamp(_placementZAxisRotation.Value, -180f, 180f); public static bool HasPlacementAxisRotation { get { if (!(Mathf.Abs(XAxisRotation) > 0.001f)) { return Mathf.Abs(ZAxisRotation) > 0.001f; } return true; } } public static KeyboardShortcut PlacementAdjustModifierKey => _placementAdjustModifierKey.Value; public static string PlacementAdjustModifierLabel => ConfigValueHelpers.FormatShortcut(PlacementAdjustModifierKey); public static string AreaUniformScaleInputLabel { get { //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_0008: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut placementAdjustModifierKey = PlacementAdjustModifierKey; if ((int)((KeyboardShortcut)(ref placementAdjustModifierKey)).MainKey != 0) { return PlacementAdjustModifierLabel + "+Wheel"; } return ""; } } public static bool IsAreaDepthModifierHeld() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return ConfigValueHelpers.IsShortcutHeld(BlueprintConfig.AreaToolDepthModifierKey, allowUnbound: false); } public static bool IsAreaWidthModifierHeld() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return ConfigValueHelpers.IsShortcutHeld(BlueprintConfig.AreaToolWidthModifierKey, allowUnbound: false); } public static bool IsAreaUniformScaleModifierHeld() { //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_0008: 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) KeyboardShortcut placementAdjustModifierKey = PlacementAdjustModifierKey; if ((int)((KeyboardShortcut)(ref placementAdjustModifierKey)).MainKey != 0) { return ConfigValueHelpers.IsShortcutHeld(PlacementAdjustModifierKey, allowUnbound: false); } return false; } public static bool IsPlacementAdjustModifierHeld() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return ConfigValueHelpers.IsShortcutHeld(PlacementAdjustModifierKey, allowUnbound: true); } public static void Bind(HomesteadPlugin plugin) { //IL_0012: 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_005b: Expected O, but got Unknown //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Expected O, but got Unknown //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Expected O, but got Unknown //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Expected O, but got Unknown //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Expected O, but got Unknown //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Expected O, but got Unknown //IL_01ae: Unknown result type (might be due to invalid IL or missing references) _gridSnapToggleHotkey = plugin.config("06 - Placement Controls", "Grid Snap Toggle Hotkey", new KeyboardShortcut((KeyCode)103, Array.Empty()), "Client-only hotkey that toggles grid snapping on or off while placing build pieces. The default is G.", synchronizedSetting: false); _gridSnapSize = plugin.config("06 - Placement Controls", "Grid Size", 0.5f, new ConfigDescription("Client-only grid spacing in meters. Values are clamped and rounded to 0.05m steps between 0.05 and 1.0.", (AcceptableValueBase)(object)new AcceptableValueRange(0.05f, 1f), Array.Empty()), synchronizedSetting: false); _placementAdjustEnabled = plugin.config("06 - Placement Controls", "Position Adjust", HomesteadPlugin.Toggle.On, "If on, hammer pieces, Homestead blueprints, and area tools can be nudged with PgUp/PgDn and arrow keys."); _placementAdjustHeightStep = plugin.config("06 - Placement Controls", "Position Height Step", 0.5f, new ConfigDescription("Client-only vertical offset step in meters for PgUp/PgDn while adjusting placement.", (AcceptableValueBase)(object)new AcceptableValueRange(0.01f, 10f), Array.Empty()), synchronizedSetting: false); _placementAdjustHorizontalStep = plugin.config("06 - Placement Controls", "Position Horizontal Step", 0.5f, new ConfigDescription("Client-only horizontal offset step in meters for arrow keys while adjusting placement.", (AcceptableValueBase)(object)new AcceptableValueRange(0.01f, 10f), Array.Empty()), synchronizedSetting: false); _placementRotationStep = plugin.config("06 - Placement Controls", "Rotation Step", 22.5f, new ConfigDescription("Client-only rotation step in degrees shared by Area Save, Area Dismantle, blueprint yaw rotation, and placement rotation controls.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 90f), Array.Empty()), synchronizedSetting: false); _placementXAxisRotation = plugin.config("06 - Placement Controls", "X Axis Rotation", 0f, new ConfigDescription("Client-only default X-axis rotation in degrees applied to ordinary hammer build piece previews and final placement. Terrain tools and Homestead area tools are ignored.", (AcceptableValueBase)(object)new AcceptableValueRange(-180f, 180f), Array.Empty()), synchronizedSetting: false); _placementZAxisRotation = plugin.config("06 - Placement Controls", "Z Axis Rotation", 0f, new ConfigDescription("Client-only default Z-axis rotation in degrees applied to ordinary hammer build piece previews and final placement. Terrain tools and Homestead area tools are ignored.", (AcceptableValueBase)(object)new AcceptableValueRange(-180f, 180f), Array.Empty()), synchronizedSetting: false); _placementAdjustModifierKey = plugin.config("06 - Placement Controls", "Position Adjust Modifier Key", new KeyboardShortcut((KeyCode)308, Array.Empty()), "Client-only modifier key held while using PgUp/PgDn and arrow keys for placement offsets. Set to None to allow the old unmodified keys.", synchronizedSetting: false); } } internal static class DvergrCircletConfig { public const float MaxDurability = 100f; public const float PerItemMinMultiplier = 1f; private static ConfigEntry _extensionEnabled; private static ConfigEntry _fuelMinutes; private static ConfigEntry _repairStation; private static ConfigEntry _perItemMaxIntensityMultiplier; private static ConfigEntry _perItemMaxRangeMultiplier; private static ConfigEntry _perItemAdjustmentStep; private static ConfigEntry _toggleLightHotkey; private static ConfigEntry _adjustmentModifierKey; private static ConfigEntry _remoteVisualSync; private static ConfigEntry _remoteLightMaxDistance; private static ConfigEntry _debugLogging; public static bool ExtensionEnabled => _extensionEnabled.Value.IsOn(); public static float FuelSeconds => Mathf.Max(1f, _fuelMinutes.Value) * 60f; public static string RepairStation { get { if (!string.IsNullOrWhiteSpace(_repairStation.Value)) { return _repairStation.Value.Trim(); } return "forge"; } } public static float PerItemMaxIntensityMultiplier => Mathf.Max(1f, Mathf.Clamp(_perItemMaxIntensityMultiplier.Value, 1f, 3f)); public static float PerItemMaxRangeMultiplier => Mathf.Max(1f, Mathf.Clamp(_perItemMaxRangeMultiplier.Value, 1f, 3f)); public static float PerItemAdjustmentStep => Mathf.Clamp(_perItemAdjustmentStep.Value, 0.05f, 1f); public static KeyboardShortcut ToggleLightHotkey => _toggleLightHotkey.Value; public static KeyboardShortcut AdjustmentModifierKey => _adjustmentModifierKey.Value; public static string AdjustmentModifierLabel => ConfigValueHelpers.FormatShortcut(AdjustmentModifierKey); public static bool RemoteVisualSync => _remoteVisualSync.Value.IsOn(); public static float RemoteLightMaxDistance => Mathf.Clamp(_remoteLightMaxDistance.Value, 0f, 200f); public static bool DebugLogging => _debugLogging.Value.IsOn(); public static void Bind(HomesteadPlugin plugin) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Expected O, but got Unknown //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Expected O, but got Unknown //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Expected O, but got Unknown //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Expected O, but got Unknown _extensionEnabled = plugin.config("08 - Dvergr Circlet", "Enabled", HomesteadPlugin.Toggle.On, new ConfigDescription("If on, Homestead gives the Dvergr circlet per-item configurable light range, light intensity, durability drain while lit, and custom repair station support. If Circlet Extended is installed, Homestead leaves circlet handling to that mod.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 1000 } })); _fuelMinutes = plugin.config("08 - Dvergr Circlet", "Base Fuel Minutes", 60f, new ConfigDescription("How many minutes a full Dvergr circlet lasts at 1.0 light intensity and 1.0 light range. Higher intensity and range drain proportionally faster.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 10000f), Array.Empty())); _repairStation = plugin.config("08 - Dvergr Circlet", "Repair Station", "forge", "Crafting station required to repair the Dvergr circlet. Use the prefab name like forge, workbench, blackforge, or the localized station token like $piece_forge."); _perItemMaxIntensityMultiplier = plugin.config("08 - Dvergr Circlet", "Maximum Intensity Multiplier", 3f, new ConfigDescription("Highest brightness multiplier a player can set on an individual Dvergr circlet with hotkeys.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 3f), Array.Empty())); _perItemMaxRangeMultiplier = plugin.config("08 - Dvergr Circlet", "Maximum Range Multiplier", 3f, new ConfigDescription("Highest range multiplier a player can set on an individual Dvergr circlet with hotkeys.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 3f), Array.Empty())); _perItemAdjustmentStep = plugin.config("08 - Dvergr Circlet", "Adjustment Step", 0.5f, new ConfigDescription("Brightness/range multiplier step used by Dvergr circlet hotkeys. 0.5 means 50% per key press.", (AcceptableValueBase)(object)new AcceptableValueRange(0.05f, 1f), Array.Empty())); _toggleLightHotkey = plugin.config("08 - Dvergr Circlet", "Toggle Light Hotkey", new KeyboardShortcut((KeyCode)108, Array.Empty()), "Client-only hotkey that toggles the equipped Dvergr circlet light on or off.", synchronizedSetting: false); _adjustmentModifierKey = plugin.config("08 - Dvergr Circlet", "Adjustment Modifier Key", new KeyboardShortcut((KeyCode)304, Array.Empty()), "Client-only modifier held while using fixed arrow keys to adjust the equipped Dvergr circlet. Up/Down changes brightness, Right/Left changes range. Set to None to use arrow keys without a modifier.", synchronizedSetting: false); _remoteVisualSync = plugin.config("08 - Dvergr Circlet", "Remote Visual Sync", HomesteadPlugin.Toggle.On, "If on, Homestead publishes Dvergr circlet custom-slot visual state through the player ZDO so other clients can see the circlet visual and light. Disable only if another mod owns circlet visuals."); _remoteLightMaxDistance = plugin.config("08 - Dvergr Circlet", "Remote Light Max Distance", 60f, new ConfigDescription("Client-only maximum distance in meters for rendering Homestead-synced remote Dvergr circlet lights. Set to 0 for no distance culling.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 200f), Array.Empty()), synchronizedSetting: false); _debugLogging = plugin.config("08 - Dvergr Circlet", "Debug Logging", HomesteadPlugin.Toggle.Off, "Client-only diagnostic logging for Dvergr circlet equip detection, AzuExtended custom slot detection, visual roots, remote sync, and fallback light state.", synchronizedSetting: false); } } internal static class AreaToolConfig { public static float BlueprintSaveMaxSide => BlueprintConfig.AreaSaveMaxSide; public static float BlueprintSaveDefaultWidth => BlueprintConfig.AreaSaveDefaultWidth; public static float BlueprintSaveDefaultDepth => BlueprintConfig.AreaSaveDefaultDepth; public static Color BlueprintSaveColor => BlueprintConfig.AreaSaveBoundaryColor; public static float DismantleMaxSide => BlueprintConfig.AreaDismantleMaxSide; public static float DismantleDefaultWidth => BlueprintConfig.AreaDismantleDefaultWidth; public static float DismantleDefaultDepth => BlueprintConfig.AreaDismantleDefaultDepth; public static Color DismantleColor => BlueprintConfig.AreaDismantleBoundaryColor; } internal static class ConfigValueHelpers { public static HashSet SplitPrefabList(string value) { return (from item in (value ?? "").Split(new char[4] { ',', ';', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries) select item.Trim() into item where item.Length > 0 select item).ToHashSet(StringComparer.OrdinalIgnoreCase); } public static bool IsShortcutHeld(KeyboardShortcut shortcut, bool allowUnbound) { //IL_0002: 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) if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0) { return allowUnbound; } if (IsModifierKeyHeld(((KeyboardShortcut)(ref shortcut)).MainKey)) { return ((KeyboardShortcut)(ref shortcut)).Modifiers.All(IsModifierKeyHeld); } return false; } public static bool IsShortcutDown(KeyboardShortcut shortcut) { //IL_0002: 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) if ((int)((KeyboardShortcut)(ref shortcut)).MainKey != 0 && ((KeyboardShortcut)(ref shortcut)).Modifiers.All(IsModifierKeyHeld)) { return IsKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey); } return false; } public static string FormatShortcut(KeyboardShortcut shortcut) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0) { return "None"; } List list = (from text in ((KeyboardShortcut)(ref shortcut)).Modifiers.Where((KeyCode key) => (int)key > 0).Select(FormatKeyCode) where !string.IsNullOrWhiteSpace(text) select text).ToList(); list.Add(FormatKeyCode(((KeyboardShortcut)(ref shortcut)).MainKey)); if (list.Count != 0) { return string.Join("+", list); } return "None"; } private static string FormatKeyCode(KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if ((int)key == 0) { return ""; } return ((object)(KeyCode)(ref key)).ToString().Replace("LeftControl", "Ctrl").Replace("RightControl", "Ctrl") .Replace("LeftShift", "Shift") .Replace("RightShift", "Shift") .Replace("LeftAlt", "Alt") .Replace("RightAlt", "Alt"); } private static bool IsModifierKeyHeld(KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: 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_0027: Expected I4, but got Unknown //IL_0027: 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_004f: Expected I4, but got Unknown //IL_00ee: Unknown result type (might be due to invalid IL or missing references) if ((int)key != 0) { switch (key - 303) { default: return (key - 323) switch { 0 => Input.GetMouseButton(0), 1 => Input.GetMouseButton(1), 2 => Input.GetMouseButton(2), 3 => Input.GetMouseButton(3), 4 => Input.GetMouseButton(4), 5 => Input.GetMouseButton(5), 6 => Input.GetMouseButton(6), _ => Input.GetKey(key), }; case 2: case 3: return Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305); case 0: case 1: return Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303); case 4: case 5: return Input.GetKey((KeyCode)308) || Input.GetKey((KeyCode)307); } } return false; } private static bool IsKeyDown(KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected I4, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) return (key - 323) switch { 0 => Input.GetMouseButtonDown(0), 1 => Input.GetMouseButtonDown(1), 2 => Input.GetMouseButtonDown(2), 3 => Input.GetMouseButtonDown(3), 4 => Input.GetMouseButtonDown(4), 5 => Input.GetMouseButtonDown(5), 6 => Input.GetMouseButtonDown(6), _ => Input.GetKeyDown(key), }; } } internal sealed class ConfigurationManagerAttributes { [UsedImplicitly] public int? Order; [UsedImplicitly] public bool? Browsable; [UsedImplicitly] public string? Category; [UsedImplicitly] public Action? CustomDrawer; } internal static class HomesteadFeatureBootstrap { private static Player? _lastLocalPlayer; public static void Initialize(ManualLogSource logger, Harmony harmony) { ZoneSessionResetRegistry.Initialize(logger); ZoneBlueprintCommands.Initialize(logger); ZoneBlueprintSaveTool.Initialize(logger); ZoneAreaDismantleTool.Initialize(logger); ZoneBlueprintPlacementTool.Initialize(logger); ZoneBlueprintChestVfx.Initialize(logger); ZoneBlueprintPlanChestPrefab.Initialize(logger); ZoneBlueprintChestZdoRegistry.Initialize(logger); ZoneBlueprintChestMapPins.Initialize(logger); ZoneBlueprintChestCommands.Initialize(logger); ZoneBlueprintStore.Initialize(logger); ZoneBuildCamera.Initialize(logger); ZoneGridSnap.Initialize(logger); ZonePlacementAdjust.Initialize(logger); ZoneDvergrCirclet.Initialize(logger); RegisterSessionResetters(); harmony.PatchAll(Assembly.GetExecutingAssembly()); AzuCraftyBoxesCompat.Initialize(logger, harmony); ZoneWorldEditTerrainCompat.Initialize(logger, harmony); } private static void RegisterSessionResetters() { ZoneSessionResetRegistry.Register("Blueprint menu", ZoneBlueprintSaveToolMenu.ResetForWorldSession); ZoneSessionResetRegistry.Register("Blueprint plan RPC", ZoneBlueprintPlanRpc.ResetForWorldSession); ZoneSessionResetRegistry.Register("Blueprint store", ZoneBlueprintStore.ResetForWorldSession); ZoneSessionResetRegistry.Register("ContentsWithin preview", ZoneContentsWithinBlueprintChestPreview.ResetForWorldSession); ZoneSessionResetRegistry.Register("Dvergr circlet", ZoneDvergrCirclet.ResetForWorldSession); } public static void Update() { ZoneBlueprintNetworkPayload.Update(); ZoneBlueprintChestZdoRegistry.Update(); ZoneBlueprintChestCommands.RegisterRpcs(); ZoneBlueprintChestVfx.Update(); ZoneAreaDismantleTool.RegisterRpcs(); ZoneBlueprintSaveToolMenu.Update(); ZoneBlueprintPlanRpc.Update(); ZoneBlueprintStore.Update(); ZoneBuildCamera.Update(); ZoneGridSnap.Update(); ZoneDvergrCirclet.Update(); AzuCraftyBoxesCompat.Update(); ZoneWorldEditTerrainCompat.Update(); } public static void Shutdown() { ZoneBuildCamera.Shutdown(); ZoneSessionResetRegistry.ResetForWorldSession("shutdown"); ZoneBlueprintChestMapPins.Shutdown(); ZoneBlueprintChestZdoRegistry.Shutdown(); ZoneBlueprintStoreDraftRepository.Flush(force: true); } public static void OnLocalPlayerSet() { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && !((Object)(object)localPlayer == (Object)(object)_lastLocalPlayer)) { _lastLocalPlayer = localPlayer; ZoneSessionResetRegistry.ResetForWorldSession("local player changed"); } } } internal static class HomesteadLocalization { private static bool _loaded; private static ManualLogSource? _logger; public static void Load(ManualLogSource logger) { _logger = logger; if (!_loaded) { _loaded = true; CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); AddEmbeddedYaml(localization, "English"); AddEmbeddedYaml(localization, "Korean"); AddExternalYamlFiles(localization); } } public static string Token(string key) { if (!key.StartsWith("$", StringComparison.Ordinal)) { return "$" + key; } return key; } public static string Text(string key) { string text = Token(key); if (Localization.instance == null) { return text; } return Localization.instance.Localize(text); } public static string Format(string key, params object[] args) { string text = Text(key); try { return string.Format(CultureInfo.InvariantCulture, text, args); } catch (FormatException) { return text; } } public static string MaybeLocalize(string value) { if (Localization.instance == null) { return value; } return Localization.instance.Localize(value); } private static void AddEmbeddedYaml(CustomLocalization localization, string language) { string resourceSuffix = ".translations." + language + ".yml"; Assembly executingAssembly = Assembly.GetExecutingAssembly(); string text = executingAssembly.GetManifestResourceNames().FirstOrDefault((string name) => name.EndsWith(resourceSuffix, StringComparison.Ordinal)); if (text == null) { ManualLogSource? logger = _logger; if (logger != null) { logger.LogWarning((object)("Homestead localization resource not found: translations/" + language + ".yml")); } return; } using Stream stream = executingAssembly.GetManifestResourceStream(text); if (stream == null) { ManualLogSource? logger2 = _logger; if (logger2 != null) { logger2.LogWarning((object)("Homestead localization resource could not be opened: " + text)); } return; } using StreamReader streamReader = new StreamReader(stream, Encoding.UTF8); localization.AddYamlFile(language, streamReader.ReadToEnd()); } private static void AddExternalYamlFiles(CustomLocalization localization) { string pluginPath = Paths.PluginPath; if (string.IsNullOrWhiteSpace(pluginPath) || !Directory.Exists(pluginPath)) { return; } HashSet hashSet = new HashSet(StringComparer.OrdinalIgnoreCase); foreach (string item in Directory.EnumerateFiles(pluginPath, "Homestead.*.yml", SearchOption.AllDirectories).Concat(Directory.EnumerateFiles(pluginPath, "Homestead.*.yaml", SearchOption.AllDirectories)).OrderBy((string path) => path, StringComparer.OrdinalIgnoreCase)) { if (!TryGetExternalLanguage(item, out string language)) { continue; } if (!hashSet.Add(language)) { ManualLogSource? logger = _logger; if (logger != null) { logger.LogWarning((object)("Duplicate external Homestead localization for language '" + language + "' skipped: " + item)); } continue; } try { localization.AddYamlFile(language, File.ReadAllText(item, Encoding.UTF8)); ManualLogSource? logger2 = _logger; if (logger2 != null) { logger2.LogInfo((object)("Loaded external Homestead localization '" + language + "' from " + item)); } } catch (Exception ex) { ManualLogSource? logger3 = _logger; if (logger3 != null) { logger3.LogWarning((object)("Failed to load external Homestead localization '" + item + "': " + ex.Message)); } } } } private static bool TryGetExternalLanguage(string file, out string language) { language = ""; string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file); string text = "Homestead."; if (!fileNameWithoutExtension.StartsWith(text, StringComparison.OrdinalIgnoreCase)) { return false; } language = fileNameWithoutExtension.Substring(text.Length).Trim(); return !string.IsNullOrWhiteSpace(language); } } internal static class HomesteadPlayerIdentity { public static string ResolvePlatformId(Player? player, long sender, long playerId) { if ((Object)(object)player != (Object)null) { return ResolveLocalPlatformId(playerId); } ZNet instance = ZNet.instance; ZNetPeer val = ((instance != null) ? instance.GetPeer(sender) : null); if (val != null) { return ResolvePeerPlatformId(val, playerId); } if ((Object)(object)Player.m_localPlayer != (Object)null && Player.m_localPlayer.GetPlayerID() == playerId) { return ResolveLocalPlatformId(playerId); } return FallbackPlatformId(playerId); } public static string ResolvePeerPlatformId(ZNetPeer peer, long playerId) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (peer == null) { return FallbackPlatformId(playerId); } ISocket socket = peer.m_socket; string text = ((socket != null) ? socket.GetHostName() : null) ?? ""; if (!string.IsNullOrWhiteSpace(text)) { return NormalizePlatformId(((int)ZNet.m_onlineBackend == 0) ? ("steam:" + text) : text); } return $"session:{peer.m_uid}"; } public static string ResolveLocalPlatformId(long playerId) { string value = ""; try { UserInfo localUser = UserInfo.GetLocalUser(); value = ((localUser != null) ? ((object)(PlatformUserID)(ref localUser.UserId)).ToString() : null) ?? ""; } catch { } value = NormalizePlatformId(value); if (!string.IsNullOrWhiteSpace(value)) { return value; } return FallbackPlatformId(playerId); } public static string FallbackPlatformId(long playerId) { if (playerId == 0L) { return ""; } return $"local:{playerId}"; } public static string NormalizePlatformId(string value) { string text = (value ?? "").Trim(); if (string.IsNullOrWhiteSpace(text)) { return ""; } if (text.StartsWith("Steam_", StringComparison.OrdinalIgnoreCase)) { return "steam:" + text.Substring("Steam_".Length); } if (text.StartsWith("steam:", StringComparison.OrdinalIgnoreCase)) { return "steam:" + text.Substring("steam:".Length).Trim(); } return text; } public static bool TryGetPeerActivity(ZNetPeer peer, out string platformId, out long playerId, out string name) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) platformId = ""; playerId = 0L; name = ""; if (peer == null || !peer.IsReady()) { return false; } platformId = ResolvePeerPlatformId(peer, 0L); playerId = TryReadPlayerId(peer.m_characterID); name = peer.m_playerName; return true; } private static long TryReadPlayerId(ZDOID characterId) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (((ZDOID)(ref characterId)).IsNone() || ZDOMan.instance == null) { return 0L; } ZDO zDO = ZDOMan.instance.GetZDO(characterId); if (zDO == null) { return 0L; } return zDO.GetLong(ZDOVars.s_playerID, 0L); } } internal sealed class SavedZdoData { private const string Prefix = "hs-zdo-v1:"; private const int Version = 1; public Dictionary Strings { get; private set; } = new Dictionary(); public Dictionary Floats { get; private set; } = new Dictionary(); public Dictionary Ints { get; private set; } = new Dictionary(); public Dictionary Bools { get; private set; } = new Dictionary(); public Dictionary Hashes { get; private set; } = new Dictionary(); public Dictionary Longs { get; private set; } = new Dictionary(); public Dictionary Vecs { get; private set; } = new Dictionary(); public Dictionary Quats { get; private set; } = new Dictionary(); public Dictionary ByteArrays { get; private set; } = new Dictionary(); public ZDOID OriginalId { get; set; } = ZDOID.None; public ZDOID TargetConnectionId { get; set; } = ZDOID.None; public int ConnectionHash { get; set; } public ConnectionType ConnectionType { get; set; } public bool Persistent { get; private set; } public bool Distant { get; private set; } public ObjectType ObjectType { get; private set; } public SavedZdoData() { }//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) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) public SavedZdoData(ZDO zdo) { //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) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) Load(zdo); } public SavedZdoData(string payload) { //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) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) Load(payload); } public string GetBase64(Dictionary _) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected I4, but got Unknown ZPackage package = new ZPackage(); package.Write(1); package.Write(Persistent); package.Write(Distant); package.Write((int)ObjectType); WriteDictionary(package, Strings, (Action)package.Write); WriteDictionary(package, Floats, (Action)package.Write); WriteDictionary(package, Ints, (Action)package.Write); WriteDictionary(package, Longs, (Action)package.Write); WriteDictionary(package, Vecs, (Action)package.Write); WriteDictionary(package, Quats, (Action)package.Write); WriteDictionary(package, ByteArrays, delegate(byte[] bytes) { package.Write(bytes ?? Array.Empty()); }); return "hs-zdo-v1:" + package.GetBase64(); } public void ApplyTo(ZDO zdo) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: 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) zdo.Persistent = Persistent; zdo.Distant = Distant; zdo.Type = ObjectType; foreach (KeyValuePair @string in Strings) { zdo.Set(@string.Key, @string.Value); } foreach (KeyValuePair @float in Floats) { zdo.Set(@float.Key, @float.Value); } foreach (KeyValuePair @int in Ints) { zdo.Set(@int.Key, @int.Value, false); } foreach (KeyValuePair @bool in Bools) { zdo.Set(@bool.Key, @bool.Value); } foreach (KeyValuePair hash in Hashes) { zdo.Set(hash.Key, hash.Value, false); } foreach (KeyValuePair @long in Longs) { zdo.Set(@long.Key, @long.Value); } foreach (KeyValuePair vec in Vecs) { zdo.Set(vec.Key, vec.Value); } foreach (KeyValuePair quat in Quats) { zdo.Set(quat.Key, quat.Value); } foreach (KeyValuePair byteArray in ByteArrays) { zdo.Set(byteArray.Key, byteArray.Value.ToArray()); } } private void Load(ZDO zdo) { //IL_0002: 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_0032: 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_00da: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) OriginalId = zdo.m_uid; Persistent = zdo.Persistent; Distant = zdo.Distant; ObjectType = zdo.Type; Strings = ZDOExtraData.GetStrings(zdo.m_uid).ToDictionary((KeyValuePair item) => item.Key, (KeyValuePair item) => item.Value); Floats = ZDOExtraData.GetFloats(zdo.m_uid).ToDictionary((KeyValuePair item) => item.Key, (KeyValuePair item) => item.Value); Ints = ZDOExtraData.GetInts(zdo.m_uid).ToDictionary((KeyValuePair item) => item.Key, (KeyValuePair item) => item.Value); Longs = ZDOExtraData.GetLongs(zdo.m_uid).ToDictionary((KeyValuePair item) => item.Key, (KeyValuePair item) => item.Value); Vecs = ZDOExtraData.GetVec3s(zdo.m_uid).ToDictionary((KeyValuePair item) => item.Key, (KeyValuePair item) => item.Value); Quats = ZDOExtraData.GetQuaternions(zdo.m_uid).ToDictionary((KeyValuePair item) => item.Key, (KeyValuePair item) => item.Value); ByteArrays = ZDOExtraData.GetByteArrays(zdo.m_uid).ToDictionary((KeyValuePair item) => item.Key, (KeyValuePair item) => item.Value.ToArray()); } private void Load(string payload) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown if (!payload.StartsWith("hs-zdo-v1:", StringComparison.Ordinal)) { throw new InvalidDataException("Unsupported Homestead ZDO data format. Re-save this blueprint with the current Homestead version."); } ZPackage package = new ZPackage(payload.Substring("hs-zdo-v1:".Length)); int num = package.ReadInt(); if (num != 1) { throw new InvalidDataException($"Unsupported Homestead ZDO data version {num}."); } Persistent = package.ReadBool(); Distant = package.ReadBool(); ObjectType = (ObjectType)(byte)package.ReadInt(); Strings = ReadDictionary(package, () => package.ReadString()); Floats = ReadDictionary(package, () => package.ReadSingle()); Ints = ReadDictionary(package, () => package.ReadInt()); Longs = ReadDictionary(package, () => package.ReadLong()); Vecs = ReadDictionary(package, () => package.ReadVector3()); Quats = ReadDictionary(package, () => package.ReadQuaternion()); ByteArrays = ReadDictionary(package, () => package.ReadByteArray().ToArray()); } private static void WriteDictionary(ZPackage package, Dictionary values, Action writeValue) { package.Write(values.Count); foreach (KeyValuePair item in values.OrderBy, int>((KeyValuePair item) => item.Key)) { package.Write(item.Key); writeValue(item.Value); } } private static Dictionary ReadDictionary(ZPackage package, Func readValue) { int num = package.ReadInt(); Dictionary dictionary = new Dictionary(num); for (int i = 0; i < num; i++) { int key = package.ReadInt(); dictionary[key] = readValue(); } return dictionary; } } internal static class SavedZdoHelper { public static ZDO? Init(GameObject prefab, Vector3 position, Quaternion rotation, Vector3? scale, SavedZdoData data, Dictionary _) { //IL_0022: 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_0062: 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) if (ZDOMan.instance == null || !Object.op_Implicit((Object)(object)prefab)) { return null; } int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)prefab).name); ZDO val = ZDOMan.instance.CreateNewZDO(position, stableHashCode); val.SetPrefab(stableHashCode); val.SetRotation(rotation); ZNetView component = prefab.GetComponent(); if ((Object)(object)component != (Object)null) { val.Persistent = component.m_persistent; val.Distant = component.m_distant; val.Type = component.m_type; } data.ApplyTo(val); if (scale.HasValue) { val.Set(ZDOVars.s_scaleHash, scale.Value); } return val; } public static void Destroy(ZDO zdo) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: 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_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) if (zdo == null || ZDOMan.instance == null) { return; } ZDOID uid = zdo.m_uid; if (!CanDestroyZdo(uid)) { return; } zdo.SetOwner(ZDOMan.GetSessionID()); ZDOID connectionZDOID = zdo.GetConnectionZDOID((ConnectionType)3); if (connectionZDOID != ZDOID.None && ZDOMan.instance.m_objectsByID.TryGetValue(connectionZDOID, out var value) && value != zdo) { Destroy(value); } ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance != (Object)null) { ZNetView val = instance.FindInstance(zdo); if ((Object)(object)val != (Object)null) { instance.Destroy(((Component)val).gameObject); } } ZDO zDO = ZDOMan.instance.GetZDO(uid); if (zDO != null && zDO.IsValid()) { zDO.SetOwner(ZDOMan.GetSessionID()); ZDOMan.instance.DestroyZDO(zDO); ZDOMan.instance.HandleDestroyedZDO(uid); } } public static void FlushDestroyed() { ZDOMan instance = ZDOMan.instance; if (instance != null) { instance.SendDestroyed(); } } private static bool CanDestroyZdo(ZDOID id) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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 ((Object)(object)Player.m_localPlayer != (Object)null && ((Character)Player.m_localPlayer).GetZDOID() == id) { return false; } if (!((Object)(object)ZNet.instance == (Object)null)) { return !ZNet.instance.m_peers.Any((ZNetPeer peer) => peer != null && peer.m_characterID == id); } return true; } } internal static class HomesteadTerrainSupport { private readonly struct TerrainSupportCell { public int X { get; } public int Z { get; } public float Height { get; } public TerrainSupportCell(int x, int z, float height) { X = x; Z = z; Height = height; } } private sealed class TerrainSupportCellIndex { private readonly Dictionary> _cellsByBucket = new Dictionary>(); private readonly float _bucketSize; private readonly int _searchRadius; public TerrainSupportCellIndex(IEnumerable cells, float featherWidth) { _bucketSize = Mathf.Max(1f, featherWidth); _searchRadius = Mathf.Max(0, Mathf.CeilToInt(featherWidth / _bucketSize)); foreach (TerrainSupportCell cell in cells) { long key = PackCell(ToBucket(cell.X), ToBucket(cell.Z)); if (!_cellsByBucket.TryGetValue(key, out List value)) { value = new List(); _cellsByBucket[key] = value; } value.Add(cell); } } public bool TryGetNearest(Vector3 node, float maxDistanceSqr, out TerrainSupportCell nearest, out float bestDistanceSqr) { //IL_001f: 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_007e: 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) nearest = default(TerrainSupportCell); bestDistanceSqr = float.PositiveInfinity; if (_cellsByBucket.Count == 0) { return false; } int num = ToBucket(node.x); int num2 = ToBucket(node.z); for (int i = num2 - _searchRadius; i <= num2 + _searchRadius; i++) { for (int j = num - _searchRadius; j <= num + _searchRadius; j++) { if (!_cellsByBucket.TryGetValue(PackCell(j, i), out List value)) { continue; } foreach (TerrainSupportCell item in value) { float num3 = node.x - (float)item.X; float num4 = node.z - (float)item.Z; float num5 = num3 * num3 + num4 * num4; if (!(num5 >= bestDistanceSqr) && !(num5 > maxDistanceSqr)) { bestDistanceSqr = num5; nearest = item; } } } } return !float.IsPositiveInfinity(bestDistanceSqr); } private int ToBucket(float value) { return Mathf.FloorToInt(value / _bucketSize); } } [CompilerGenerated] private sealed class <>c__DisplayClass7_0 { public bool zoneChanged; internal void b__3(bool result) { zoneChanged = result; } } [CompilerGenerated] private sealed class d__12 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Heightmap heightmap; public List supportCells; public Dictionary supportHeights; public Action onComplete; private int 5__2; private float[] 5__3; private Color[] 5__4; private float 5__5; private TerrainSupportCellIndex 5__6; private bool 5__7; private int 5__8; private int 5__9; private int 5__10; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__12(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__3 = null; 5__4 = null; 5__6 = null; <>1__state = -2; } private bool MoveNext() { //IL_00cc: 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_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; goto IL_01d7; } <>1__state = -1; 5__2 = heightmap.m_width + 1; 5__3 = new float[5__2 * 5__2]; 5__4 = (Color[])(object)new Color[5__2 * 5__2]; 5__5 = BlueprintConfig.TerrainSupportFeatherWidth; 5__6 = new TerrainSupportCellIndex(supportCells, 5__5); 5__7 = false; 5__8 = 0; 5__9 = 0; goto IL_020c; IL_020c: if (5__9 < 5__2) { 5__10 = 0; goto IL_01e9; } if (!5__7) { onComplete(obj: false); return false; } PersistSupportFillBaseLayer(heightmap.GetAndCreateTerrainCompiler(), 5__2, 5__3, 5__4); heightmap.Poke(false); ClutterSystem instance = ClutterSystem.instance; if (instance != null) { instance.ResetGrass(((Component)heightmap).transform.position, 48f); } onComplete(obj: true); return false; IL_01d7: 5__10++; goto IL_01e9; IL_01e9: if (5__10 < 5__2) { int num2 = 5__9 * 5__2 + 5__10; Vector3 val = VertexToWorld(heightmap, 5__10, 5__9); float worldHeight = GetWorldHeight(heightmap, 5__10, 5__9); float height; float num3 = (TryGetTerrainBaseHeight(val.x, val.z, out height) ? height : worldHeight); float num4 = num3; 5__4[num2] = GetPaint(heightmap, 5__10, 5__9); float height2; if (supportHeights.TryGetValue(PackCell(Mathf.RoundToInt(val.x), Mathf.RoundToInt(val.z)), out var value)) { num4 = value; } else if (TryGetFeatheredSupportHeight(val, num3, 5__6, 5__5, out height2)) { num4 = height2; } 5__3[num2] = num4; if (Mathf.Abs(worldHeight - num4) > 0.01f) { 5__7 = true; } 5__8++; if (5__8 >= 1024) { 5__8 = 0; <>2__current = null; <>1__state = 1; return true; } goto IL_01d7; } 5__9++; goto IL_020c; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__7 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public IEnumerable supportContacts; public Action onComplete; private <>c__DisplayClass7_0 <>8__1; private List 5__2; private Dictionary 5__3; private bool 5__4; private List.Enumerator <>7__wrap4; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__7(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 1) <= 1u) { try { } finally { <>m__Finally1(); } } <>8__1 = null; 5__2 = null; 5__3 = null; <>7__wrap4 = default(List.Enumerator); <>1__state = -2; } private bool MoveNext() { //IL_0102: Unknown result type (might be due to invalid IL or missing references) bool result2; try { switch (<>1__state) { default: result2 = false; goto end_IL_0000; case 0: <>1__state = -1; 5__2 = BuildSupportCells(supportContacts); if (5__2.Count != 0) { 5__3 = 5__2.ToDictionary((TerrainSupportCell cell) => PackCell(cell.X, cell.Z), (TerrainSupportCell cell) => cell.Height); List list = 5__2.Select((TerrainSupportCell cell) => ZoneSystem.GetZone(new Vector3((float)cell.X, 0f, (float)cell.Z))).Distinct().ToList(); 5__4 = false; <>7__wrap4 = list.GetEnumerator(); <>1__state = -3; break; } onComplete(obj: false); result2 = false; goto end_IL_0000; case 1: <>1__state = -3; 5__4 |= <>8__1.zoneChanged; <>2__current = null; <>1__state = 2; result2 = true; goto end_IL_0000; case 2: <>1__state = -3; <>8__1 = null; break; } if (<>7__wrap4.MoveNext()) { Vector2i current = <>7__wrap4.Current; <>8__1 = new <>c__DisplayClass7_0(); if (!TryGetHeightmap(current, out Heightmap heightmap)) { onComplete(obj: false); result2 = false; <>m__Finally1(); } else { <>8__1.zoneChanged = false; <>2__current = ApplySupportCellsToHeightmapAsync(heightmap, 5__3, 5__2, delegate(bool result) { <>8__1.zoneChanged = result; }); <>1__state = 1; result2 = true; } } else { <>m__Finally1(); <>7__wrap4 = default(List.Enumerator); onComplete(5__4); result2 = false; } end_IL_0000:; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result2; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>7__wrap4).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__37 : IEnumerable, IEnumerable, IEnumerator, IDisposable, IEnumerator { private int <>1__state; private Vector3 <>2__current; private int <>l__initialThreadId; private Bounds bounds; public Bounds <>3__bounds; private Vector3 5__2; private Vector3 5__3; Vector3 IEnumerator.Current { [DebuggerHidden] get { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return <>2__current; } } [DebuggerHidden] public d__37(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_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_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: 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) switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__2 = ((Bounds)(ref bounds)).min; 5__3 = ((Bounds)(ref bounds)).max; <>2__current = new Vector3(5__2.x, 5__2.y, 5__2.z); <>1__state = 1; return true; case 1: <>1__state = -1; <>2__current = new Vector3(5__2.x, 5__2.y, 5__3.z); <>1__state = 2; return true; case 2: <>1__state = -1; <>2__current = new Vector3(5__2.x, 5__3.y, 5__2.z); <>1__state = 3; return true; case 3: <>1__state = -1; <>2__current = new Vector3(5__2.x, 5__3.y, 5__3.z); <>1__state = 4; return true; case 4: <>1__state = -1; <>2__current = new Vector3(5__3.x, 5__2.y, 5__2.z); <>1__state = 5; return true; case 5: <>1__state = -1; <>2__current = new Vector3(5__3.x, 5__2.y, 5__3.z); <>1__state = 6; return true; case 6: <>1__state = -1; <>2__current = new Vector3(5__3.x, 5__3.y, 5__2.z); <>1__state = 7; return true; case 7: <>1__state = -1; <>2__current = new Vector3(5__3.x, 5__3.y, 5__3.z); <>1__state = 8; return true; case 8: <>1__state = -1; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { //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) d__37 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__37(0); } d__.bounds = <>3__bounds; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } private const float SearchRadius = 48f; private const float SupportFillClearance = 0.05f; private const int TerrainApplyNodeBatchSize = 1024; private static readonly int SupportFillBaseLayerHash = StringExtensionMethods.GetStableHashCode("sighsorry.Homestead.terrain_base_v1"); public static bool TryGetWearNTearBounds(GameObject prefab, Vector3 position, Quaternion rotation, Vector3 scale, out Bounds bounds) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) return TryGetWearNTearWorldBounds(prefab, position, rotation, scale, out bounds); } public static bool TryGetTerrainHeight(float x, float z, out float height) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) return Heightmap.GetHeight(new Vector3(x, 0f, z), ref height); } public static bool ApplyWorldSupportContacts(IEnumerable supportContacts) { //IL_0091: 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_0098: 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_00b4: Unknown result type (might be due to invalid IL or missing references) List list = BuildSupportCells(supportContacts); if (list.Count == 0) { return false; } Dictionary supportHeights = list.ToDictionary((TerrainSupportCell cell) => PackCell(cell.X, cell.Z), (TerrainSupportCell cell) => cell.Height); List list2 = list.Select((TerrainSupportCell cell) => ZoneSystem.GetZone(new Vector3((float)cell.X, 0f, (float)cell.Z))).Distinct().ToList(); bool flag = false; foreach (Vector2i item in list2) { if (!TryGetHeightmap(item, out Heightmap heightmap)) { throw new InvalidOperationException($"Target terrain zone ({item.x},{item.y}) is not loaded for blueprint support placement."); } flag |= ApplySupportCellsToHeightmap(heightmap, supportHeights, list); } return flag; } [IteratorStateMachine(typeof(d__7))] public static IEnumerator ApplyWorldSupportContactsAsync(IEnumerable supportContacts, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__7(0) { supportContacts = supportContacts, onComplete = onComplete }; } public static void ApplyBaseLayer(Heightmap heightmap) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) TerrainComp val = TerrainComp.FindTerrainCompiler(((Component)heightmap).transform.position); if (!IsCompilerReady(val)) { return; } byte[] byteArray = val.m_nview.GetZDO().GetByteArray(SupportFillBaseLayerHash, (byte[])null); if (byteArray == null || byteArray.Length == 0 || !TryDeserializeBaseLayer(byteArray, heightmap, out int width, out float[] worldHeights, out Color[] paints) || width != heightmap.m_width + 1 || worldHeights.Length != heightmap.m_heights.Count || (paints.Length != 0 && paints.Length != worldHeights.Length)) { return; } float y = ((Component)heightmap).transform.position.y; for (int i = 0; i < worldHeights.Length; i++) { heightmap.m_heights[i] = worldHeights[i] - y; } if (paints.Length != worldHeights.Length) { return; } for (int j = 0; j < width; j++) { for (int k = 0; k < width; k++) { heightmap.m_paintMask.SetPixel(k, j, paints[j * width + k]); } } } internal static void ResetSupportFillBaseLayer(IEnumerable? heightNodes, IEnumerable? paintNodes, Vector3 position, float radius) { //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) Dictionary> dictionary = CollectTerrainNodeIndices(heightNodes); Dictionary> dictionary2 = CollectTerrainNodeIndices(paintNodes); if (dictionary.Count == 0 && dictionary2.Count == 0) { return; } HashSet hashSet = dictionary.Keys.Concat(dictionary2.Keys).ToHashSet(); int num = 0; foreach (TerrainComp item in hashSet) { if (!TryLoadSupportFillBaseLayer(item, out int width, out float[] worldHeights, out Color[] paints)) { continue; } bool flag = false; if (dictionary.TryGetValue(item, out var value)) { foreach (int item2 in value) { if (IsValidPayloadIndex(item2, width, worldHeights.Length)) { IndexToXZ(item2, width, out var x, out var z); Vector3 val = VertexToWorld(item.m_hmap, x, z); if (TryGetTerrainBaseHeight(val.x, val.z, out var height) && Mathf.Abs(worldHeights[item2] - height) > 0.01f) { worldHeights[item2] = height; flag = true; } } } } bool num2 = paints.Length == width * width; Color[] array = (num2 ? TryGetBasePaints(item.m_hmap, width) : null); if (num2 && array != null && dictionary2.TryGetValue(item, out var value2)) { foreach (int item3 in value2) { if (IsValidPayloadIndex(item3, width, paints.Length) && item3 < array.Length) { Color val2 = array[item3]; if (!Approximately(paints[item3], val2)) { paints[item3] = val2; flag = true; } } } } if (flag) { if (IsSupportFillBaseLayerNative(item.m_hmap, width, worldHeights, paints, array)) { item.m_nview.GetZDO().Set(SupportFillBaseLayerHash, Array.Empty()); } else { item.m_nview.GetZDO().Set(SupportFillBaseLayerHash, SerializeBaseLayer(item.m_hmap, width, worldHeights, paints)); } PersistCompiler(item); num++; } } if (num > 0) { ClutterSystem instance = ClutterSystem.instance; if (instance != null) { instance.ResetGrass(position, radius); } } } private static List BuildSupportCells(IEnumerable supportContacts) { return (from contact in supportContacts select new TerrainSupportCell(Mathf.RoundToInt(contact.x), Mathf.RoundToInt(contact.z), contact.y - 0.05f) into cell group cell by PackCell(cell.X, cell.Z) into @group select @group.OrderBy((TerrainSupportCell cell) => cell.Height).First()).ToList(); } private static bool ApplySupportCellsToHeightmap(Heightmap heightmap, Dictionary supportHeights, List supportCells) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) int num = heightmap.m_width + 1; float[] array = new float[num * num]; Color[] array2 = (Color[])(object)new Color[num * num]; float terrainSupportFeatherWidth = BlueprintConfig.TerrainSupportFeatherWidth; TerrainSupportCellIndex supportIndex = new TerrainSupportCellIndex(supportCells, terrainSupportFeatherWidth); bool flag = false; for (int i = 0; i < num; i++) { for (int j = 0; j < num; j++) { int num2 = i * num + j; Vector3 val = VertexToWorld(heightmap, j, i); float worldHeight = GetWorldHeight(heightmap, j, i); float height; float num3 = (TryGetTerrainBaseHeight(val.x, val.z, out height) ? height : worldHeight); float num4 = num3; array2[num2] = GetPaint(heightmap, j, i); float height2; if (supportHeights.TryGetValue(PackCell(Mathf.RoundToInt(val.x), Mathf.RoundToInt(val.z)), out var value)) { num4 = value; } else if (TryGetFeatheredSupportHeight(val, num3, supportIndex, terrainSupportFeatherWidth, out height2)) { num4 = height2; } array[num2] = num4; if (Mathf.Abs(worldHeight - num4) > 0.01f) { flag = true; } } } if (!flag) { return false; } PersistSupportFillBaseLayer(heightmap.GetAndCreateTerrainCompiler(), num, array, array2); heightmap.Poke(false); ClutterSystem instance = ClutterSystem.instance; if (instance != null) { instance.ResetGrass(((Component)heightmap).transform.position, 48f); } return true; } [IteratorStateMachine(typeof(d__12))] private static IEnumerator ApplySupportCellsToHeightmapAsync(Heightmap heightmap, Dictionary supportHeights, List supportCells, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__12(0) { heightmap = heightmap, supportHeights = supportHeights, supportCells = supportCells, onComplete = onComplete }; } private static bool TryGetFeatheredSupportHeight(Vector3 node, float baseHeight, TerrainSupportCellIndex supportIndex, float featherWidth, out float height) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) height = baseHeight; if (featherWidth <= 0f) { return false; } float maxDistanceSqr = featherWidth * featherWidth; if (!supportIndex.TryGetNearest(node, maxDistanceSqr, out var nearest, out var bestDistanceSqr)) { return false; } float num = Mathf.Sqrt(bestDistanceSqr); float num2 = 1f - Mathf.Clamp01(num / featherWidth); num2 = num2 * num2 * (3f - 2f * num2); height = Mathf.Lerp(baseHeight, nearest.Height, num2); return true; } private static bool TryLoadSupportFillBaseLayer(TerrainComp compiler, out int width, out float[] worldHeights, out Color[] paints) { width = 0; worldHeights = Array.Empty(); paints = Array.Empty(); if (!IsCompilerReady(compiler)) { return false; } byte[] byteArray = compiler.m_nview.GetZDO().GetByteArray(SupportFillBaseLayerHash, (byte[])null); if (byteArray != null && byteArray.Length != 0 && TryDeserializeBaseLayer(byteArray, compiler.m_hmap, out width, out worldHeights, out paints) && width == compiler.m_hmap.m_width + 1 && worldHeights.Length == width * width) { if (paints.Length != 0) { return paints.Length == worldHeights.Length; } return true; } return false; } private static Dictionary> CollectTerrainNodeIndices(IEnumerable? nodes) { Dictionary> dictionary = new Dictionary>(); if (nodes == null) { return dictionary; } foreach (object node in nodes) { if (TryReadTerrainNode(node, out TerrainComp compiler, out int index)) { if (!dictionary.TryGetValue(compiler, out var value)) { value = (dictionary[compiler] = new HashSet()); } value.Add(index); } } return dictionary; } private static bool TryReadTerrainNode(object? node, out TerrainComp compiler, out int index) { compiler = null; index = -1; if (node == null) { return false; } Type type = node.GetType(); FieldInfo fieldInfo = AccessTools.Field(type, "Compiler"); FieldInfo fieldInfo2 = AccessTools.Field(type, "Index"); object? obj = fieldInfo?.GetValue(node); TerrainComp val = (TerrainComp)((obj is TerrainComp) ? obj : null); object obj2 = fieldInfo2?.GetValue(node); if ((Object)(object)val == (Object)null || !(obj2 is int num)) { return false; } compiler = val; index = num; return true; } private static byte[] SerializeBaseLayer(Heightmap heightmap, int width, float[] worldHeights, Color[] paints) { Color[] paints2 = (ShouldSerializePaints(heightmap, width, paints) ? paints : Array.Empty()); return SerializeSparseBaseLayer(heightmap, width, worldHeights, paints2); } private static byte[] SerializeSparseBaseLayer(Heightmap heightmap, int width, float[] worldHeights, Color[] paints) { //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_0029: 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_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Expected O, but got Unknown //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) List list = new List(); List list2 = new List(); for (int i = 0; i < worldHeights.Length; i++) { IndexToXZ(i, width, out var x, out var z); Vector3 val = VertexToWorld(heightmap, x, z); float height; float num = (TryGetTerrainBaseHeight(val.x, val.z, out height) ? height : GetWorldHeight(heightmap, x, z)); if (!(Mathf.Abs(worldHeights[i] - num) <= 0.01f)) { list.Add(i); list2.Add(worldHeights[i]); } } List list3 = new List(); List list4 = new List(); if (paints.Length == worldHeights.Length) { Color[] array = TryGetBasePaints(heightmap, width); for (int j = 0; j < paints.Length; j++) { Color b = ((array != null && array.Length == paints.Length) ? array[j] : GetPaint(heightmap, j % width, j / width)); if (!Approximately(paints[j], b)) { list3.Add(j); list4.Add(paints[j]); } } } ZPackage val2 = new ZPackage(); val2.Write(3); val2.Write(width); val2.Write(worldHeights.Length); val2.Write(list.Count); for (int k = 0; k < list.Count; k++) { val2.Write(list[k]); val2.Write(list2[k]); } val2.Write(list3.Count); for (int l = 0; l < list3.Count; l++) { val2.Write(list3[l]); WriteColor(val2, list4[l]); } return Utils.Compress(val2.GetArray()); } private static bool TryDeserializeBaseLayer(byte[] payload, Heightmap heightmap, out int width, out float[] worldHeights, out Color[] paints) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown width = 0; worldHeights = Array.Empty(); paints = Array.Empty(); try { ZPackage val = new ZPackage(Utils.Decompress(payload)); if (val.ReadInt() != 3) { return false; } width = val.ReadInt(); int heightCount = val.ReadInt(); return TryDeserializeSparseBaseLayer(val, heightmap, width, heightCount, out worldHeights, out paints); } catch { return false; } } private static bool TryDeserializeSparseBaseLayer(ZPackage package, Heightmap heightmap, int width, int heightCount, out float[] worldHeights, out Color[] paints) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) worldHeights = new float[heightCount]; paints = Array.Empty(); if ((Object)(object)heightmap == (Object)null || width <= 0 || width != heightmap.m_width + 1 || heightCount != width * width) { return false; } for (int i = 0; i < worldHeights.Length; i++) { IndexToXZ(i, width, out var x, out var z); Vector3 val = VertexToWorld(heightmap, x, z); worldHeights[i] = (TryGetTerrainBaseHeight(val.x, val.z, out var height) ? height : GetWorldHeight(heightmap, x, z)); } int num = package.ReadInt(); for (int j = 0; j < num; j++) { int num2 = package.ReadInt(); float num3 = package.ReadSingle(); if (num2 < 0 || num2 >= worldHeights.Length) { return false; } worldHeights[num2] = num3; } int num4 = package.ReadInt(); if (num4 <= 0) { return true; } paints = TryGetBasePaints(heightmap, width) ?? BuildCurrentPaintLayer(heightmap, width); if (paints.Length != worldHeights.Length) { return false; } for (int k = 0; k < num4; k++) { int num5 = package.ReadInt(); Color val2 = ReadColor(package); if (num5 < 0 || num5 >= paints.Length) { return false; } paints[num5] = val2; } return true; } private static void PersistSupportFillBaseLayer(TerrainComp compiler, int width, float[] worldHeights, Color[] paints) { if (!IsCompilerReady(compiler)) { throw new InvalidOperationException("Target terrain compiler is not network ready."); } if (!compiler.m_nview.IsOwner()) { compiler.m_nview.ClaimOwnership(); } Array.Clear(compiler.m_modifiedHeight, 0, compiler.m_modifiedHeight.Length); Array.Clear(compiler.m_levelDelta, 0, compiler.m_levelDelta.Length); Array.Clear(compiler.m_smoothDelta, 0, compiler.m_smoothDelta.Length); Array.Clear(compiler.m_modifiedPaint, 0, compiler.m_modifiedPaint.Length); Array.Clear(compiler.m_paintMask, 0, compiler.m_paintMask.Length); compiler.m_nview.GetZDO().Set(SupportFillBaseLayerHash, SerializeBaseLayer(compiler.m_hmap, width, worldHeights, paints)); PersistCompiler(compiler); } private static void PersistCompiler(TerrainComp compiler) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)compiler.m_nview != (Object)null && compiler.m_nview.IsValid() && !compiler.m_nview.IsOwner()) { compiler.m_nview.ClaimOwnership(); } compiler.m_operations++; compiler.m_lastOpPoint = Vector3.zero; compiler.m_lastOpRadius = 0f; compiler.Save(); compiler.m_hmap.Poke(false); } private static bool ShouldSerializePaints(Heightmap heightmap, int width, Color[] paints) { //IL_0025: 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) if (paints.Length != width * width) { return false; } Color[] array = TryGetBasePaints(heightmap, width); if (array == null || array.Length != paints.Length) { return true; } for (int i = 0; i < paints.Length; i++) { if (!Approximately(paints[i], array[i])) { return true; } } return false; } private static Color[] BuildCurrentPaintLayer(Heightmap heightmap, int width) { //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) Color[] array = (Color[])(object)new Color[width * width]; for (int i = 0; i < width; i++) { for (int j = 0; j < width; j++) { array[i * width + j] = GetPaint(heightmap, j, i); } } return array; } private static Color[]? TryGetBasePaints(Heightmap heightmap, int width) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) if (HeightmapBuilder.instance == null || WorldGenerator.instance == null) { return null; } try { HMBuildData val = HeightmapBuilder.instance.RequestTerrainSync(((Component)heightmap).transform.position, heightmap.m_width, heightmap.m_scale, heightmap.IsDistantLod, WorldGenerator.instance); return (val.m_baseMask != null && val.m_baseMask.Length == width * width) ? val.m_baseMask : null; } catch { return null; } } private static bool IsSupportFillBaseLayerNative(Heightmap heightmap, int width, float[] worldHeights, Color[] paints, Color[]? basePaints) { //IL_002d: 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_0034: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) bool flag = paints.Length == width * width; if (flag && (basePaints == null || basePaints.Length != paints.Length)) { return false; } for (int i = 0; i < worldHeights.Length; i++) { IndexToXZ(i, width, out var x, out var z); Vector3 val = VertexToWorld(heightmap, x, z); if (!TryGetTerrainBaseHeight(val.x, val.z, out var height) || Mathf.Abs(worldHeights[i] - height) > 0.01f || (flag && !Approximately(paints[i], basePaints[i]))) { return false; } } return true; } private static bool TryGetTerrainBaseHeight(float x, float z, out float height) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (WorldGenerator.instance != null) { height = WorldGenerator.instance.GetHeight(x, z); return true; } if (Heightmap.GetHeight(new Vector3(x, 0f, z), ref height)) { return true; } height = 0f; return false; } private static bool TryGetHeightmap(Vector2i zone, out Heightmap heightmap) { //IL_0015: 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) heightmap = null; if ((Object)(object)ZoneSystem.instance == (Object)null || !ZoneSystem.instance.IsZoneLoaded(zone)) { return false; } heightmap = Heightmap.FindHeightmap(ZoneSystem.GetZonePos(zone)); return (Object)(object)heightmap != (Object)null; } private static float GetWorldHeight(Heightmap heightmap, int x, int z) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) return heightmap.GetHeight(x, z) + ((Component)heightmap).transform.position.y; } private static Color GetPaint(Heightmap heightmap, int x, int z) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.Clamp(x, 0, heightmap.m_width); int num2 = Mathf.Clamp(z, 0, heightmap.m_width); return heightmap.GetPaintMask(num, num2); } private static bool IsCompilerReady(TerrainComp compiler) { if ((Object)(object)compiler == (Object)null || (Object)(object)compiler.m_hmap == (Object)null) { return false; } ZNetView component = ((Component)compiler).GetComponent(); if ((Object)(object)component != (Object)null) { return component.IsValid(); } return false; } private static bool IsValidPayloadIndex(int index, int width, int length) { if (width > 0 && index >= 0 && index < length) { return index < width * width; } return false; } private static void IndexToXZ(int index, int width, out int x, out int z) { z = index / width; x = index - z * width; } private static bool Approximately(Color a, Color b) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_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_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_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) if (Mathf.Abs(a.r - b.r) < 0.001f && Mathf.Abs(a.g - b.g) < 0.001f && Mathf.Abs(a.b - b.b) < 0.001f) { return Mathf.Abs(a.a - b.a) < 0.001f; } return false; } private static bool TryGetWearNTearWorldBounds(GameObject prefab, Vector3 position, Quaternion rotation, Vector3 scale, out Bounds bounds) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //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) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: 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_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) bounds = default(Bounds); Collider[] componentsInChildren = prefab.GetComponentsInChildren(); Matrix4x4 val = Matrix4x4.TRS(position, rotation, scale); bool flag = false; Collider[] array = componentsInChildren; foreach (Collider val2 in array) { if ((Object)(object)val2 == (Object)null || !val2.enabled || val2.isTrigger || !TryGetColliderLocalBounds(val2, out var bounds2)) { continue; } Matrix4x4 val3 = prefab.transform.worldToLocalMatrix * ((Component)val2).transform.localToWorldMatrix; foreach (Vector3 boundsCorner in GetBoundsCorners(bounds2)) { Vector3 val4 = ((Matrix4x4)(ref val)).MultiplyPoint3x4(((Matrix4x4)(ref val3)).MultiplyPoint3x4(boundsCorner)); if (flag) { ((Bounds)(ref bounds)).Encapsulate(val4); continue; } bounds = new Bounds(val4, Vector3.zero); flag = true; } } return flag; } private static bool TryGetColliderLocalBounds(Collider collider, out Bounds bounds) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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_006c: 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_0076: 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_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: 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_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) BoxCollider val = (BoxCollider)(object)((collider is BoxCollider) ? collider : null); if (val == null) { SphereCollider val2 = (SphereCollider)(object)((collider is SphereCollider) ? collider : null); if (val2 == null) { CapsuleCollider val3 = (CapsuleCollider)(object)((collider is CapsuleCollider) ? collider : null); if (val3 == null) { MeshCollider val4 = (MeshCollider)(object)((collider is MeshCollider) ? collider : null); if (val4 != null && (Object)(object)val4.sharedMesh != (Object)null) { bounds = val4.sharedMesh.bounds; return true; } Bounds bounds2 = collider.bounds; bounds = new Bounds(((Component)collider).transform.InverseTransformPoint(((Bounds)(ref bounds2)).center), ((Bounds)(ref bounds2)).size); return true; } Vector3 val5 = Vector3.one * (val3.radius * 2f); ((Vector3)(ref val5))[val3.direction] = Mathf.Max(val3.height, val3.radius * 2f); bounds = new Bounds(val3.center, val5); return true; } bounds = new Bounds(val2.center, Vector3.one * (val2.radius * 2f)); return true; } bounds = new Bounds(val.center, val.size); return true; } [IteratorStateMachine(typeof(d__37))] private static IEnumerable GetBoundsCorners(Bounds bounds) { //IL_0008: 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) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__37(-2) { <>3__bounds = bounds }; } private static long PackCell(int x, int z) { return ((long)x << 32) ^ (uint)z; } private static Vector3 VertexToWorld(Heightmap heightmap, int x, int z) { //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_0046: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)heightmap).transform.position; position.x += (float)(x - heightmap.m_width / 2) * heightmap.m_scale; position.z += (float)(z - heightmap.m_width / 2) * heightmap.m_scale; return position; } private static void WriteColor(ZPackage package, Color color) { //IL_0001: 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_0019: 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) package.Write(color.r); package.Write(color.g); package.Write(color.b); package.Write(color.a); } private static Color ReadColor(ZPackage package) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) return new Color(package.ReadSingle(), package.ReadSingle(), package.ReadSingle(), package.ReadSingle()); } } [HarmonyPatch(typeof(Heightmap), "ApplyModifiers")] internal static class HomesteadTerrainSupportBaseLayerPatch { private static void Prefix(Heightmap __instance) { HomesteadTerrainSupport.ApplyBaseLayer(__instance); } } internal static class HomesteadTimestamp { public static string Now() { return Format(DateTime.UtcNow); } public static string Format(DateTime utc) { if (utc == DateTime.MinValue) { return ""; } return new DateTimeOffset(DateTime.SpecifyKind(utc, DateTimeKind.Utc)).ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss zzz", CultureInfo.InvariantCulture); } public static DateTime ParseUtc(string value) { if (string.IsNullOrWhiteSpace(value)) { return DateTime.MinValue; } if (DateTimeOffset.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces, out var result) || DateTimeOffset.TryParse(value, CultureInfo.CurrentCulture, DateTimeStyles.AllowWhiteSpaces, out result)) { return DateTime.SpecifyKind(result.UtcDateTime, DateTimeKind.Utc); } if (DateTime.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeLocal, out var result2) || DateTime.TryParse(value, CultureInfo.CurrentCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeLocal, out result2)) { return DateTime.SpecifyKind(result2, DateTimeKind.Utc); } return DateTime.MinValue; } public static bool IsExpired(string timestamp, DateTime utcNow) { DateTime dateTime = ParseUtc(timestamp); if (dateTime != DateTime.MinValue) { return dateTime <= DateTime.SpecifyKind(utcNow, DateTimeKind.Utc); } return false; } } internal static class HomesteadYaml { private static readonly ISerializer Serializer = new SerializerBuilder().DisableAliases().ConfigureDefaultValuesHandling(DefaultValuesHandling.OmitNull).WithNamingConvention(CamelCaseNamingConvention.Instance) .WithTypeConverter(new FlowFloatArrayYamlConverter()) .Build(); private static readonly IDeserializer Deserializer = new DeserializerBuilder().IgnoreUnmatchedProperties().WithNamingConvention(CamelCaseNamingConvention.Instance).WithTypeConverter(new FlowFloatArrayYamlConverter()) .Build(); public static string Serialize(T value) { return Serializer.Serialize(value); } public static T Deserialize(string yaml) { return Deserializer.Deserialize(yaml) ?? throw new InvalidDataException("Failed to deserialize " + typeof(T).Name + "."); } } internal sealed class FlowFloatArrayYamlConverter : IYamlTypeConverter { public bool Accepts(Type type) { return type == typeof(float[]); } public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer) { parser.Consume(); List list = new List(); SequenceEnd @event; while (!parser.TryConsume(out @event)) { YamlDotNet.Core.Events.Scalar scalar = parser.Consume(); if (!float.TryParse(scalar.Value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { Mark start = scalar.Start; Mark end = scalar.End; throw new YamlException(in start, in end, "Invalid float value '" + scalar.Value + "'."); } list.Add(result); } return list.ToArray(); } public void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer) { float[] obj = (value as float[]) ?? Array.Empty(); emitter.Emit(new SequenceStart(AnchorName.Empty, TagName.Empty, isImplicit: true, SequenceStyle.Flow)); float[] array = obj; foreach (float num in array) { emitter.Emit(new YamlDotNet.Core.Events.Scalar(AnchorName.Empty, TagName.Empty, num.ToString("0.###", CultureInfo.InvariantCulture), ScalarStyle.Plain, isPlainImplicit: true, isQuotedImplicit: true)); } emitter.Emit(new SequenceEnd()); } } public static class ToggleExtensions { [SpecialName] public sealed class $7EB8D39D0590F52339A917419F61209D { [SpecialName] public static class $352DF56E54E9138FA9089CCF33D1E5A3 { } [ExtensionMarker("$352DF56E54E9138FA9089CCF33D1E5A3")] public bool IsOn() { throw new NotSupportedException(); } [ExtensionMarker("$352DF56E54E9138FA9089CCF33D1E5A3")] public bool IsOff() { throw new NotSupportedException(); } } public static bool IsOn(this HomesteadPlugin.Toggle value) { return value == HomesteadPlugin.Toggle.On; } public static bool IsOff(this HomesteadPlugin.Toggle value) { return value == HomesteadPlugin.Toggle.Off; } } public enum BlueprintAzuCraftyBoxesPullMode { Off, ConfirmOnly, OpenAndConfirm } public enum BlueprintTerrainSupportMode { Off, On, AdminDebug } public enum BlueprintAreaSaveCreatorMode { AllCreators, OwnedAndCreatorless, OwnedOnly } public enum BlueprintStoreIdentityMode { PlayerId, SteamId } public enum BlueprintStoreNotificationMode { Off, BadgeOnly, AutoOpenPanel } public enum BuildCameraDistanceMode { Fixed, ComfortScaled } public enum BuildCameraRestrictionMode { Off, CameraNeedsCoziness, CameraPickUpNeedsCoziness } internal static class VersionHandshakeLogger { public static ManualLogSource Log => HomesteadPlugin.HomesteadLogger; } [HarmonyPatch(typeof(ZNet), "OnNewConnection")] public static class RegisterAndCheckVersion { private static void Prefix(ZNetPeer peer, ref ZNet __instance) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown VersionHandshakeLogger.Log.LogDebug((object)"Registering version RPC handler"); peer.m_rpc.Register("Homestead_VersionCheck", (Action)RpcHandlers.RPC_ModVersion); VersionHandshakeLogger.Log.LogInfo((object)"Invoking version check"); ZPackage val = new ZPackage(); val.Write("1.0.5"); peer.m_rpc.Invoke("Homestead_VersionCheck", new object[1] { val }); } } [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] public static class VerifyClient { private static bool Prefix(ZRpc rpc, ZPackage pkg, ref ZNet __instance) { if (!__instance.IsServer() || RpcHandlers.ValidatedPeers.Contains(rpc)) { return true; } VersionHandshakeLogger.Log.LogWarning((object)("Peer (" + rpc.m_socket.GetHostName() + ") never sent version or couldn't due to previous disconnect, disconnecting")); rpc.Invoke("Error", new object[1] { 3 }); return false; } } [HarmonyPatch(typeof(FejdStartup), "ShowConnectError")] public class ShowConnectionError { private static void Postfix(FejdStartup __instance) { if (__instance.m_connectionFailedPanel.activeSelf) { __instance.m_connectionFailedError.fontSizeMax = 25f; __instance.m_connectionFailedError.fontSizeMin = 15f; TMP_Text connectionFailedError = __instance.m_connectionFailedError; connectionFailedError.text = connectionFailedError.text + "\n" + HomesteadPlugin.ConnectionError; } } } [HarmonyPatch(typeof(ZNet), "Disconnect")] public static class RemoveDisconnectedPeerFromVerified { private static void Prefix(ZNetPeer peer, ref ZNet __instance) { if (__instance.IsServer()) { VersionHandshakeLogger.Log.LogInfo((object)("Peer (" + peer.m_rpc.m_socket.GetHostName() + ") disconnected, removing from validated list")); RpcHandlers.ValidatedPeers.Remove(peer.m_rpc); } } } public static class RpcHandlers { public static readonly List ValidatedPeers = new List(); public static void RPC_ModVersion(ZRpc rpc, ZPackage pkg) { string text = pkg.ReadString(); VersionHandshakeLogger.Log.LogInfo((object)("Version check, local: 1.0.5, remote: " + text)); if (text != "1.0.5") { HomesteadPlugin.ConnectionError = "Homestead Installed: 1.0.5\n Needed: " + text; if (ZNet.instance.IsServer()) { VersionHandshakeLogger.Log.LogWarning((object)("Peer (" + rpc.m_socket.GetHostName() + ") has incompatible version, disconnecting...")); rpc.Invoke("Error", new object[1] { 3 }); } } else if (!ZNet.instance.IsServer()) { VersionHandshakeLogger.Log.LogInfo((object)"Received same version from server!"); } else { VersionHandshakeLogger.Log.LogInfo((object)("Adding peer (" + rpc.m_socket.GetHostName() + ") to validated list")); ValidatedPeers.Add(rpc); } } } internal static class ZoneAreaCameraZoomGuard { [HarmonyPatch(typeof(GameCamera), "UpdateCamera")] private static class GameCameraUpdateCameraPatch { private static void Prefix(GameCamera __instance) { if (_suppressFrame == Time.frameCount) { _distance = __instance.m_distance; _zoomSensitivity = __instance.m_zoomSens; __instance.m_zoomSens = 0f; } } private static void Postfix(GameCamera __instance) { if (_suppressFrame == Time.frameCount) { __instance.m_zoomSens = _zoomSensitivity; __instance.m_distance = _distance; } } } private static int _suppressFrame = -1; private static float _distance; private static float _zoomSensitivity; public static void SuppressWheelZoomThisFrame() { if (!((Object)(object)GameCamera.instance == (Object)null) && _suppressFrame != Time.frameCount) { _distance = GameCamera.instance.m_distance; _zoomSensitivity = GameCamera.instance.m_zoomSens; _suppressFrame = Time.frameCount; } } } internal sealed class ZoneAreaToolController { internal sealed class Options { public float MinSide { get; set; } public float SizeStep { get; set; } public Func MaxSide { get; set; } public Func DefaultWidth { get; set; } public Func DefaultDepth { get; set; } public Func Color { get; set; } public string RangeLineName { get; set; } = ""; public string TargetOverlayName { get; set; } = ""; public float TargetOverlayRefreshInterval { get; set; } = 0.12f; public float StableTargetOverlayRefreshInterval { get; set; } = 1f; public Func GetSavedYaw { get; set; } = () => null; public Action SetSavedYaw { get; set; } = delegate { }; public Func IsLocked { get; set; } = () => false; public Func? GetEffectiveYaw { get; set; } public Action? OnLockedScroll { get; set; } public Action? OnFrame { get; set; } public Func ShouldBlockToolInput { get; set; } = () => false; public Func StatusTitle { get; set; } = () => ""; public Func> FindCandidates { get; set; } = (Player _, ZoneAreaSelection _) => Array.Empty(); public Action OnClick { get; set; } = delegate { }; } private readonly MonoBehaviour _owner; private readonly Options _options; private LineRenderer? _rangeLine; private ZoneAreaTargetOverlay? _targetOverlay; private Material? _material; private bool _active; private float _width; private float _depth; private float _yaw; private float _heightOffset; private Vector3 _horizontalOffset; private Vector3 _aimPoint; private Vector3 _rawAimPoint; private bool _hasAimPoint; private int _suppressInputFrames; private float _lastTargetOverlayRefreshTime = -999f; private int _lastTargetOverlaySignature; private bool _hasTargetOverlaySignature; public bool Active => _active; public bool HasAimPoint => _hasAimPoint; public Vector3 AimPoint => _aimPoint; public float EffectiveYaw => GetEffectiveYaw(); public Vector3 HorizontalOffset => _horizontalOffset; public float HeightOffset => _heightOffset; public ZoneAreaSelection CurrentArea => ZoneAreaToolShared.BuildArea(_aimPoint, ref _width, ref _depth, _yaw, _options.DefaultWidth(), _options.DefaultDepth(), _options.MinSide, _options.MaxSide()); public string FormattedSize => ZoneAreaToolShared.FormatSize(_width, _depth); public ZoneAreaToolController(MonoBehaviour owner, Options options) { _owner = owner; _options = options; } public void Activate(Player player) { //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) if (!_active) { _width = Mathf.Clamp(_options.DefaultWidth(), _options.MinSide, _options.MaxSide()); _depth = Mathf.Clamp(_options.DefaultDepth(), _options.MinSide, _options.MaxSide()); float? num = _options.GetSavedYaw(); float yaw; if (!num.HasValue) { Quaternion rotation = ((Component)player).transform.rotation; yaw = ZoneAreaSelection.NormalizeYaw(((Quaternion)(ref rotation)).eulerAngles.y); } else { yaw = num.GetValueOrDefault(); } _yaw = yaw; _heightOffset = 0f; _horizontalOffset = Vector3.zero; } _active = true; _hasAimPoint = false; _suppressInputFrames = 2; EnsureRangeLine(); } public void Deactivate() { _active = false; ResetOffsets(); ClearTargetOverlay(); ZoneAreaToolStatusHud.Hide(); HideRange(); } public void ResetOffsets() { //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) _heightOffset = 0f; _horizontalOffset = Vector3.zero; } public void Destroy() { _targetOverlay?.Destroy(); _targetOverlay = null; if ((Object)(object)_material != (Object)null) { Object.Destroy((Object)(object)_material); _material = null; } } public bool Tick() { //IL_0058: 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_0060: 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_0066: Unknown result type (might be due to invalid IL or missing references) if (!_active) { return true; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || !ZoneAreaToolShared.IsHoldingBuildTool(localPlayer)) { return false; } if (!ZoneAreaToolShared.TryGetAimPoint(localPlayer, _options.MaxSide(), out var point)) { _hasAimPoint = false; HideRange(); ClearTargetOverlay(); ZoneAreaToolStatusHud.Hide(); return true; } _rawAimPoint = point; _aimPoint = GetAdjustedAimPoint(point); _hasAimPoint = true; bool flag = _options.IsLocked(); if (flag) { HideRange(); ClearTargetOverlay(); } else { DrawRange(); UpdateTargetOverlay(localPlayer); } _options.OnFrame?.Invoke(localPlayer); UpdateStatusHud(); if (ZoneAreaToolShared.ShouldBlockInput()) { return true; } if (_suppressInputFrames > 0) { _suppressInputFrames--; return true; } if (_options.ShouldBlockToolInput()) { return true; } HandleScroll(flag); HandleOffset(); UpdateStatusHud(); if (!flag && Input.GetMouseButtonDown(0)) { _options.OnClick(localPlayer, CurrentArea); } return true; } private void HandleScroll(bool locked) { float axis = Input.GetAxis("Mouse ScrollWheel"); if (Mathf.Abs(axis) <= 0.001f) { return; } ZoneAreaCameraZoomGuard.SuppressWheelZoomThisFrame(); if (locked && _options.OnLockedScroll != null) { _options.OnLockedScroll(axis); return; } float delta = ((axis > 0f) ? _options.SizeStep : (0f - _options.SizeStep)); if (PlacementControlConfig.IsAreaDepthModifierHeld()) { ZoneAreaToolShared.ResizeDepth(ref _depth, delta, _options.MinSide, _options.MaxSide()); ClearTargetOverlay(); return; } if (PlacementControlConfig.IsAreaWidthModifierHeld()) { ZoneAreaToolShared.ResizeWidth(ref _width, delta, _options.MinSide, _options.MaxSide()); ClearTargetOverlay(); return; } if (PlacementControlConfig.IsAreaUniformScaleModifierHeld()) { ZoneAreaToolShared.ResizeUniform(ref _width, ref _depth, delta, _options.MinSide, _options.MaxSide()); ClearTargetOverlay(); return; } float num = ((axis > 0f) ? PlacementControlConfig.RotationStep : (0f - PlacementControlConfig.RotationStep)); _yaw = ZoneAreaSelection.NormalizeYaw(_yaw + num); _options.SetSavedYaw(_yaw); ClearTargetOverlay(); } private void HandleOffset() { //IL_0063: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) bool flag = false; if (PlacementControlConfig.IsPlacementAdjustModifierHeld() && (Input.GetKeyDown((KeyCode)280) || Input.GetKeyDown((KeyCode)281))) { float num = (Input.GetKeyDown((KeyCode)280) ? 1f : (-1f)); _heightOffset = ZoneAreaToolShared.RoundOffset(_heightOffset + num * PlacementControlConfig.HeightStep); flag = true; } Vector3 val = (PlacementControlConfig.IsPlacementAdjustModifierHeld() ? ZonePlacementOffset.GetArrowKeyLocalNudge() : Vector3.zero); if (((Vector3)(ref val)).sqrMagnitude > 0.0001f) { _horizontalOffset += val * PlacementControlConfig.HorizontalStep; flag = true; } if (flag) { _aimPoint = GetAdjustedAimPoint(_rawAimPoint); ClearTargetOverlay(); } } private Vector3 GetAdjustedAimPoint(Vector3 rawAimPoint) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) return ZoneAreaToolShared.GetAdjustedAimPoint(rawAimPoint, GetEffectiveYaw(), _horizontalOffset, _heightOffset); } private float GetEffectiveYaw() { return _options.GetEffectiveYaw?.Invoke(_yaw) ?? _yaw; } private void DrawRange() { //IL_0022: 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) EnsureRangeLine(); if (!((Object)(object)_rangeLine == (Object)null)) { ZoneAreaToolShared.DrawGroundRectangle(_rangeLine, CurrentArea, _aimPoint, _heightOffset, _options.Color()); } } private void UpdateTargetOverlay(Player player) { if (ZDOMan.instance == null || (Object)(object)ZNetScene.instance == (Object)null) { return; } ZoneAreaSelection currentArea = CurrentArea; int num = BuildTargetOverlaySignature(currentArea); bool num2 = !_hasTargetOverlaySignature || num != _lastTargetOverlaySignature; float time = Time.time; float num3 = (num2 ? _options.TargetOverlayRefreshInterval : Mathf.Max(_options.TargetOverlayRefreshInterval, _options.StableTargetOverlayRefreshInterval)); if (!(time - _lastTargetOverlayRefreshTime < num3)) { _lastTargetOverlaySignature = num; _hasTargetOverlaySignature = true; _lastTargetOverlayRefreshTime = time; if (_targetOverlay == null) { _targetOverlay = new ZoneAreaTargetOverlay(((Component)_owner).transform, _options.TargetOverlayName); } _targetOverlay.Draw(_options.FindCandidates(player, currentArea), currentArea); } } private void ClearTargetOverlay() { _targetOverlay?.Clear(); _lastTargetOverlayRefreshTime = -999f; _hasTargetOverlaySignature = false; } private static int BuildTargetOverlaySignature(ZoneAreaSelection area) { //IL_0007: 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) return ((((17 * 31 + Mathf.RoundToInt(area.Center.x * 2f)) * 31 + Mathf.RoundToInt(area.Center.z * 2f)) * 31 + Mathf.RoundToInt(area.Width * 2f)) * 31 + Mathf.RoundToInt(area.Depth * 2f)) * 31 + Mathf.RoundToInt(area.Yaw * 10f); } private void UpdateStatusHud() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) ZoneAreaToolStatusHud.Show(_options.StatusTitle(), FormattedSize, GetEffectiveYaw(), _horizontalOffset, _heightOffset); } private void EnsureRangeLine() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_rangeLine != (Object)null)) { EnsureMaterial(); _rangeLine = ZoneAreaToolShared.CreateLineRenderer(((Component)_owner).transform, _options.RangeLineName, 0.12f, _options.Color(), _material); ((Renderer)_rangeLine).enabled = false; } } private void EnsureMaterial() { if (_material == null) { _material = ZoneAreaToolShared.CreateLineMaterial(); } } private void HideRange() { if ((Object)(object)_rangeLine != (Object)null) { ((Renderer)_rangeLine).enabled = false; } } } internal sealed class ZoneAreaDismantleTool : MonoBehaviour { private readonly struct DismantleTarget { public ZDO Zdo { get; } public GameObject Prefab { get; } public DismantleTarget(ZDO zdo, GameObject prefab) { Zdo = zdo; Prefab = prefab; } } private sealed class MaterialRefund { public string PrefabName { get; } public string DisplayName { get; } public ItemData Prototype { get; } public GameObject DropPrefab { get; } public int Amount { get; set; } public MaterialRefund(string prefabName, string displayName, ItemData prototype, GameObject dropPrefab) { PrefabName = prefabName; DisplayName = displayName; Prototype = prototype; DropPrefab = dropPrefab; } } private readonly struct DismantleResult { public bool Success { get; } public string Message { get; } public bool PlayDestroySfx { get; } public Vector3 EffectPosition { get; } public DismantleResult(bool success, string message, bool playDestroySfx = false, Vector3 effectPosition = default(Vector3)) { //IL_0016: 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) Success = success; Message = message; PlayDestroySfx = playDestroySfx; EffectPosition = effectPosition; } public static DismantleResult Ok(string message, Vector3 effectPosition) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) return new DismantleResult(success: true, message, playDestroySfx: true, effectPosition); } public static DismantleResult Fail(string message) { //IL_0005: 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) return new DismantleResult(success: false, message); } } private const float MinSideLength = 1f; private const float SizeStep = 1f; private const float TargetOverlayRefreshInterval = 0.3f; private const float RequestCooldownSeconds = 1f; private const float RequestCooldownCleanupSeconds = 60f; private const string RequestRpcName = "sighsorry.Homestead_AreaDismantleRequest"; private const string ResultRpcName = "sighsorry.Homestead_AreaDismantleResult"; private const string DestroySfxPrefab = "sfx_wood_destroyed"; private static ManualLogSource? _logger; private static ZoneAreaDismantleTool? _instance; private static readonly ZoneRpcRegistrar RpcRegistrar = new ZoneRpcRegistrar(); private static float? _lastAreaYaw; private static readonly Dictionary NextRequestAtBySender = new Dictionary(); private static float _nextCooldownCleanup; private readonly List _nearbyTargetZdos = new List(); private readonly List _targetCandidateZdos = new List(); private ZoneAreaToolController? _areaTool; private bool _active; private static float MaxSelectableSide => Mathf.Max(1f, AreaToolConfig.DismantleMaxSide); public static bool IsActive { get { ZoneAreaDismantleTool? instance = _instance; if (instance == null) { return false; } return (instance._areaTool?.Active).GetValueOrDefault(); } } private ZoneAreaToolController AreaTool => _areaTool ?? (_areaTool = new ZoneAreaToolController((MonoBehaviour)(object)this, new ZoneAreaToolController.Options { MinSide = 1f, SizeStep = 1f, MaxSide = () => MaxSelectableSide, DefaultWidth = () => AreaToolConfig.DismantleDefaultWidth, DefaultDepth = () => AreaToolConfig.DismantleDefaultDepth, Color = () => AreaToolConfig.DismantleColor, RangeLineName = "HomesteadAreaDismantleRadius", TargetOverlayName = "HomesteadAreaDismantleTarget", TargetOverlayRefreshInterval = 0.3f, GetSavedYaw = () => _lastAreaYaw, SetSavedYaw = delegate(float yaw) { _lastAreaYaw = yaw; }, StatusTitle = () => HomesteadLocalization.Text("hs_area_dismantle_name"), FindCandidates = FindDismantlePreviewCandidates, OnClick = RequestDismantle })); public static void Initialize(ManualLogSource logger) { _logger = logger; EnsureInstance(); RegisterRpcs(); } internal static void RegisterRpcs() { RpcRegistrar.EnsureRegistered(delegate(ZRoutedRpc routedRpc) { routedRpc.Register("sighsorry.Homestead_AreaDismantleRequest", (Action)RPC_HandleRequest); routedRpc.Register("sighsorry.Homestead_AreaDismantleResult", (Action)RPC_HandleResult); }); } public static void Activate(Player player) { EnsureInstance(); _instance?.ActivateInternal(player); } public static void Deactivate() { _instance?.DeactivateInternal(); } private static void EnsureInstance() { //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_002a: Expected O, but got Unknown if (!((Object)(object)_instance != (Object)null) || !Object.op_Implicit((Object)(object)_instance)) { GameObject val = new GameObject("HomesteadAreaDismantleTool"); Object.DontDestroyOnLoad((Object)val); _instance = val.AddComponent(); } } private void ActivateInternal(Player player) { _active = true; AreaTool.Activate(player); } private void DeactivateInternal() { _active = false; _areaTool?.Deactivate(); } private void Update() { if (!_active) { ZoneAreaToolController? areaTool = _areaTool; if (areaTool == null || !areaTool.Active) { return; } } if (!AreaTool.Tick()) { DeactivateInternal(); } } private void OnDestroy() { _areaTool?.Destroy(); _areaTool = null; if ((Object)(object)_instance == (Object)(object)this) { _instance = null; } } private void RequestDismantle(Player player) { RequestDismantle(player, AreaTool.CurrentArea); } private void RequestDismantle(Player player, ZoneAreaSelection area) { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected O, but got Unknown //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) if (!AreaTool.HasAimPoint) { return; } if ((Object)(object)ZNet.instance == (Object)null || ZDOMan.instance == null) { ShowResult(DismantleResult.Fail(HomesteadLocalization.Text("hs_common_world_not_ready"))); return; } if (ZNet.instance.IsServer()) { long playerID = player.GetPlayerID(); if (!TryReserveLocalRequest(playerID, out string reason)) { ShowResult(DismantleResult.Fail(reason)); } else { ShowResult(ExecuteDismantle(playerID, ((Component)player).transform.position, area)); } return; } RegisterRpcs(); ZPackage val = new ZPackage(); val.Write(area.Center); val.Write(area.Width); val.Write(area.Depth); val.Write(area.Yaw); ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), "sighsorry.Homestead_AreaDismantleRequest", new object[1] { val }); } private static void RPC_HandleRequest(long sender, ZPackage package) { //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Expected O, but got Unknown //IL_00da: 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_0067: 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 ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return; } DismantleResult dismantleResult; try { if (!TryReserveRequest(sender, out string reason)) { dismantleResult = DismantleResult.Fail(reason); } else { Vector3 center = package.ReadVector3(); float width = package.ReadSingle(); float depth = package.ReadSingle(); float yaw = package.ReadSingle(); dismantleResult = (TryResolveRemotePlayer(sender, out long playerId, out Vector3 playerPosition, out string reason2) ? ExecuteDismantle(playerId, playerPosition, new ZoneAreaSelection(center, width, depth, yaw)) : DismantleResult.Fail(reason2)); } } catch (Exception ex) { ManualLogSource? logger = _logger; if (logger != null) { logger.LogError((object)$"Area dismantle RPC failed: {ex}"); } dismantleResult = DismantleResult.Fail(ex.Message); } ZPackage val = new ZPackage(); val.Write(dismantleResult.Success); val.Write(dismantleResult.Message); val.Write(dismantleResult.PlayDestroySfx); val.Write(dismantleResult.EffectPosition); ZRoutedRpc.instance.InvokeRoutedRPC(sender, "sighsorry.Homestead_AreaDismantleResult", new object[1] { val }); } private static bool TryReserveRequest(long sender, out string reason) { reason = ""; if (sender == 0L) { return true; } float now = Time.realtimeSinceStartup; if (now >= _nextCooldownCleanup) { _nextCooldownCleanup = now + 60f; foreach (long item in (from pair in NextRequestAtBySender where pair.Value <= now select pair.Key).ToList()) { NextRequestAtBySender.Remove(item); } } if (NextRequestAtBySender.TryGetValue(sender, out var value) && now < value) { reason = HomesteadLocalization.Text("hs_dismantle_rpc_cooldown"); return false; } NextRequestAtBySender[sender] = now + 1f; return true; } private static bool TryReserveLocalRequest(long playerId, out string reason) { reason = ""; if (playerId == 0L) { return true; } return TryReserveRequest((playerId > 0) ? (-playerId) : playerId, out reason); } private static void RPC_HandleResult(long sender, ZPackage package) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)ZNet.instance != (Object)null) || !ZNet.instance.IsServer()) { ShowResult(new DismantleResult(package.ReadBool(), package.ReadString(), package.ReadBool(), package.ReadVector3())); } } private IReadOnlyList FindDismantlePreviewCandidates(Player player, ZoneAreaSelection area) { _targetCandidateZdos.Clear(); if (ZDOMan.instance == null || (Object)(object)ZNetScene.instance == (Object)null || (Object)(object)player == (Object)null) { return _targetCandidateZdos; } long playerID = player.GetPlayerID(); if (playerID == 0L) { return _targetCandidateZdos; } HashSet areaDismantlePrefabBlacklist = BlueprintConfig.AreaDismantlePrefabBlacklist; ZoneAreaTargetOverlay.CollectNearbyZdos(area, _nearbyTargetZdos); foreach (ZDO nearbyTargetZdo in _nearbyTargetZdos) { if (!ZoneBlueprintCommands.IsHomesteadBlueprintChest(nearbyTargetZdo) && nearbyTargetZdo.GetLong(ZDOVars.s_creator, 0L) == playerID && ZoneBlueprintCommands.TryReadWearNTear(nearbyTargetZdo, out GameObject prefab) && IsLoadedWearNTear(nearbyTargetZdo)) { string prefabName = Utils.GetPrefabName(prefab); if (!areaDismantlePrefabBlacklist.Contains(prefabName) && !HasProtectedContentsOrAttachments(nearbyTargetZdo, prefab)) { _targetCandidateZdos.Add(nearbyTargetZdo); } } } return _targetCandidateZdos; } private static bool IsLoadedWearNTear(ZDO zdo) { if ((Object)(object)ZNetScene.instance == (Object)null) { return false; } ZNetView val = ZNetScene.instance.FindInstance(zdo); if ((Object)(object)val != (Object)null) { return (Object)(object)((Component)val).GetComponent() != (Object)null; } return false; } private static DismantleResult ExecuteDismantle(long playerId, Vector3 playerPosition, ZoneAreaSelection area) { //IL_004e: 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_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_0281: Unknown result type (might be due to invalid IL or missing references) //IL_02ce: Unknown result type (might be due to invalid IL or missing references) if (ZDOMan.instance == null || (Object)(object)ZNetScene.instance == (Object)null) { return DismantleResult.Fail(HomesteadLocalization.Text("hs_common_world_not_ready")); } if (playerId == 0L) { return DismantleResult.Fail(HomesteadLocalization.Text("hs_dismantle_playerid_missing")); } float maxSelectableSide = MaxSelectableSide; area = area.Clamp(1f, maxSelectableSide); if (HorizontalDistance(area.Center, playerPosition) > area.HalfDiagonal + maxSelectableSide + 16f) { return DismantleResult.Fail(HomesteadLocalization.Text("hs_dismantle_too_far")); } List list = new List(); int num = 0; int num2 = 0; int num3 = 0; HashSet areaDismantlePrefabBlacklist = BlueprintConfig.AreaDismantlePrefabBlacklist; List list2 = new List(); ZoneAreaTargetOverlay.CollectNearbyZdos(area, list2); foreach (ZDO item in list2) { if (!ZoneBlueprintCommands.TryReadWearNTear(item, out GameObject prefab)) { continue; } string prefabName = Utils.GetPrefabName(prefab); if (area.Contains(item.GetPosition())) { if (ZoneBlueprintCommands.IsHomesteadBlueprintChest(item)) { num2++; } else if (areaDismantlePrefabBlacklist.Contains(prefabName) || ZoneBlueprintCommands.IsHomesteadBlueprintChestPrefab(prefab)) { num2++; } else if (item.GetLong(ZDOVars.s_creator, 0L) != playerId) { num++; } else if (HasProtectedContentsOrAttachments(item, prefab)) { num3++; } else { list.Add(new DismantleTarget(item, prefab)); } } } if (list.Count == 0) { string text = BuildSkippedMessage(num, num2, num3, verbose: true); return DismantleResult.Fail(HomesteadLocalization.Format("hs_dismantle_no_owned", Mathf.RoundToInt(area.Width), Mathf.RoundToInt(area.Depth), text)); } Dictionary dictionary = new Dictionary(); foreach (DismantleTarget item2 in list) { CollectRefundMaterials(item2.Prefab, dictionary); } int num4 = 0; foreach (DismantleTarget item3 in list) { if (item3.Zdo != null && item3.Zdo.IsValid()) { SavedZdoHelper.Destroy(item3.Zdo); num4++; } } SavedZdoHelper.FlushDestroyed(); int num5 = dictionary.Values.Sum((MaterialRefund refund) => refund.Amount); int num6 = DropRefundStacks(dictionary.Values, area.Center); string text2 = BuildSkippedMessage(num, num2, num3, verbose: false); return DismantleResult.Ok(HomesteadLocalization.Format("hs_dismantle_done", num4, num5, num6, text2), area.Center); } private static string BuildSkippedMessage(int skippedNotOwned, int skippedBlacklisted, int skippedWithContents, bool verbose) { List list = new List(); if (skippedNotOwned > 0) { list.Add(verbose ? HomesteadLocalization.Format("hs_dismantle_skipped_not_owned_verbose", skippedNotOwned) : HomesteadLocalization.Format("hs_dismantle_skipped_not_owned_short", skippedNotOwned)); } if (skippedBlacklisted > 0) { list.Add(verbose ? HomesteadLocalization.Format("hs_dismantle_skipped_blacklisted_verbose", skippedBlacklisted) : HomesteadLocalization.Format("hs_dismantle_skipped_blacklisted_short", skippedBlacklisted)); } if (skippedWithContents > 0) { list.Add(verbose ? HomesteadLocalization.Format("hs_dismantle_skipped_contents_verbose", skippedWithContents) : HomesteadLocalization.Format("hs_dismantle_skipped_contents_short", skippedWithContents)); } if (list.Count != 0) { return HomesteadLocalization.Format("hs_dismantle_skipped_suffix", string.Join(", ", list)); } return ""; } private static bool HasProtectedContentsOrAttachments(ZDO zdo, GameObject prefab) { if ((Object)(object)prefab.GetComponent() != (Object)null && HasContainerItems(zdo)) { return true; } if ((Object)(object)prefab.GetComponent() != (Object)null && !string.IsNullOrEmpty(zdo.GetString(ZDOVars.s_item, ""))) { return true; } ArmorStand component = prefab.GetComponent(); if ((Object)(object)component != (Object)null) { int num = Mathf.Max(component.m_slots?.Count ?? 0, 32); for (int i = 0; i < num; i++) { if (!string.IsNullOrEmpty(zdo.GetString(i + "_item", ""))) { return true; } } } return false; } private static bool HasContainerItems(ZDO zdo) { //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) string @string = zdo.GetString(ZDOVars.s_items, ""); if (!string.IsNullOrEmpty(@string)) { try { ZPackage val = new ZPackage(@string); val.ReadInt(); return val.ReadInt() > 0; } catch { return true; } } ZNetScene instance = ZNetScene.instance; ZNetView val2 = ((instance != null) ? instance.FindInstance(zdo) : null); Container val3 = (((Object)(object)val2 != (Object)null) ? ((Component)val2).GetComponent() : null); if ((Object)(object)val3 == (Object)null) { return false; } try { val3.Load(); } catch { } Inventory inventory = val3.GetInventory(); if (inventory == null) { return false; } return inventory.NrOfItems() > 0; } private static bool TryResolveRemotePlayer(long sender, out long playerId, out Vector3 playerPosition, out string reason) { //IL_0005: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) playerId = 0L; playerPosition = Vector3.zero; reason = ""; if ((Object)(object)ZNet.instance == (Object)null || ZDOMan.instance == null) { reason = "World is not ready."; return false; } ZNetPeer peer = ZNet.instance.GetPeer(sender); if (peer == null || !peer.IsReady()) { reason = "Player is not ready."; return false; } playerPosition = peer.m_refPos; if (((ZDOID)(ref peer.m_characterID)).IsNone()) { reason = "Could not resolve your character."; return false; } ZDO zDO = ZDOMan.instance.GetZDO(peer.m_characterID); playerId = ((zDO != null) ? zDO.GetLong(ZDOVars.s_playerID, 0L) : 0); if (playerId == 0L) { reason = "Could not resolve your playerID."; return false; } return true; } private static void CollectRefundMaterials(GameObject prefab, Dictionary refunds) { Piece component = prefab.GetComponent(); if ((Object)(object)component == (Object)null) { return; } Requirement[] resources = component.m_resources; foreach (Requirement val in resources) { if (!Object.op_Implicit((Object)(object)val.m_resItem) || val.m_amount <= 0 || !val.m_recover) { continue; } int amount = val.GetAmount(0); if (amount > 0) { string prefabName = Utils.GetPrefabName(((Component)val.m_resItem).gameObject); if (!refunds.TryGetValue(prefabName, out MaterialRefund value)) { value = (refunds[prefabName] = new MaterialRefund(prefabName, val.m_resItem.m_itemData.m_shared.m_name, val.m_resItem.m_itemData, ((Component)val.m_resItem).gameObject)); } value.Amount += amount; } } } private static int DropRefundStacks(IEnumerable refunds, Vector3 dropPosition) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) int num = 0; foreach (MaterialRefund refund in refunds) { if (refund.Amount > 0) { int num2 = Mathf.Max(1, refund.Prototype.m_shared.m_maxStackSize); int num3 = refund.Amount; while (num3 > 0) { int num4 = Mathf.Min(num3, num2); ItemData obj = refund.Prototype.Clone(); obj.m_stack = num4; obj.m_dropPrefab = refund.DropPrefab; Vector2 val = Random.insideUnitCircle * 0.8f; Vector3 val2 = dropPosition + new Vector3(val.x, 0.85f, val.y); ItemDrop.DropItem(obj, 0, val2, Random.rotation); num3 -= num4; num++; } } } return num; } private static float HorizontalDistance(Vector3 a, Vector3 b) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) float num = a.x - b.x; float num2 = a.z - b.z; return Mathf.Sqrt(num * num + num2 * num2); } private static void ShowResult(DismantleResult result) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) ManualLogSource? logger = _logger; if (logger != null) { logger.LogInfo((object)result.Message); } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { ((Character)localPlayer).Message((MessageType)(result.Success ? 1 : 2), result.Message, 0, (Sprite)null); } if (result.PlayDestroySfx) { PlayDestroySfx(result.EffectPosition); } } private static void PlayDestroySfx(Vector3 position) { //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) ZNetScene instance = ZNetScene.instance; GameObject val = ((instance != null) ? instance.GetPrefab("sfx_wood_destroyed") : null); if (Object.op_Implicit((Object)(object)val)) { Object.Instantiate(val, position, Quaternion.identity); } } private static void Message(Player player, string message) { ManualLogSource? logger = _logger; if (logger != null) { logger.LogInfo((object)message); } ((Character)player).Message((MessageType)1, message, 0, (Sprite)null); } } internal readonly struct ZoneAreaSelection { public Vector3 Center { get; } public float Width { get; } public float Depth { get; } public float Yaw { get; } public float MaxSide => Mathf.Max(Width, Depth); public float HalfDiagonal => Mathf.Sqrt(Width * Width + Depth * Depth) * 0.5f; public Quaternion Rotation => Quaternion.Euler(0f, Yaw, 0f); public ZoneAreaSelection(Vector3 center, float width, float depth, float yaw) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) Center = center; Width = Mathf.Max(0.01f, width); Depth = Mathf.Max(0.01f, depth); Yaw = NormalizeYaw(yaw); } public ZoneAreaSelection Clamp(float minSide, float maxSide) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return new ZoneAreaSelection(Center, Mathf.Clamp(Width, minSide, maxSide), Mathf.Clamp(Depth, minSide, maxSide), Yaw); } public bool Contains(Vector3 worldPosition) { //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_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_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Quaternion.Inverse(Rotation) * (worldPosition - Center); if (Mathf.Abs(val.x) <= Width * 0.5f) { return Mathf.Abs(val.z) <= Depth * 0.5f; } return false; } public bool IntersectsBoundary(Bounds worldBounds) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) GetLocalBounds(worldBounds, out var minX, out var maxX, out var minZ, out var maxZ); float num = Width * 0.5f; float num2 = Depth * 0.5f; if (!(maxX >= 0f - num) || !(minX <= num) || !(maxZ >= 0f - num2) || !(minZ <= num2)) { return false; } return !(minX >= 0f - num) || !(maxX <= num) || !(minZ >= 0f - num2) || !(maxZ <= num2); } public Vector3 GetCorner(int index) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: 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_0080: 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_006b: Unknown result type (might be due to invalid IL or missing references) float num = Width * 0.5f; float num2 = Depth * 0.5f; Vector3 val = (Vector3)(index switch { 0 => new Vector3(0f - num, 0f, 0f - num2), 1 => new Vector3(num, 0f, 0f - num2), 2 => new Vector3(num, 0f, num2), _ => new Vector3(0f - num, 0f, num2), }); return Center + Rotation * val; } private void GetLocalBounds(Bounds worldBounds, out float minX, out float maxX, out float minZ, out float maxZ) { //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_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_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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0068: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: 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) Quaternion val = Quaternion.Inverse(Rotation); Vector3 min = ((Bounds)(ref worldBounds)).min; Vector3 max = ((Bounds)(ref worldBounds)).max; minX = (minZ = float.PositiveInfinity); maxX = (maxZ = float.NegativeInfinity); Encapsulate(val * (new Vector3(min.x, 0f, min.z) - Center), ref minX, ref maxX, ref minZ, ref maxZ); Encapsulate(val * (new Vector3(min.x, 0f, max.z) - Center), ref minX, ref maxX, ref minZ, ref maxZ); Encapsulate(val * (new Vector3(max.x, 0f, min.z) - Center), ref minX, ref maxX, ref minZ, ref maxZ); Encapsulate(val * (new Vector3(max.x, 0f, max.z) - Center), ref minX, ref maxX, ref minZ, ref maxZ); } private static void Encapsulate(Vector3 local, ref float minX, ref float maxX, ref float minZ, ref float maxZ) { //IL_0003: 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_0021: 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) minX = Mathf.Min(minX, local.x); maxX = Mathf.Max(maxX, local.x); minZ = Mathf.Min(minZ, local.z); maxZ = Mathf.Max(maxZ, local.z); } public static float NormalizeYaw(float yaw) { yaw %= 360f; if (!(yaw < 0f)) { return yaw; } return yaw + 360f; } } internal static class ZoneAreaToolShared { private const float LineHeight = 0.25f; private const int MinEdgeSegments = 4; private const int MaxEdgeSegments = 64; public static ZoneAreaSelection BuildArea(Vector3 center, ref float width, ref float depth, float yaw, float defaultWidth, float defaultDepth, float minSide, float maxSide) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) width = Mathf.Clamp((width <= 0f) ? defaultWidth : width, minSide, maxSide); depth = Mathf.Clamp((depth <= 0f) ? defaultDepth : depth, minSide, maxSide); return new ZoneAreaSelection(center, width, depth, yaw).Clamp(minSide, maxSide); } public static void ResizeUniform(ref float width, ref float depth, float delta, float minSide, float maxSide) { float num = Mathf.Max(minSide, Mathf.Max(width, depth)); float num2 = Mathf.Clamp(num + delta, minSide, maxSide) / num; width = Mathf.Clamp(width * num2, minSide, maxSide); depth = Mathf.Clamp(depth * num2, minSide, maxSide); } public static void ResizeDepth(ref float depth, float delta, float minSide, float maxSide) { depth = Mathf.Clamp(depth + delta, minSide, maxSide); } public static void ResizeWidth(ref float width, float delta, float minSide, float maxSide) { width = Mathf.Clamp(width + delta, minSide, maxSide); } public static void DrawGroundRectangle(LineRenderer line, ZoneAreaSelection area, Vector3 center, float heightOffset, Color color) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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_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_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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_0081: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) ((Renderer)line).enabled = true; line.startColor = color; line.endColor = color; int num = Mathf.Clamp(Mathf.CeilToInt(area.MaxSide / 4f), 4, 64); line.positionCount = num * 4 + 1; int num2 = 0; for (int i = 0; i < 4; i++) { Vector3 corner = area.GetCorner(i); Vector3 corner2 = area.GetCorner((i + 1) % 4); for (int j = 0; j < num; j++) { Vector3 val = Vector3.Lerp(corner, corner2, (float)j / (float)num); val.y = ZoneToolAim.SampleGroundY(val.x, val.z, center.y) + 0.25f + heightOffset; line.SetPosition(num2++, val); } } Vector3 corner3 = area.GetCorner(0); corner3.y = ZoneToolAim.SampleGroundY(corner3.x, corner3.z, center.y) + 0.25f + heightOffset; line.SetPosition(num2, corner3); } public static LineRenderer CreateLineRenderer(Transform parent, string objectName, float width, Color color, Material? material) { //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_0052: 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) GameObject val = new GameObject(objectName); val.transform.SetParent(parent, false); LineRenderer obj = val.AddComponent(); obj.useWorldSpace = true; obj.startWidth = width; obj.endWidth = width; obj.numCornerVertices = 2; obj.numCapVertices = 2; ((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)obj).receiveShadows = false; ((Renderer)obj).material = material; obj.startColor = color; obj.endColor = color; return obj; } public static Material? CreateLineMaterial() { //IL_0025: 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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown Shader val = Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Color"); if ((Object)(object)val == (Object)null) { return null; } return new Material(val) { color = Color.white }; } public static Vector3 GetAdjustedAimPoint(Vector3 aimPoint, float yaw, Vector3 horizontalOffset, float heightOffset) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_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) return aimPoint + ZonePlacementOffset.ToWorldOffset(yaw, horizontalOffset, heightOffset); } public static string FormatSize(float width, float depth) { return $"{Mathf.RoundToInt(width)}x{Mathf.RoundToInt(depth)}m"; } public static string FormatScaleInput() { if (!string.IsNullOrWhiteSpace(PlacementControlConfig.AreaUniformScaleInputLabel)) { return PlacementControlConfig.AreaUniformScaleInputLabel; } return HomesteadLocalization.Text("hs_common_unbound"); } public static string FormatDepthInput() { if (!string.IsNullOrWhiteSpace(BlueprintConfig.AreaToolDepthInputLabel)) { return BlueprintConfig.AreaToolDepthInputLabel; } return HomesteadLocalization.Text("hs_common_unbound"); } public static string FormatWidthInput() { if (!string.IsNullOrWhiteSpace(BlueprintConfig.AreaToolWidthInputLabel)) { return BlueprintConfig.AreaToolWidthInputLabel; } return HomesteadLocalization.Text("hs_common_unbound"); } public static float RoundOffset(float value) { return Mathf.Round(value * 1000f) / 1000f; } public static bool TryGetAimPoint(Player player, float maxSelectableSide, out Vector3 point) { return ZoneToolAim.TryGetAimPoint(player, maxSelectableSide * 2f, out point); } public static bool IsHoldingBuildTool(Player player) { return (Object)(object)((Humanoid)player).GetRightItem()?.m_shared?.m_buildPieces != (Object)null; } public static bool ShouldBlockInput() { if (Hud.IsPieceSelectionVisible() || Console.IsVisible() || TextInput.IsVisible() || Menu.IsVisible() || InventoryGui.IsVisible() || Minimap.IsOpen()) { return true; } if ((Object)(object)Chat.instance != (Object)null) { return Chat.instance.HasFocus(); } return false; } } internal sealed class ZoneAreaToolStatusHud : MonoBehaviour { private static ZoneAreaToolStatusHud? _instance; private static bool _missingFontLogged; private CanvasGroup? _canvasGroup; private TextMeshProUGUI? _text; private RectTransform? _rectTransform; private string _areaLine = ""; private string _placementLine = ""; private string _dvergrLine = ""; private string _buildCameraLine = ""; private string _pickupLine = ""; private string _lastAreaLine = ""; private string _lastPlacementLine = ""; private string _lastDvergrLine = ""; private float _areaHideAfter = float.MinValue; private float _placementHideAfter = float.MinValue; private float _dvergrHideAfter = float.MinValue; private float _buildCameraHideAfter = float.MinValue; private float _pickupHideAfter = float.MinValue; public static void Show(string title, string size, float yaw, Vector3 horizontalOffset, float heightOffset) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) ShowPlacementLine(horizontalOffset, heightOffset, yaw, FormatAreaSize(size)); } public static void ShowBlueprint(string title, float yaw, Vector3 horizontalOffset, float heightOffset) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) ShowPlacementLine(horizontalOffset, heightOffset, yaw); } public static void ShowOffset(string title, Vector3 horizontalOffset, float heightOffset, float xAxisRotation = 0f, float zAxisRotation = 0f) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) float degree = ((Mathf.Abs(xAxisRotation) >= 0.001f) ? xAxisRotation : zAxisRotation); ShowPlacementLine(horizontalOffset, heightOffset, degree); } public static void ShowDefaultPlacement(Vector3 horizontalOffset, float heightOffset, float yaw, float xAxisRotation, float zAxisRotation, bool keepVisible) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Hud.instance == (Object)null)) { EnsureInstance(); _instance?.SetAreaLine("", keepVisible: false); _instance?.SetPlacementLine(FormatDefaultPlacementLine(horizontalOffset, heightOffset, yaw, xAxisRotation, zAxisRotation), 1f, keepVisible); } } public static void ShowDvergrCirclet(bool lightOn, float intensityMultiplier, float rangeMultiplier) { if (!((Object)(object)Hud.instance == (Object)null)) { EnsureInstance(); _instance?.SetDvergrLine(HomesteadLocalization.Format("hs_dvergr_hud", lightOn ? HomesteadLocalization.Text("hs_common_on") : HomesteadLocalization.Text("hs_common_off"), rangeMultiplier * 100f, intensityMultiplier * 100f), 1f); } } public static void ShowCameraPickupBlocked(string message) { if (!((Object)(object)Hud.instance == (Object)null)) { EnsureInstance(); _instance?.SetPickupLine(message, 0.35f); } } public static void ShowBuildCameraDistance(float currentDistance, float maxDistance, string detail) { if (!((Object)(object)Hud.instance == (Object)null)) { EnsureInstance(); string text = (string.IsNullOrWhiteSpace(detail) ? "" : (" = " + detail)); _instance?.SetBuildCameraLine(HomesteadLocalization.Format("hs_build_camera_distance_hud", FormatMeters(currentDistance), FormatMeters(maxDistance), text)); } } public static void HideBuildCameraDistance() { if (!((Object)(object)_instance == (Object)null)) { _instance._buildCameraLine = ""; _instance._buildCameraHideAfter = float.MinValue; _instance.RefreshText(); } } public static void Hide() { ClearPlacementLine(force: true); } public static void HideDefaultPlacement() { ClearPlacementLine(force: false); } private static void ClearPlacementLine(bool force) { if (((!ZoneBlueprintSaveTool.IsActive && !ZoneAreaDismantleTool.IsActive && !ZoneBlueprintPlacementTool.IsActive) || force) && !((Object)(object)_instance == (Object)null)) { _instance._placementLine = ""; _instance._areaLine = ""; _instance._lastPlacementLine = ""; _instance._lastAreaLine = ""; _instance._placementHideAfter = float.MinValue; _instance._areaHideAfter = float.MinValue; _instance.RefreshText(); } } private static void ShowPlacementLine(Vector3 horizontalOffset, float heightOffset, float degree, string areaSize = "") { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Hud.instance == (Object)null)) { bool flag = !string.IsNullOrWhiteSpace(areaSize); bool keepVisible = flag || HasNonZeroPlacementValue(horizontalOffset, heightOffset, degree); EnsureInstance(); _instance?.SetAreaLine(flag ? areaSize : "", keepVisible); _instance?.SetPlacementLine("X " + Format(horizontalOffset.x) + " | Y " + Format(heightOffset) + " | Z " + Format(horizontalOffset.z) + " | θ " + FormatDegree(degree), 1f, keepVisible); } } private static void EnsureInstance() { if ((Object)(object)Hud.instance == (Object)null) { return; } if ((Object)(object)_instance != (Object)null && Object.op_Implicit((Object)(object)_instance)) { _instance.EnsureElements(); return; } _instance = ((Component)Hud.instance).GetComponent(); if ((Object)(object)_instance == (Object)null) { _instance = ((Component)Hud.instance).gameObject.AddComponent(); } _instance.EnsureElements(); } private void Update() { bool flag = false; if (!string.IsNullOrEmpty(_areaLine) && Time.unscaledTime > _areaHideAfter) { _areaLine = ""; flag = true; } if (!string.IsNullOrEmpty(_placementLine) && Time.unscaledTime > _placementHideAfter) { _placementLine = ""; flag = true; } if (!string.IsNullOrEmpty(_dvergrLine) && Time.unscaledTime > _dvergrHideAfter) { _dvergrLine = ""; flag = true; } if (!string.IsNullOrEmpty(_buildCameraLine) && Time.unscaledTime > _buildCameraHideAfter) { _buildCameraLine = ""; flag = true; } if (!string.IsNullOrEmpty(_pickupLine) && Time.unscaledTime > _pickupHideAfter) { _pickupLine = ""; flag = true; } if (flag) { RefreshText(); } ApplyLayout(); } private void SetAreaLine(string line, bool keepVisible) { EnsureElements(); if (!CanShow()) { return; } if (string.IsNullOrWhiteSpace(line)) { if (!string.IsNullOrEmpty(_areaLine) || !string.IsNullOrEmpty(_lastAreaLine)) { _areaLine = ""; _lastAreaLine = ""; _areaHideAfter = float.MinValue; RefreshText(); } } else if (!string.Equals(_lastAreaLine, line, StringComparison.Ordinal)) { _lastAreaLine = line; _areaLine = line; _areaHideAfter = (keepVisible ? float.PositiveInfinity : (Time.unscaledTime + 1f)); RefreshText(); } else if (keepVisible && !float.IsPositiveInfinity(_areaHideAfter)) { _areaLine = line; _areaHideAfter = float.PositiveInfinity; RefreshText(); } } private void SetPlacementLine(string line, float visibleSeconds, bool keepVisible) { EnsureElements(); if (CanShow()) { if (!string.Equals(_lastPlacementLine, line, StringComparison.Ordinal)) { _lastPlacementLine = line; _placementLine = line; _placementHideAfter = (keepVisible ? float.PositiveInfinity : (Time.unscaledTime + visibleSeconds)); RefreshText(); } else if (keepVisible && !float.IsPositiveInfinity(_placementHideAfter)) { _placementLine = line; _placementHideAfter = float.PositiveInfinity; RefreshText(); } } } private void SetDvergrLine(string line, float visibleSeconds) { EnsureElements(); if (CanShow()) { if (!string.Equals(_lastDvergrLine, line, StringComparison.Ordinal)) { _lastDvergrLine = line; _dvergrLine = line; _dvergrHideAfter = Time.unscaledTime + visibleSeconds; RefreshText(); } else if (Time.unscaledTime <= _dvergrHideAfter) { RefreshText(); } } } private void SetPickupLine(string line, float visibleSeconds) { EnsureElements(); if (CanShow()) { _pickupLine = line; _pickupHideAfter = Time.unscaledTime + visibleSeconds; RefreshText(); } } private void SetBuildCameraLine(string line) { EnsureElements(); if (CanShow()) { _buildCameraLine = line; _buildCameraHideAfter = float.PositiveInfinity; RefreshText(); } } private bool CanShow() { if ((Object)(object)_text != (Object)null && (Object)(object)_canvasGroup != (Object)null) { return (Object)(object)_rectTransform != (Object)null; } return false; } private void RefreshText() { if (CanShow()) { PruneExpiredLines(); string[] source = new string[5] { _areaLine, _placementLine, _dvergrLine, _buildCameraLine, _pickupLine }; ((TMP_Text)_text).text = string.Join("\n", source.Where((string line) => !string.IsNullOrEmpty(line))); _canvasGroup.alpha = (string.IsNullOrEmpty(((TMP_Text)_text).text) ? 0f : 1f); ((TMP_Text)_text).transform.SetAsLastSibling(); ApplyLayout(); } } private void EnsureElements() { //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Expected O, but got Unknown //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Hud.instance == (Object)null) { return; } TextMeshProUGUI val = FindHudTextTemplate(); if ((Object)(object)((val != null) ? ((TMP_Text)val).font : null) == (Object)null) { LogMissingFontOnce(); return; } if ((Object)(object)_text == (Object)null || (Object)(object)_canvasGroup == (Object)null || (Object)(object)_rectTransform == (Object)null) { _text = Object.Instantiate(val, ((Component)Hud.instance).transform, false); GameObject gameObject = ((Component)_text).gameObject; ((Object)gameObject).name = "HomesteadUnifiedStatusHud"; gameObject.SetActive(true); gameObject.transform.SetAsLastSibling(); _rectTransform = (RectTransform)gameObject.transform; _rectTransform.anchorMin = new Vector2(0f, 1f); _rectTransform.anchorMax = new Vector2(0f, 1f); _rectTransform.pivot = new Vector2(0f, 1f); _canvasGroup = gameObject.GetComponent(); if ((Object)(object)_canvasGroup == (Object)null) { _canvasGroup = gameObject.AddComponent(); } _canvasGroup.alpha = 0f; ((Graphic)_text).color = new Color(1f, 0.86f, 0.45f, 1f); ((TMP_Text)_text).alignment = (TextAlignmentOptions)513; ((TMP_Text)_text).enableAutoSizing = false; ((TMP_Text)_text).textWrappingMode = (TextWrappingModes)0; ((TMP_Text)_text).overflowMode = (TextOverflowModes)0; ((TMP_Text)_text).margin = Vector4.zero; ((Graphic)_text).raycastTarget = false; ((TMP_Text)_text).text = string.Empty; } if (!((Object)(object)_text == (Object)null)) { ((TMP_Text)_text).font = ((TMP_Text)val).font; if ((Object)(object)((TMP_Text)val).fontSharedMaterial != (Object)null) { ((TMP_Text)_text).fontSharedMaterial = ((TMP_Text)val).fontSharedMaterial; } ApplyLayout(); } } private void ApplyLayout() { //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) if (!((Object)(object)_rectTransform == (Object)null) && !((Object)(object)_text == (Object)null)) { _rectTransform.anchoredPosition = ClientConfig.StatusHudPosition; ((TMP_Text)_text).fontSize = ClientConfig.StatusHudFontSize; _rectTransform.sizeDelta = CalculateHudSize(((TMP_Text)_text).fontSize); } } private static TextMeshProUGUI? FindHudTextTemplate() { TMP_Text obj = Hud.instance?.m_buildSelection; TextMeshProUGUI val = (TextMeshProUGUI)(object)((obj is TextMeshProUGUI) ? obj : null); if ((Object)(object)((val != null) ? ((TMP_Text)val).font : null) != (Object)null) { return val; } Hud instance = Hud.instance; if (instance == null) { return null; } return ((IEnumerable)((Component)instance).GetComponentsInChildren(true)).FirstOrDefault((Func)((TextMeshProUGUI text) => (Object)(object)text != (Object)null && (Object)(object)((TMP_Text)text).font != (Object)null)); } private static void LogMissingFontOnce() { if (!_missingFontLogged) { _missingFontLogged = true; HomesteadPlugin.HomesteadLogger.LogWarning((object)"Homestead status HUD could not find a TextMeshPro font asset."); } } private static Vector2 CalculateHudSize(float fontSize) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) float num = fontSize * 5f * 1.45f + 12f; return new Vector2(Mathf.Clamp(fontSize * 34f, 220f, 1800f), Mathf.Clamp(num, 40f, 420f)); } private static string Format(float value) { return value.ToString("+0.##;-0.##;0", CultureInfo.InvariantCulture); } private static string FormatDegree(float value) { return Mathf.RoundToInt(value).ToString(CultureInfo.InvariantCulture); } private static string FormatMeters(float value) { return $"{Mathf.RoundToInt(value)}m"; } private static string FormatDefaultPlacementLine(Vector3 horizontalOffset, float heightOffset, float yaw, float xAxisRotation, float zAxisRotation) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) string text = "X " + Format(horizontalOffset.x) + " | Y " + Format(heightOffset) + " | Z " + Format(horizontalOffset.z) + " | θ " + FormatDegree(yaw); if (Mathf.Abs(xAxisRotation) >= 0.001f) { text = text + " | RX " + FormatDegree(xAxisRotation); } if (Mathf.Abs(zAxisRotation) >= 0.001f) { text = text + " | RZ " + FormatDegree(zAxisRotation); } return text; } private void PruneExpiredLines() { float unscaledTime = Time.unscaledTime; if (!string.IsNullOrEmpty(_areaLine) && unscaledTime > _areaHideAfter) { _areaLine = ""; } if (!string.IsNullOrEmpty(_placementLine) && unscaledTime > _placementHideAfter) { _placementLine = ""; } if (!string.IsNullOrEmpty(_dvergrLine) && unscaledTime > _dvergrHideAfter) { _dvergrLine = ""; } if (!string.IsNullOrEmpty(_buildCameraLine) && unscaledTime > _buildCameraHideAfter) { _buildCameraLine = ""; } if (!string.IsNullOrEmpty(_pickupLine) && unscaledTime > _pickupHideAfter) { _pickupLine = ""; } } private static bool HasNonZeroPlacementValue(Vector3 horizontalOffset, float heightOffset, float degree) { //IL_0000: 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) if (!(Mathf.Abs(horizontalOffset.x) > 0.001f) && !(Mathf.Abs(heightOffset) > 0.001f) && !(Mathf.Abs(horizontalOffset.z) > 0.001f)) { return Mathf.Abs(degree) > 0.001f; } return true; } private static string FormatAreaSize(string size) { string text = (size ?? "").Trim(); if (text.EndsWith("m", StringComparison.OrdinalIgnoreCase)) { string[] array = text.Substring(0, text.Length - 1).Split(new char[1] { 'x' }); if (array.Length == 2 && !string.IsNullOrWhiteSpace(array[0]) && !string.IsNullOrWhiteSpace(array[1])) { return array[0].Trim() + "m | " + array[1].Trim() + "m"; } } return text; } } internal sealed class ZoneAreaTargetOverlay { private readonly struct OverlayCandidate { public ZDO Zdo { get; } public float BoundaryPriority { get; } public OverlayCandidate(ZDO zdo, float boundaryPriority) { Zdo = zdo; BoundaryPriority = boundaryPriority; } } private const int MaxHighlightedTargets = 1600; private const int MaxCandidateInspections = 2500; public const float BoundaryCandidatePadding = 24f; private static readonly Color IncludedBoundaryColor = new Color(1f, 0.9f, 0.12f, 1f); private static readonly Color ExcludedBoundaryColor = new Color(1f, 0.45f, 0.05f, 1f); private readonly Dictionary _highlighted = new Dictionary(); private readonly Dictionary _nextHighlighted = new Dictionary(); private readonly List _candidateBuffer = new List(); public ZoneAreaTargetOverlay(Transform parent, string objectPrefix) { } public void Draw(IReadOnlyList candidates, ZoneAreaSelection selection) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004d: 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_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) _nextHighlighted.Clear(); _candidateBuffer.Clear(); float num = selection.HalfDiagonal + 24f; float num2 = num * num; for (int i = 0; i < candidates.Count; i++) { ZDO val = candidates[i]; if (val != null && val.IsValid()) { Vector3 position = val.GetPosition(); if (!(HorizontalDistanceSqr(position, selection.Center) > num2) && TryEstimateBoundaryPriority(position, selection, out var boundaryPriority)) { _candidateBuffer.Add(new OverlayCandidate(val, boundaryPriority)); } } } _candidateBuffer.Sort((OverlayCandidate left, OverlayCandidate right) => left.BoundaryPriority.CompareTo(right.BoundaryPriority)); int num3 = 0; int num4 = 0; foreach (OverlayCandidate item in _candidateBuffer) { if (num3 >= 1600 || num4 >= 2500) { break; } num4++; ZDO zdo = item.Zdo; if (TryClassifyBoundary(zdo, selection, out var included) && TryGetWearNTear(zdo, out WearNTear wearNTear)) { _nextHighlighted[zdo.m_uid] = included; if (!_highlighted.TryGetValue(zdo.m_uid, out var value) || value != included) { ApplyTint(wearNTear, included ? IncludedBoundaryColor : ExcludedBoundaryColor); } num3++; } } _candidateBuffer.Clear(); foreach (KeyValuePair item2 in _highlighted) { if (!_nextHighlighted.ContainsKey(item2.Key)) { ResetTint(item2.Key); } } _highlighted.Clear(); foreach (KeyValuePair item3 in _nextHighlighted) { _highlighted[item3.Key] = item3.Value; } } public void Clear() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) foreach (ZDOID key in _highlighted.Keys) { ResetTint(key); } _highlighted.Clear(); _nextHighlighted.Clear(); _candidateBuffer.Clear(); } public void Destroy() { Clear(); } private static bool TryGetWearNTear(ZDO zdo, out WearNTear wearNTear) { wearNTear = null; if (zdo == null || !zdo.IsValid() || (Object)(object)ZNetScene.instance == (Object)null) { return false; } ZNetView val = ZNetScene.instance.FindInstance(zdo); if ((Object)(object)val == (Object)null) { return false; } wearNTear = ((Component)val).GetComponent(); return (Object)(object)wearNTear != (Object)null; } public static void CollectNearbyZdos(ZoneAreaSelection selection, List buffer) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) buffer.Clear(); if (ZDOMan.instance != null) { float num = (((Object)(object)ZoneSystem.instance != (Object)null) ? ZoneSystem.instance.m_zoneSize : 64f); int num2 = Mathf.CeilToInt((selection.HalfDiagonal + 24f) / Mathf.Max(1f, num)); ZDOMan.instance.FindSectorObjects(ZoneSystem.GetZone(selection.Center), num2, 0, buffer, (List)null); } } private static bool TryClassifyBoundary(ZDO zdo, ZoneAreaSelection selection, out bool included) { //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_0024: 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_003c: 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_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) included = false; if (zdo == null || !zdo.IsValid() || !ZoneBlueprintCommands.TryReadWearNTear(zdo, out GameObject prefab)) { return false; } Vector3 position = zdo.GetPosition(); included = selection.Contains(position); float num = selection.HalfDiagonal + 24f; if (HorizontalDistanceSqr(position, selection.Center) > num * num) { return false; } Vector3 vec = zdo.GetVec3(ZDOVars.s_scaleHash, prefab.transform.localScale); if (!HomesteadTerrainSupport.TryGetWearNTearBounds(prefab, position, zdo.GetRotation(), vec, out var bounds)) { return false; } return selection.IntersectsBoundary(bounds); } private static void ApplyTint(WearNTear wearNTear, Color color) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0037: 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) if ((Object)(object)MaterialMan.instance == (Object)null) { wearNTear.Highlight(); return; } GameObject gameObject = ((Component)wearNTear).gameObject; MaterialMan.instance.SetValue(gameObject, ShaderProps._Color, color); MaterialMan.instance.SetValue(gameObject, ShaderProps._EmissionColor, color * 0.35f); } private static void ResetTint(WearNTear wearNTear) { if ((Object)(object)MaterialMan.instance == (Object)null) { wearNTear.ResetHighlight(); return; } GameObject gameObject = ((Component)wearNTear).gameObject; MaterialMan.instance.ResetValue(gameObject, ShaderProps._Color); MaterialMan.instance.ResetValue(gameObject, ShaderProps._EmissionColor); } private static void ResetTint(ZDOID id) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.FindInstance(id) : null); WearNTear val2 = (((Object)(object)val != (Object)null) ? val.GetComponent() : null); if ((Object)(object)val2 != (Object)null) { ResetTint(val2); } } private static float HorizontalDistanceSqr(Vector3 a, Vector3 b) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) float num = a.x - b.x; float num2 = a.z - b.z; return num * num + num2 * num2; } private static bool TryEstimateBoundaryPriority(Vector3 position, ZoneAreaSelection selection, out float boundaryPriority) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: 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_003a: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Quaternion.Inverse(selection.Rotation) * (position - selection.Center); float num = selection.Width * 0.5f; float num2 = selection.Depth * 0.5f; float num3 = Mathf.Abs(val.x); float num4 = Mathf.Abs(val.z); float num5 = Mathf.Abs(num3 - num); float num6 = Mathf.Abs(num4 - num2); float num7 = Mathf.Max(num3 - num, 0f); float num8 = Mathf.Max(num4 - num2, 0f); float num9 = Mathf.Min(num - num3, num2 - num4); boundaryPriority = Mathf.Min(num5, num6); if (num7 <= 24f && num8 <= 24f) { return num9 <= 24f; } return false; } } [HarmonyPatch] internal static class ZoneBuildKeyHints { private sealed class HintWidgets { public TextMeshProUGUI? Label; public LayoutElement? Layout; public Transform? Key0Root; public Transform? Key1Root; public TextMeshProUGUI? Key0Text; public TextMeshProUGUI? Key1Text; public bool LastVisible; public string LastLabel = ""; public string LastKey0 = ""; public string LastKey1 = ""; public float LastPreferredWidth; } private const string TemplatePath = "BuildHints/Keyboard/AltPlace"; private const string FallbackTemplatePath = "BuildHints/Keyboard/Snap"; private const float BuildCameraConditionRefreshInterval = 0.35f; private static GameObject? _offsetHint; private static GameObject? _gridHint; private static GameObject? _toolHint; private static GameObject? _buildCameraHint; private static readonly Dictionary HintWidgetCache = new Dictionary(); private static Player? _cachedBuildCameraConditionPlayer; private static float _nextBuildCameraConditionRefresh; private static string _cachedBuildCameraCondition = ""; [HarmonyPostfix] [HarmonyPatch(typeof(KeyHints), "Awake")] private static void KeyHintsAwakePostfix(KeyHints __instance) { EnsureHints(__instance); UpdateHints(__instance); } [HarmonyPostfix] [HarmonyPatch(typeof(KeyHints), "UpdateHints")] private static void KeyHintsUpdateHintsPostfix(KeyHints __instance) { UpdateHints(__instance); } private static void EnsureHints(KeyHints keyHints) { if (Object.op_Implicit((Object)(object)keyHints) && !Object.op_Implicit((Object)(object)_offsetHint)) { Transform val = ((Component)keyHints).transform.Find("BuildHints/Keyboard/AltPlace") ?? ((Component)keyHints).transform.Find("BuildHints/Keyboard/Snap"); if ((Object)(object)val == (Object)null) { HomesteadPlugin.HomesteadLogger.LogDebug((object)"Homestead key hints: build hint template was not found."); return; } Transform parent = val.parent; _offsetHint = CreateHint(val, parent, "HomesteadOffsetHint", 0); _gridHint = CreateHint(val, parent, "HomesteadGridHint", 1); _toolHint = CreateHint(val, parent, "HomesteadToolHint", 2); _buildCameraHint = CreateHint(val, parent, "HomesteadBuildCameraHint", 3); HintWidgetCache.Clear(); } } private static GameObject CreateHint(Transform template, Transform parent, string name, int siblingIndex) { GameObject obj = Object.Instantiate(((Component)template).gameObject, parent); ((Object)obj).name = name; obj.transform.SetSiblingIndex(Mathf.Clamp(siblingIndex, 0, parent.childCount - 1)); EnsureKeyCount(obj, 2); return obj; } private static void UpdateHints(KeyHints keyHints) { //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0170: 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_0194: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Invalid comparison between Unknown and I4 //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02bd: Unknown result type (might be due to invalid IL or missing references) EnsureHints(keyHints); if ((Object)(object)_offsetHint == (Object)null || (Object)(object)_gridHint == (Object)null || (Object)(object)_toolHint == (Object)null || (Object)(object)_buildCameraHint == (Object)null) { return; } Player localPlayer = Player.m_localPlayer; bool flag = keyHints.m_keyHintsEnabled && (Object)(object)localPlayer != (Object)null && ((Character)localPlayer).InPlaceMode() && !ZInput.IsGamepadActive(); if (ZoneBlueprintSaveToolMenu.IsStoreToolSelected(localPlayer)) { HideHomesteadHints(); return; } bool flag2 = ZoneBlueprintSaveTool.IsActive || ZoneAreaDismantleTool.IsActive || ZoneBlueprintPlacementTool.IsActive; string text = ""; if (flag && (Object)(object)localPlayer != (Object)null && ZoneBuildCamera.IsEnabled()) { text = GetCachedBuildCameraConditionText(localPlayer); } GetPlacementAdjustHintKeys(out string key, out string key2, out float preferredWidth); SetHint(_offsetHint, flag && (PlacementControlConfig.PlacementAdjustEnabled || flag2), HomesteadLocalization.Text("hs_keyhint_adjust_offset"), key, key2, preferredWidth); GameObject? gridHint = _gridHint; KeyboardShortcut val; int visible; if (flag) { val = PlacementControlConfig.GridSnapToggleHotkey; if ((int)((KeyboardShortcut)(ref val)).MainKey != 0) { visible = ((!flag2) ? 1 : 0); goto IL_00fc; } } visible = 0; goto IL_00fc; IL_00fc: SetHint(gridHint, (byte)visible != 0, ZoneGridSnap.IsActive ? HomesteadLocalization.Text("hs_keyhint_grid_on") : HomesteadLocalization.Text("hs_keyhint_grid_off"), FormatShortcut(PlacementControlConfig.GridSnapToggleHotkey), "", 102f); if (ZoneBlueprintSaveTool.IsActive || ZoneAreaDismantleTool.IsActive) { string text2 = (string.IsNullOrWhiteSpace(PlacementControlConfig.AreaUniformScaleInputLabel) ? "" : ("+" + PlacementControlConfig.PlacementAdjustModifierLabel)); val = BlueprintConfig.AreaToolDepthModifierKey; string text3 = (((int)((KeyboardShortcut)(ref val)).MainKey == 0) ? "" : ("+" + BlueprintConfig.AreaToolDepthModifierLabel)); val = BlueprintConfig.AreaToolWidthModifierKey; string text4 = (((int)((KeyboardShortcut)(ref val)).MainKey == 0) ? "" : ("+" + BlueprintConfig.AreaToolWidthModifierLabel)); string key3 = string.Join("/", new string[3] { text2, text3, text4 }.Where((string value) => !string.IsNullOrWhiteSpace(value))); SetHint(_toolHint, flag, HomesteadLocalization.Text("hs_keyhint_area_shape"), "Wheel", key3, 166f); } else if (ZoneBlueprintPlacementTool.IsActive) { SetHint(_toolHint, flag, HomesteadLocalization.Text("hs_keyhint_blueprint_place"), "Wheel", "Mouse0", 128f); } else { _toolHint.SetActive(false); } int num; if (ZoneBuildCamera.InBuildMode()) { val = BuildCameraConfig.LookAtLockHotkey; num = (((int)((KeyboardShortcut)(ref val)).MainKey > 0) ? 1 : 0); } else { num = 0; } bool flag3 = (byte)num != 0; SetHint(_buildCameraHint, flag && ZoneBuildCamera.IsEnabled(), flag3 ? HomesteadLocalization.Text("hs_keyhint_build_camera_lock") : HomesteadLocalization.Format("hs_keyhint_build_camera", text), FormatShortcut(BuildCameraConfig.ToggleHotkey), flag3 ? FormatShortcut(BuildCameraConfig.LookAtLockHotkey) : "", flag3 ? 190f : 160f); } private static void HideHomesteadHints() { SetActiveIfChanged(_offsetHint, active: false); SetActiveIfChanged(_gridHint, active: false); SetActiveIfChanged(_toolHint, active: false); SetActiveIfChanged(_buildCameraHint, active: false); } private static void SetHint(GameObject hint, bool visible, string label, string key0, string key1, float preferredTextWidth) { HintWidgets hintWidgets = GetHintWidgets(hint); SetActiveIfChanged(hint, visible); hintWidgets.LastVisible = visible; if (visible) { SetText(hintWidgets, label, preferredTextWidth); SetKeyText(hintWidgets.Key0Root, hintWidgets.Key0Text, key0, ref hintWidgets.LastKey0); SetKeyText(hintWidgets.Key1Root, hintWidgets.Key1Text, key1, ref hintWidgets.LastKey1); } } private static void SetText(HintWidgets widgets, string text, float preferredWidth) { TextMeshProUGUI label = widgets.Label; if ((Object)(object)label != (Object)null && !string.Equals(widgets.LastLabel, text, StringComparison.Ordinal)) { Localization instance = Localization.instance; if (instance != null) { instance.RemoveTextFromCache((TMP_Text)(object)label); } ((TMP_Text)label).text = text; widgets.LastLabel = text; } LayoutElement layout = widgets.Layout; if ((Object)(object)layout != (Object)null && Math.Abs(widgets.LastPreferredWidth - preferredWidth) > 0.1f) { layout.preferredWidth = preferredWidth; widgets.LastPreferredWidth = preferredWidth; } } private static void SetKeyText(Transform? keyRoot, TextMeshProUGUI? label, string text, ref string lastText) { if ((Object)(object)keyRoot == (Object)null) { return; } SetActiveIfChanged(((Component)keyRoot).gameObject, !string.IsNullOrWhiteSpace(text)); if ((Object)(object)label != (Object)null && !string.Equals(lastText, text, StringComparison.Ordinal)) { Localization instance = Localization.instance; if (instance != null) { instance.RemoveTextFromCache((TMP_Text)(object)label); } ((TMP_Text)label).text = text; lastText = text; } } private static HintWidgets GetHintWidgets(GameObject hint) { int instanceID = ((Object)hint).GetInstanceID(); if (HintWidgetCache.TryGetValue(instanceID, out HintWidgets value)) { return value; } TextMeshProUGUI val = FindLabelText(hint); Transform keyRoot = GetKeyRoot(hint, 0); Transform keyRoot2 = GetKeyRoot(hint, 1); LayoutElement val2 = default(LayoutElement); value = new HintWidgets { Label = val, Layout = (((Object)(object)val != (Object)null && ((Component)val).TryGetComponent(ref val2)) ? val2 : null), Key0Root = keyRoot, Key1Root = keyRoot2, Key0Text = (((Object)(object)keyRoot != (Object)null) ? FindKeyText(keyRoot) : null), Key1Text = (((Object)(object)keyRoot2 != (Object)null) ? FindKeyText(keyRoot2) : null), LastVisible = hint.activeSelf, LastPreferredWidth = float.NaN }; HintWidgetCache[instanceID] = value; return value; } private static void SetActiveIfChanged(GameObject? target, bool active) { if ((Object)(object)target != (Object)null && Object.op_Implicit((Object)(object)target) && target.activeSelf != active) { target.SetActive(active); } } private static string GetCachedBuildCameraConditionText(Player player) { if ((Object)(object)_cachedBuildCameraConditionPlayer != (Object)(object)player || Time.unscaledTime >= _nextBuildCameraConditionRefresh) { _cachedBuildCameraConditionPlayer = player; _cachedBuildCameraCondition = ZoneBuildCamera.GetKeyHintConditionText(player); _nextBuildCameraConditionRefresh = Time.unscaledTime + 0.35f; } return _cachedBuildCameraCondition; } private static Transform? GetKeyRoot(GameObject hint, int index) { List list = FindKeyRoots(hint); if (index < 0 || index >= list.Count) { return null; } return list[index]; } private static void EnsureKeyCount(GameObject hint, int count) { Transform keyRoot = GetKeyRoot(hint, 0); if ((Object)(object)keyRoot == (Object)null) { return; } for (int i = 1; i < count; i++) { if (!((Object)(object)GetKeyRoot(hint, i) != (Object)null)) { ((Object)Object.Instantiate(((Component)keyRoot).gameObject, keyRoot.parent).transform).name = $"key_bkg ({i})"; } } } private static TextMeshProUGUI? FindLabelText(GameObject hint) { TextMeshProUGUI[] componentsInChildren = hint.GetComponentsInChildren(true); return ((IEnumerable)componentsInChildren).FirstOrDefault((Func)((TextMeshProUGUI text) => !IsKeyText(((TMP_Text)text).transform))) ?? componentsInChildren.OrderByDescending((TextMeshProUGUI text) => ((TMP_Text)text).fontSize).FirstOrDefault(); } private static TextMeshProUGUI? FindKeyText(Transform keyRoot) { return ((IEnumerable)((Component)keyRoot).GetComponentsInChildren(true)).FirstOrDefault((Func)((TextMeshProUGUI text) => IsKeyText(((TMP_Text)text).transform))) ?? ((Component)keyRoot).GetComponentInChildren(true); } private static List FindKeyRoots(GameObject hint) { GameObject hint2 = hint; List list = (from transform in hint2.GetComponentsInChildren(true) where (Object)(object)transform != (Object)(object)hint2.transform && IsKeyRoot(transform) orderby transform.GetSiblingIndex() select transform).ToList(); if (list.Count > 0) { return list; } return (from transform in (from text in hint2.GetComponentsInChildren(true) where IsKeyText(((TMP_Text)text).transform) select ((TMP_Text)text).transform.parent ?? ((TMP_Text)text).transform).Distinct() orderby transform.GetSiblingIndex() select transform).ToList(); } private static bool IsKeyRoot(Transform transform) { string name = ((Object)transform).name; if (name.IndexOf("key_bkg", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("keybkg", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("key background", StringComparison.OrdinalIgnoreCase) < 0) { return name.Equals("key_bkg", StringComparison.OrdinalIgnoreCase); } return true; } private static bool IsKeyText(Transform transform) { if (((Object)transform).name.Equals("Key", StringComparison.OrdinalIgnoreCase)) { return true; } Transform parent = transform.parent; while ((Object)(object)parent != (Object)null) { if (IsKeyRoot(parent)) { return true; } parent = parent.parent; } return false; } private static string FormatShortcut(KeyboardShortcut shortcut) { string text = ((object)(KeyboardShortcut)(ref shortcut)).ToString(); if (string.IsNullOrWhiteSpace(text)) { return HomesteadLocalization.Text("hs_common_unbound"); } return text.Replace(" + ", "+"); } private static void GetPlacementAdjustHintKeys(out string key0, out string key1, out float preferredWidth) { //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_0008: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut placementAdjustModifierKey = PlacementControlConfig.PlacementAdjustModifierKey; if ((int)((KeyboardShortcut)(ref placementAdjustModifierKey)).MainKey == 0) { key0 = "Arrows"; key1 = "PgUp/PgDn"; preferredWidth = 104f; } else { key0 = PlacementControlConfig.PlacementAdjustModifierLabel; key1 = "+Arrows/+PgUpDn"; preferredWidth = 128f; } } } internal static class ZoneBuildCamera { internal struct EyeOriginOverrideState { public bool Changed; public Vector3 OriginalEyePosition; } private struct BuildCameraView { public float Yaw; public float Pitch; } private struct NearbyCraftingStation { public Vector3 Position; public float Distance; public float RangeBuild; } private const string ExternalBuildCameraGuid = "Azumatt.BuildCameraCHE"; private static readonly Dictionary InBuildModeByPlayer = new Dictionary(); private static readonly Collider[] PickupOverlapBuffer = (Collider[])(object)new Collider[128]; private static readonly Collider[] PickupHudOverlapBuffer = (Collider[])(object)new Collider[128]; private static ManualLogSource Log = null; private static BuildCameraView _viewDirection; private static bool _externalBuildCameraWarningLogged; private static bool _showPickupBlockedHud; private static float _nextPickupHudRefreshTime; private static float _nextPickupCandidateScanTime; private static bool _cachedPickupCandidate; private static float _nextMessageTime; private static Transform? _lookAtTarget; private static Vector3 _lookAtTargetOffset = Vector3.zero; internal static void Initialize(ManualLogSource logger) { Log = logger; } internal static void Shutdown() { DisableBuildMode(); InBuildModeByPlayer.Clear(); _showPickupBlockedHud = false; ZoneBuildCameraDvergerLight.CleanupAll(); } internal static void Update() { if (!(Time.time < _nextPickupHudRefreshTime)) { _nextPickupHudRefreshTime = Time.time + 0.2f; _showPickupBlockedHud = ShouldShowPickupBlockedHud(); if (_showPickupBlockedHud) { ZoneAreaToolStatusHud.ShowCameraPickupBlocked(FormatWithMinimumComfort(LocalizeText("hs_build_camera_pickup_blocked_hud", "Pickup blocked: Be cozy to use build camera item pickup (Comfort {0})"))); } } } internal static bool IsEnabled() { if (!BuildCameraConfig.Enabled) { return false; } if (!Chainloader.PluginInfos.ContainsKey("Azumatt.BuildCameraCHE")) { return true; } if (!_externalBuildCameraWarningLogged) { _externalBuildCameraWarningLogged = true; Log.LogWarning((object)"Standalone BuildCameraCHE is loaded. Homestead built-in build camera is disabled to avoid duplicate camera patches."); } return false; } internal static bool IsLocalPlayer(Player player) { if (Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return (Object)(object)player == (Object)(object)Player.m_localPlayer; } return false; } internal static bool InBuildMode() { Player localPlayer = Player.m_localPlayer; bool value = default(bool); return IsEnabled() && Object.op_Implicit((Object)(object)localPlayer) && InBuildModeByPlayer.TryGetValue(localPlayer, out value) && value; } internal static bool EnableBuildMode() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (!IsEnabled() || !Object.op_Implicit((Object)(object)localPlayer)) { return false; } if (ShouldRestrictCameraEntry() && !MeetsComfortGate()) { NotifyNeedCozyForCurrentMode(); return false; } InBuildModeByPlayer[localPlayer] = true; SetViewDirectionFromRotation(((Component)((Character)localPlayer).m_eye).transform.rotation); ResetCameraSessionState(); ((Character)localPlayer).Message((MessageType)1, HomesteadLocalization.Text("hs_build_camera_enter"), 0, (Sprite)null); return true; } internal static void DisableBuildMode() { Player localPlayer = Player.m_localPlayer; if (Object.op_Implicit((Object)(object)localPlayer)) { InBuildModeByPlayer[localPlayer] = false; } _showPickupBlockedHud = false; ResetCameraSessionState(); ZoneAreaToolStatusHud.HideBuildCameraDistance(); } internal static bool ToolIsEquipped(Player player) { ItemData rightItem = ((Humanoid)player).m_rightItem; if (rightItem != null && rightItem.m_shared != null) { return Object.op_Implicit((Object)(object)rightItem.m_shared.m_buildPieces); } return false; } internal static bool ShouldDeactivateBuildMode(Player player) { if (ToolIsEquipped(player)) { if (ShouldRestrictCameraEntry()) { return !MeetsComfortGate(); } return false; } return true; } internal static bool BuildStationInRange(Player player) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) NearbyCraftingStation? nearestBuildStation = GetNearestBuildStation(GetBuildInteractionOrigin(player)); if (nearestBuildStation.HasValue) { return nearestBuildStation.Value.Distance <= nearestBuildStation.Value.RangeBuild; } return false; } internal static Vector3 GetBuildInteractionOrigin(Player player) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (!InBuildMode() || !Object.op_Implicit((Object)(object)GameCamera.instance)) { return ((Component)player).transform.position; } return ((Component)GameCamera.instance).transform.position; } internal static bool TryGetBuildCameraOrigin(out Vector3 origin) { //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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (InBuildMode() && Object.op_Implicit((Object)(object)GameCamera.instance)) { origin = ((Component)GameCamera.instance).transform.position; return true; } origin = Vector3.zero; return false; } internal static EyeOriginOverrideState BeginEyeOriginOverride(Player player) { //IL_0040: 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_0051: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)player) || !Object.op_Implicit((Object)(object)((Character)player).m_eye) || !TryGetBuildCameraOrigin(out var origin)) { return default(EyeOriginOverrideState); } EyeOriginOverrideState eyeOriginOverrideState = default(EyeOriginOverrideState); eyeOriginOverrideState.Changed = true; eyeOriginOverrideState.OriginalEyePosition = ((Character)player).m_eye.position; EyeOriginOverrideState result = eyeOriginOverrideState; ((Character)player).m_eye.position = origin; return result; } internal static void EndEyeOriginOverride(Player player, EyeOriginOverrideState state) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (state.Changed && Object.op_Implicit((Object)(object)player) && Object.op_Implicit((Object)(object)((Character)player).m_eye)) { ((Character)player).m_eye.position = state.OriginalEyePosition; } } internal static string GetKeyHintConditionText(Player player) { if (!IsEnabled() || !Object.op_Implicit((Object)(object)player)) { return ""; } if (InBuildMode()) { return HomesteadLocalization.Text("hs_build_camera_active"); } if (!ToolIsEquipped(player)) { return HomesteadLocalization.Text("hs_build_camera_need_tool"); } if (!BuildStationInRange(player)) { return HomesteadLocalization.Text("hs_build_camera_need_station"); } string text = FormatComfortProgress(); return BuildCameraConfig.RestrictionMode switch { BuildCameraRestrictionMode.CameraNeedsCoziness => MeetsComfortGate() ? HomesteadLocalization.Format("hs_build_camera_station_cozy", text) : HomesteadLocalization.Format("hs_build_camera_need_cozy", text), BuildCameraRestrictionMode.CameraPickUpNeedsCoziness => HomesteadLocalization.Format("hs_build_camera_station_pickup_cozy", text), _ => HomesteadLocalization.Text("hs_build_camera_station_ready"), }; } internal static void UpdateBuildCamera(float dt, GameCamera camera) { //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) //IL_0034: 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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_008c: 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_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer) || IsInputBlocked(blockPieceSelection: true)) { return; } UpdateLookAtLock(camera); if (((Character)localPlayer).TakeInput()) { Vector3 untransformedMovementVelocity = GetUntransformedMovementVelocity(dt); Vector3 val = ((Component)camera).transform.TransformVector(untransformedMovementVelocity); Transform transform = ((Component)camera).transform; transform.position += val * dt; StayNearAvatar(localPlayer, camera); StayAboveGround(camera); ShowDistanceHud(localPlayer, camera); Quaternion val2 = UpdateBuildCameraViewDirection(dt); if (TryGetLookAtRotation(camera, out var rotation)) { val2 = rotation; SetViewDirectionFromRotation(val2); } ((Component)camera).transform.rotation = val2; } } internal static bool IsInputBlocked(bool blockPieceSelection) { if ((!Object.op_Implicit((Object)(object)Chat.instance) || !Chat.instance.HasFocus()) && !Console.IsVisible() && !TextInput.IsVisible() && !StoreGui.IsVisible() && !InventoryGui.IsVisible() && !Menu.IsVisible() && (!Object.op_Implicit((Object)(object)TextViewer.instance) || !TextViewer.instance.IsVisible()) && !Minimap.IsOpen() && !Hud.InRadial() && (!blockPieceSelection || !Hud.IsPieceSelectionVisible()) && !PlayerCustomizaton.BarberBlocksLook() && !PlayerCustomizaton.IsBarberGuiVisible() && !UnifiedPopup.IsVisible()) { return ZNet.IsPasswordDialogShowing(); } return true; } private static void ResetCameraSessionState() { ClearLookAtLock(); } private static void UpdateLookAtLock(GameCamera camera) { //IL_0000: 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_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: 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) if (!ConfigValueHelpers.IsShortcutDown(BuildCameraConfig.LookAtLockHotkey)) { return; } if (Object.op_Implicit((Object)(object)_lookAtTarget)) { ClearLookAtLock(); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)1, HomesteadLocalization.Text("hs_build_camera_lock_off"), 0, (Sprite)null); } return; } int mask = LayerMask.GetMask(new string[8] { "Default", "static_solid", "terrain", "vehicle", "character", "piece", "character_net", "viewblock" }); RaycastHit val = default(RaycastHit); if (Physics.Raycast(((Component)camera).transform.position, ((Component)camera).transform.forward, ref val, 10000f, mask) && Object.op_Implicit((Object)(object)((RaycastHit)(ref val)).collider)) { _lookAtTarget = ((Component)((RaycastHit)(ref val)).collider).transform; _lookAtTargetOffset = _lookAtTarget.InverseTransformPoint(((RaycastHit)(ref val)).point); Player localPlayer2 = Player.m_localPlayer; if (localPlayer2 != null) { ((Character)localPlayer2).Message((MessageType)1, HomesteadLocalization.Text("hs_build_camera_lock_on"), 0, (Sprite)null); } } } private static void ClearLookAtLock() { //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) _lookAtTarget = null; _lookAtTargetOffset = Vector3.zero; } private static bool TryGetLookAtRotation(GameCamera camera, out Quaternion rotation) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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) rotation = ((Component)camera).transform.rotation; if (!Object.op_Implicit((Object)(object)_lookAtTarget)) { ClearLookAtLock(); return false; } Vector3 val = _lookAtTarget.TransformPoint(_lookAtTargetOffset) - ((Component)camera).transform.position; if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { return false; } rotation = Quaternion.LookRotation(((Vector3)(ref val)).normalized, Vector3.up); return true; } internal static void AutoPickup(float dt, GameCamera camera) { //IL_0033: 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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0189: 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_0194: Unknown result type (might be due to invalid IL or missing references) //IL_019e: 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_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer) || ((Character)localPlayer).IsTeleporting() || !Player.m_enableAutoPickup || (ShouldRestrictCameraPickup() && !MeetsComfortGate())) { return; } Vector3 val = ((Component)camera).transform.position + Vector3.up; int num = Physics.OverlapSphereNonAlloc(val, BuildCameraConfig.ResourcePickupRange, PickupOverlapBuffer, localPlayer.m_autoPickupMask); Collider[] array = PickupOverlapBuffer; if (num >= PickupOverlapBuffer.Length) { array = Physics.OverlapSphere(val, BuildCameraConfig.ResourcePickupRange, localPlayer.m_autoPickupMask); num = array.Length; } for (int i = 0; i < num; i++) { Collider val2 = array[i]; if (!Object.op_Implicit((Object)(object)val2) || !Object.op_Implicit((Object)(object)val2.attachedRigidbody)) { continue; } FloatingTerrainDummy val3 = null; ItemDrop component = ((Component)val2.attachedRigidbody).GetComponent(); if ((Object)(object)component == (Object)null) { FloatingTerrainDummy component2 = ((Component)val2.attachedRigidbody).gameObject.GetComponent(); if (component2 != null && Object.op_Implicit((Object)(object)component2) && Object.op_Implicit((Object)(object)component2.m_parent)) { val3 = component2; component = ((Component)component2.m_parent).gameObject.GetComponent(); } } if (!IsPickupCandidate(localPlayer, component)) { continue; } if (!component.CanPickup(true)) { component.RequestOwn(); continue; } component.Load(); float num2 = Vector3.Distance(((Component)component).transform.position, val); if (num2 > BuildCameraConfig.ResourcePickupRange) { continue; } if (num2 < BuildCameraConfig.ResourcePickupRange) { ((Humanoid)localPlayer).Pickup(((Component)component).gameObject, true, true); continue; } Vector3 val4 = Vector3.Normalize(val - ((Component)component).transform.position) * 15f * dt; Transform transform = ((Component)component).transform; transform.position += val4; if (Object.op_Implicit((Object)(object)val3)) { Transform transform2 = ((Component)val3).transform; transform2.position += val4; } } } private static NearbyCraftingStation? GetNearestBuildStation(Vector3 position) { //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_005f: 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) NearbyCraftingStation? result = null; foreach (CraftingStation allStation in CraftingStation.m_allStations) { if (Object.op_Implicit((Object)(object)allStation)) { float num = Vector3.Distance(((Component)allStation).transform.position, position); if (!result.HasValue || !(num >= result.Value.Distance)) { NearbyCraftingStation value = default(NearbyCraftingStation); value.Position = ((Component)allStation).transform.position; value.Distance = num; value.RangeBuild = allStation.m_rangeBuild; result = value; } } } return result; } private static void StayNearAvatar(Player player, GameCamera camera) { //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_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_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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)player).transform.position; Vector3 position2 = ((Component)camera).transform.position; float maxDistanceFromAvatar = GetMaxDistanceFromAvatar(player); float num = Vector3.Distance(position2, position); if (!(num <= maxDistanceFromAvatar) && !(num <= 0.001f)) { Transform transform = ((Component)camera).transform; Vector3 val = position2 - position; transform.position = position + ((Vector3)(ref val)).normalized * maxDistanceFromAvatar; } } private static void ShowDistanceHud(Player player, GameCamera camera) { //IL_0006: 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) float currentDistance = Vector3.Distance(((Component)camera).transform.position, ((Component)player).transform.position); float maxDistanceFromAvatar = GetMaxDistanceFromAvatar(player); ZoneAreaToolStatusHud.ShowBuildCameraDistance(currentDistance, maxDistanceFromAvatar, GetDistanceDetail(player)); } private static float GetMaxDistanceFromAvatar(Player player) { if (BuildCameraConfig.DistanceMode == BuildCameraDistanceMode.Fixed) { return BuildCameraConfig.MaxDistanceFromAvatar; } int distanceComfortLevel = GetDistanceComfortLevel(player); return BuildCameraConfig.BaseDistanceFromAvatar + (float)distanceComfortLevel * BuildCameraConfig.DistancePerComfortLevel; } private static string GetDistanceDetail(Player player) { if (BuildCameraConfig.DistanceMode == BuildCameraDistanceMode.Fixed) { return "Fixed " + FormatDistanceNumber(BuildCameraConfig.MaxDistanceFromAvatar); } int distanceComfortLevel = GetDistanceComfortLevel(player); return FormatDistanceNumber(BuildCameraConfig.BaseDistanceFromAvatar) + "+" + $"{FormatDistanceNumber(BuildCameraConfig.DistancePerComfortLevel)}*{distanceComfortLevel}(Comfort)"; } private static int GetDistanceComfortLevel(Player player) { if (!Object.op_Implicit((Object)(object)player) || !IsComfortActive(player)) { return 0; } return Mathf.Max(0, player.GetComfortLevel()); } private static string FormatDistanceNumber(float value) { return value.ToString("0.##", CultureInfo.InvariantCulture); } private static void StayAboveGround(GameCamera camera) { //IL_0017: 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_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) float num = default(float); if (Object.op_Implicit((Object)(object)ZoneSystem.instance) && ZoneSystem.instance.GetGroundHeight(((Component)camera).transform.position, ref num) && ((Component)camera).transform.position.y < num) { Vector3 position = ((Component)camera).transform.position; position.y = num; ((Component)camera).transform.position = position; } } private static Quaternion UpdateBuildCameraViewDirection(float dt) { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) _viewDirection.Yaw += PlayerController.m_mouseSens * Input.GetAxis("Mouse X") + ZInput.GetJoyRightStickX(true) * 110f * dt; float num = (PlayerController.m_invertMouse ? (-1f) : 1f); float num2 = _viewDirection.Pitch - (num * (PlayerController.m_mouseSens * Input.GetAxis("Mouse Y")) - ZInput.GetJoyRightStickY(true) * 110f * dt); _viewDirection.Pitch = Mathf.Clamp(num2, -89f, 89f); return Quaternion.Euler(0f, _viewDirection.Yaw, 0f) * Quaternion.Euler(_viewDirection.Pitch, 0f, 0f); } private static void SetViewDirectionFromRotation(Quaternion rotation) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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) Vector3 eulerAngles = ((Quaternion)(ref rotation)).eulerAngles; _viewDirection.Yaw = eulerAngles.y; _viewDirection.Pitch = NormalizePitch(eulerAngles.x); } private static float NormalizePitch(float pitch) { if (pitch > 180f) { pitch -= 360f; } return Mathf.Clamp(pitch, -89f, 89f); } private static Vector3 GetUntransformedMovementVelocity(float dt) { //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_0012: 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_001d: 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_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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005a: 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_0065: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_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_010e: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Vector3.zero; if (ZInput.GetButton("Left")) { val -= Vector3.right; } if (ZInput.GetButton("Right")) { val += Vector3.right; } if (ZInput.GetButton("Forward")) { val += Vector3.forward; } if (ZInput.GetButton("Backward")) { val -= Vector3.forward; } Character.takeInputDelay = Mathf.Max(0f, Character.takeInputDelay - dt); if ((ZInput.GetButton("Jump") || ZInput.GetButton("JoyJump")) && Character.takeInputDelay <= 0f && !Hud.IsPieceSelectionVisible()) { val += Vector3.up; } if (ZInput.GetButton("Crouch") || ZInput.GetButtonPressedTimer("JoyCrouch") > 0.33f) { val -= Vector3.up; } val += Vector3.right * ZInput.GetJoyLeftStickX(false); val += -Vector3.forward * ZInput.GetJoyLeftStickY(true); val += Vector3.up * ZInput.GetJoyRTrigger(); val -= Vector3.up * ZInput.GetJoyLTrigger(); if (((Vector3)(ref val)).sqrMagnitude > 1f) { ((Vector3)(ref val)).Normalize(); } Player localPlayer = Player.m_localPlayer; float num = (ZInput.GetButton("Run") ? ((Character)localPlayer).m_runSpeed : ((Character)localPlayer).m_walkSpeed); return val * (num * BuildCameraConfig.MoveSpeedMultiplier); } private static bool ShouldRestrictCameraEntry() { return BuildCameraConfig.RestrictionMode == BuildCameraRestrictionMode.CameraNeedsCoziness; } private static bool ShouldRestrictCameraPickup() { return BuildCameraConfig.RestrictionMode == BuildCameraRestrictionMode.CameraPickUpNeedsCoziness; } private static bool MeetsComfortGate() { Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer) || localPlayer.GetComfortLevel() < BuildCameraConfig.MinimumComfortLevel) { return false; } return IsComfortActive(localPlayer); } private static bool IsComfortActive(Player player) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) SEMan sEMan = ((Character)player).GetSEMan(); if (sEMan == null) { return false; } if (sEMan.HaveStatusEffect(SEMan.s_statusEffectResting)) { return true; } bool num = sEMan.HaveStatusEffect(SEMan.s_statusEffectCampFire); bool flag = player.InShelter() || ((Character)player).IsSitting(); bool flag2 = player.IsSensed(); bool flag3 = sEMan.HaveStatusEffect(SEMan.s_statusEffectCold) || sEMan.HaveStatusEffect(SEMan.s_statusEffectFreezing); bool flag4 = sEMan.HaveStatusEffect(SEMan.s_statusEffectBurning); bool flag5 = Object.op_Implicit((Object)(object)EffectArea.IsPointInsideArea(((Component)player).transform.position, (Type)64, 1f)); bool flag6 = sEMan.HaveStatusEffect(SEMan.s_statusEffectWet) && !flag5; if (num && flag && !flag2 && !flag3 && !flag6) { return !flag4; } return false; } private static void NotifyNeedCozyForCurrentMode() { Player localPlayer = Player.m_localPlayer; if (Object.op_Implicit((Object)(object)localPlayer) && !(Time.time < _nextMessageTime)) { _nextMessageTime = Time.time + 1.5f; string text = FormatWithMinimumComfort(LocalizeText("hs_build_camera_need_cozy_center", "Be cozy to use build camera (Comfort {0})")); ((Character)localPlayer).Message((MessageType)2, text, 0, (Sprite)null); } } private static bool ShouldShowPickupBlockedHud() { if (ShouldRestrictCameraPickup() && InBuildMode() && !MeetsComfortGate() && Object.op_Implicit((Object)(object)GameCamera.instance)) { return HasNearbyPickupCandidate(); } return false; } private static bool HasNearbyPickupCandidate() { if (Time.time < _nextPickupCandidateScanTime) { return _cachedPickupCandidate; } _nextPickupCandidateScanTime = Time.time + 0.05f; _cachedPickupCandidate = HasNearbyPickupCandidateUncached(); return _cachedPickupCandidate; } private static bool HasNearbyPickupCandidateUncached() { //IL_0033: 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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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_011c: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; GameCamera instance = GameCamera.instance; if (!Object.op_Implicit((Object)(object)localPlayer) || !Object.op_Implicit((Object)(object)instance) || ((Character)localPlayer).IsTeleporting() || !Player.m_enableAutoPickup) { return false; } Vector3 val = ((Component)instance).transform.position + Vector3.up; float resourcePickupRange = BuildCameraConfig.ResourcePickupRange; int num = Physics.OverlapSphereNonAlloc(val, resourcePickupRange, PickupHudOverlapBuffer, localPlayer.m_autoPickupMask); Collider[] array = PickupHudOverlapBuffer; if (num >= PickupHudOverlapBuffer.Length) { array = Physics.OverlapSphere(val, resourcePickupRange, localPlayer.m_autoPickupMask); num = array.Length; } for (int i = 0; i < num; i++) { Collider val2 = array[i]; if (!Object.op_Implicit((Object)(object)val2) || !Object.op_Implicit((Object)(object)val2.attachedRigidbody)) { continue; } ItemDrop component = ((Component)val2.attachedRigidbody).GetComponent(); if ((Object)(object)component == (Object)null) { FloatingTerrainDummy component2 = ((Component)val2.attachedRigidbody).gameObject.GetComponent(); if (component2 != null && Object.op_Implicit((Object)(object)component2) && Object.op_Implicit((Object)(object)component2.m_parent)) { component = ((Component)component2.m_parent).gameObject.GetComponent(); } } if (IsPickupCandidate(localPlayer, component) && Vector3.Distance(((Component)component).transform.position, val) <= resourcePickupRange) { return true; } } return false; } private static bool IsPickupCandidate(Player player, ItemDrop? itemDrop) { if ((Object)(object)itemDrop == (Object)null || !itemDrop.m_autoPickup || itemDrop.InTar()) { return false; } ZNetView component = ((Component)itemDrop).GetComponent(); if ((Object)(object)component == (Object)null || !component.IsValid()) { return false; } if (((Humanoid)player).HaveUniqueKey(itemDrop.m_itemData.m_shared.m_name)) { return false; } if (!itemDrop.CanPickup(true)) { return true; } itemDrop.Load(); if (((Humanoid)player).m_inventory.CanAddItem(itemDrop.m_itemData, -1)) { return itemDrop.m_itemData.GetWeight(-1) + ((Humanoid)player).m_inventory.GetTotalWeight() <= player.GetMaxCarryWeight(); } return false; } private static string LocalizeText(string key, string fallback) { Localization instance = Localization.instance; if (instance == null) { return fallback; } string text = "$" + key; string text2 = instance.Localize(text); if (!(text2 == text)) { return text2; } return fallback; } private static string FormatWithMinimumComfort(string template) { try { return string.Format(template, BuildCameraConfig.MinimumComfortLevel); } catch (FormatException) { return $"{template} (Comfort {BuildCameraConfig.MinimumComfortLevel})"; } } private static string FormatComfortProgress() { Player localPlayer = Player.m_localPlayer; int num = (Object.op_Implicit((Object)(object)localPlayer) ? localPlayer.GetComfortLevel() : 0); return $"C{num}/{BuildCameraConfig.MinimumComfortLevel}"; } } [HarmonyPatch(typeof(SE_Demister), "UpdateStatusEffect")] internal static class ZoneBuildCameraDemisterPatch { private struct ForceFieldData { public float EndRange; } private const float BuildCameraDemisterRangeMultiplier = 2.5f; private static readonly Dictionary OriginalForceFields = new Dictionary(); private static bool Prefix(SE_Demister __instance, float dt) { Character character = ((StatusEffect)__instance).m_character; Player val = (Player)(object)((character is Player) ? character : null); if ((Object)(object)val == (Object)null || !ZoneBuildCamera.IsLocalPlayer(val) || !ZoneBuildCamera.InBuildMode() || !BuildCameraConfig.DemisterFollowCamera) { RestoreNormalForceField(__instance); return true; } IncreaseForceFieldRange(__instance); UpdateDemisterForCamera(__instance, val, dt); return false; } internal static void CleanupBall(GameObject ball) { if (Object.op_Implicit((Object)(object)ball)) { OriginalForceFields.Remove(ball); } } private static void IncreaseForceFieldRange(SE_Demister instance) { if (Object.op_Implicit((Object)(object)instance.m_ballInstance) && !OriginalForceFields.ContainsKey(instance.m_ballInstance)) { ParticleSystemForceField componentInChildren = instance.m_ballInstance.GetComponentInChildren(); if (Object.op_Implicit((Object)(object)componentInChildren)) { OriginalForceFields[instance.m_ballInstance] = new ForceFieldData { EndRange = componentInChildren.endRange }; componentInChildren.endRange *= 2.5f; } } } private static void RestoreNormalForceField(SE_Demister instance) { if (Object.op_Implicit((Object)(object)instance.m_ballInstance) && OriginalForceFields.TryGetValue(instance.m_ballInstance, out var value)) { ParticleSystemForceField componentInChildren = instance.m_ballInstance.GetComponentInChildren(); if (Object.op_Implicit((Object)(object)componentInChildren)) { componentInChildren.endRange = value.EndRange; } OriginalForceFields.Remove(instance.m_ballInstance); } } private static void UpdateDemisterForCamera(SE_Demister instance, Player player, float dt) { //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_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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_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_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_0031: 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_005c: 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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0088: 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_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_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_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_021c: 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_023d: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) Vector3 cameraPosition = GetCameraPosition(); Vector3 cameraForward = GetCameraForward(); if (!Object.op_Implicit((Object)(object)instance.m_ballInstance)) { instance.m_ballInstance = Object.Instantiate(instance.m_ballPrefab, cameraPosition + cameraForward * 0.5f, Quaternion.identity); return; } bool num = IsUnderRoof(instance); Vector3 val = instance.m_ballInstance.transform.position; Vector3 val2 = (num ? instance.m_offsetInterior : instance.m_offset); float num2 = (num ? instance.m_noiseDistanceInterior : instance.m_noiseDistance); Vector3 val3 = GetCameraRight() * val2.x + GetCameraUp() * val2.y + cameraForward * val2.z; Vector3 val4 = cameraPosition + val3; float num3 = Time.time * instance.m_noiseSpeed; Vector3 val5 = new Vector3(Mathf.Sin(num3 * 4f), Mathf.Sin(num3 * 2f) * instance.m_noiseDistanceYScale, Mathf.Cos(num3 * 5f)) * num2; Vector3 val6 = val4 + val5; float num4 = Vector3.Distance(val6, val); Vector3 val7; if (num4 > instance.m_maxDistance * 2f) { val = val6; } else if (num4 > instance.m_maxDistance) { val7 = val - val6; Vector3 normalized = ((Vector3)(ref val7)).normalized; val = val6 + normalized * instance.m_maxDistance; } Vector3 ballVel = instance.m_ballVel; val7 = val6 - val; instance.m_ballVel = ballVel + ((Vector3)(ref val7)).normalized * instance.m_ballAcceleration * dt; if (((Vector3)(ref instance.m_ballVel)).magnitude > instance.m_ballMaxSpeed) { instance.m_ballVel = ((Vector3)(ref instance.m_ballVel)).normalized * instance.m_ballMaxSpeed; } if (!num) { instance.m_ballVel += ((Character)player).GetVelocity() * instance.m_characterVelocityFactor * dt; } instance.m_ballVel -= instance.m_ballVel * instance.m_ballFriction; instance.m_ballInstance.transform.position = val + instance.m_ballVel * dt; Transform transform = instance.m_ballInstance.transform; transform.rotation *= Quaternion.Euler(instance.m_rotationSpeed, 0f, instance.m_rotationSpeed * 0.5321f); } private static Vector3 GetCameraPosition() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)GameCamera.instance)) { return Vector3.zero; } return ((Component)GameCamera.instance).transform.position; } private static Vector3 GetCameraForward() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)GameCamera.instance)) { return Vector3.forward; } return ((Component)GameCamera.instance).transform.forward; } private static Vector3 GetCameraRight() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)GameCamera.instance)) { return Vector3.right; } return ((Component)GameCamera.instance).transform.right; } private static Vector3 GetCameraUp() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)GameCamera.instance)) { return Vector3.up; } return ((Component)GameCamera.instance).transform.up; } private static bool IsUnderRoof(SE_Demister instance) { //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) RaycastHit val = default(RaycastHit); return Physics.Raycast(GetCameraPosition(), Vector3.up, ref val, 4f, instance.m_coverRayMask); } } [HarmonyPatch(typeof(SE_Demister), "RemoveEffects")] internal static class ZoneBuildCameraDemisterCleanupPatch { private static void Prefix(SE_Demister __instance) { ZoneBuildCameraDemisterPatch.CleanupBall(__instance.m_ballInstance); } } internal static class ZoneBuildCameraDvergerLight { private sealed class ProxyLightState { public Light Source; public int SourceVisibleCullingMask; public Light ProxyLight; public GameObject ProxyObject; } private sealed class CircletExtendedApi { public MethodInfo? GetCircletMethod; public MethodInfo? GetCircletDataMethod; public FieldInfo? CircletItemInstanceField; public Type? VisEquipmentCircletType; public Func? GetCircletFast; public Func? GetCircletDataFast; public Func? GetCircletInstanceFast; } [HarmonyPatch(typeof(GameCamera), "UpdateCamera")] private static class GameCameraUpdatePatch { private static void Postfix(GameCamera __instance) { try { UpdateProxyLights(__instance); } catch (Exception ex) { if (Time.time >= _nextWarningLogTime) { _nextWarningLogTime = Time.time + 2f; HomesteadPlugin.HomesteadLogger.LogWarning((object)("Dvergr circlet build camera light failed: " + ex.Message)); } CleanupAll(); } } } [HarmonyPatch(typeof(Player), "SetLocalPlayer")] private static class PlayerSetLocalPlayerPatch { private static void Postfix() { CleanupAll(); } } private const string CircletExtendedGuid = "shudnal.CircletExtended"; private static readonly Dictionary ProxyBySourceId = new Dictionary(); private static readonly BindingFlags StaticMethodFlags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; private static readonly BindingFlags InstanceFieldFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private static readonly List TempLights = new List(); private static readonly List TempVisualRoots = new List(); private static readonly HashSet TempSourceIdSet = new HashSet(); private static readonly List TempRemoveSourceIds = new List(); private static CircletExtendedApi? _circletExtendedApi; private static bool _circletExtendedApiInitialized; private static float _nextWarningLogTime; internal static void CleanupAll() { foreach (KeyValuePair item in ProxyBySourceId) { RestoreSourceAndDestroyProxy(item.Value.Source, item.Value); } ProxyBySourceId.Clear(); } private static void UpdateProxyLights(GameCamera camera) { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (!BuildCameraConfig.FollowDvergrCircletLight || !Object.op_Implicit((Object)(object)localPlayer) || !Object.op_Implicit((Object)(object)camera) || !ZoneBuildCamera.InBuildMode() || !IsAnySupportedCircletEquipped(localPlayer)) { CleanupAll(); return; } if (!TryGetHelmetLights(localPlayer, TempLights) || TempLights.Count == 0) { CleanupAll(); return; } Vector3 cameraOffset = default(Vector3); ((Vector3)(ref cameraOffset))..ctor(0f, BuildCameraConfig.HelmetLightOffsetUp, BuildCameraConfig.HelmetLightOffsetForward); RemoveStaleSources(TempLights); AddNewSources(TempLights, ((Component)camera).transform, cameraOffset); UpdateExistingProxies(((Component)camera).transform, cameraOffset); } private static bool IsAnySupportedCircletEquipped(Player player) { if (ZoneDvergrCirclet.TryGetEquippedDvergrCirclet(player, out ItemData _)) { return true; } return IsDvergrCircletItem(GetCircletExtendedEquippedCirclet(player)); } private static bool IsDvergrCircletItem(ItemData? item) { if (item == null) { return false; } string text = (Object.op_Implicit((Object)(object)item.m_dropPrefab) ? ((Object)item.m_dropPrefab).name : string.Empty); if (text.Equals("HelmetDverger", StringComparison.OrdinalIgnoreCase) || text.StartsWith("HelmetDverger", StringComparison.OrdinalIgnoreCase)) { return true; } string text2 = item.m_shared?.m_name ?? string.Empty; if (text2.IndexOf("helmet_dverger", StringComparison.OrdinalIgnoreCase) < 0) { if (text2.IndexOf("dverger", StringComparison.OrdinalIgnoreCase) >= 0) { if (text2.IndexOf("helmet", StringComparison.OrdinalIgnoreCase) < 0) { return text2.IndexOf("circlet", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } return false; } return true; } private static ItemData? GetCircletExtendedEquippedCirclet(Player player) { CircletExtendedApi circletExtendedApi = GetCircletExtendedApi(); if (circletExtendedApi == null) { return null; } if (circletExtendedApi.GetCircletFast != null) { try { return circletExtendedApi.GetCircletFast((Humanoid)(object)player); } catch { } } if (circletExtendedApi.GetCircletMethod == null) { return null; } try { object? obj2 = circletExtendedApi.GetCircletMethod.Invoke(null, new object[1] { player }); return (ItemData?)((obj2 is ItemData) ? obj2 : null); } catch { return null; } } private static bool TryGetHelmetLights(Player player, List output) { output.Clear(); VisEquipment visEquipment = ((Humanoid)player).m_visEquipment; if (!Object.op_Implicit((Object)(object)visEquipment)) { return false; } if (Object.op_Implicit((Object)(object)visEquipment.m_helmetItemInstance)) { AppendLightsFromRoot(visEquipment.m_helmetItemInstance, output); } if (ZoneDvergrCirclet.TryGetEquippedDvergrCirclet(player, out ItemData item) && item != null && AzuExtendedPlayerInventoryCompat.TryGetCustomEquipVisualRoots(visEquipment, item, TempVisualRoots)) { foreach (GameObject tempVisualRoot in TempVisualRoots) { if (Object.op_Implicit((Object)(object)tempVisualRoot)) { AppendLightsFromRoot(tempVisualRoot, output); } } } ZoneDvergrCirclet.TryAppendFallbackLight(output); if (TryGetCircletExtendedItemInstance(visEquipment, out GameObject circletItemInstance) && Object.op_Implicit((Object)(object)circletItemInstance)) { AppendLightsFromRoot(circletItemInstance, output); } return output.Count > 0; } private static void AppendLightsFromRoot(GameObject root, List output) { root.GetComponentsInChildren(true, output); for (int num = output.Count - 1; num >= 0; num--) { if ((Object)(object)output[num] == (Object)null) { output.RemoveAt(num); } } } private static bool TryGetCircletExtendedItemInstance(VisEquipment visEquipment, out GameObject? circletItemInstance) { circletItemInstance = null; CircletExtendedApi circletExtendedApi = GetCircletExtendedApi(); if (circletExtendedApi == null || (circletExtendedApi.GetCircletDataFast == null && circletExtendedApi.GetCircletDataMethod == null) || (circletExtendedApi.GetCircletInstanceFast == null && circletExtendedApi.CircletItemInstanceField == null)) { return false; } try { object obj = ((circletExtendedApi.GetCircletDataFast != null) ? circletExtendedApi.GetCircletDataFast(visEquipment) : circletExtendedApi.GetCircletDataMethod?.Invoke(null, new object[1] { visEquipment })); if (obj == null) { return false; } GameObject val = (GameObject)((circletExtendedApi.GetCircletInstanceFast != null) ? ((object)circletExtendedApi.GetCircletInstanceFast(obj)) : ((object)/*isinst with value type is only supported in some contexts*/)); if (Object.op_Implicit((Object)(object)val)) { circletItemInstance = val; return true; } } catch { } return false; } private static void RemoveStaleSources(List currentSources) { TempSourceIdSet.Clear(); foreach (Light currentSource in currentSources) { if (Object.op_Implicit((Object)(object)currentSource)) { TempSourceIdSet.Add(((Object)currentSource).GetInstanceID()); } } TempRemoveSourceIds.Clear(); foreach (KeyValuePair item in ProxyBySourceId) { if (!Object.op_Implicit((Object)(object)item.Value.Source) || !TempSourceIdSet.Contains(item.Key)) { TempRemoveSourceIds.Add(item.Key); } } foreach (int tempRemoveSourceId in TempRemoveSourceIds) { RemoveProxyState(tempRemoveSourceId); } } private static void AddNewSources(List currentSources, Transform cameraTransform, Vector3 cameraOffset) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) foreach (Light currentSource in currentSources) { if (Object.op_Implicit((Object)(object)currentSource)) { int instanceID = ((Object)currentSource).GetInstanceID(); if (!ProxyBySourceId.ContainsKey(instanceID)) { ProxyBySourceId[instanceID] = CreateProxyState(currentSource, cameraTransform, cameraOffset); } } } } private static void UpdateExistingProxies(Transform cameraTransform, Vector3 cameraOffset) { //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) TempRemoveSourceIds.Clear(); foreach (KeyValuePair item in ProxyBySourceId) { ProxyLightState value = item.Value; Light source = value.Source; if (!Object.op_Implicit((Object)(object)source) || (Object)(object)value.ProxyLight == (Object)null || (Object)(object)value.ProxyObject == (Object)null) { TempRemoveSourceIds.Add(item.Key); continue; } CopyLightState(source, value.ProxyLight); SuppressSourceLight(source, value); value.ProxyObject.transform.position = CalculateCameraFollowPosition(cameraTransform, cameraOffset); value.ProxyObject.transform.rotation = cameraTransform.rotation; value.ProxyObject.SetActive(((Component)source).gameObject.activeInHierarchy); } foreach (int tempRemoveSourceId in TempRemoveSourceIds) { RemoveProxyState(tempRemoveSourceId); } } private static ProxyLightState CreateProxyState(Light source, Transform cameraTransform, Vector3 cameraOffset) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //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) //IL_0076: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Homestead_DvergrBuildCameraLight_" + ((Object)source).name) { hideFlags = (HideFlags)61 }; Light val2 = val.AddComponent(); CopyLightState(source, val2); ProxyLightState proxyLightState = new ProxyLightState { Source = source, SourceVisibleCullingMask = source.cullingMask, ProxyLight = val2, ProxyObject = val }; proxyLightState.ProxyObject.transform.position = CalculateCameraFollowPosition(cameraTransform, cameraOffset); proxyLightState.ProxyObject.transform.rotation = cameraTransform.rotation; SuppressSourceLight(source, proxyLightState); return proxyLightState; } private static void RemoveProxyState(int sourceId) { if (ProxyBySourceId.TryGetValue(sourceId, out ProxyLightState value)) { RestoreSourceAndDestroyProxy(value.Source, value); ProxyBySourceId.Remove(sourceId); } } private static void RestoreSourceAndDestroyProxy(Light? source, ProxyLightState? state) { if ((Object)(object)source != (Object)null && state != null) { source.cullingMask = state.SourceVisibleCullingMask; } if ((Object)(object)state?.ProxyObject != (Object)null) { Object.Destroy((Object)(object)state.ProxyObject); } } private static void SuppressSourceLight(Light source, ProxyLightState state) { if (source.cullingMask != 0) { state.SourceVisibleCullingMask = source.cullingMask; source.cullingMask = 0; } } private static Vector3 CalculateCameraFollowPosition(Transform cameraTransform, Vector3 cameraOffset) { //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_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) //IL_0017: 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_0022: 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_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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) return cameraTransform.position + cameraTransform.right * cameraOffset.x + cameraTransform.up * cameraOffset.y + cameraTransform.forward * cameraOffset.z; } private static void CopyLightState(Light src, Light dst) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000e: 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_0086: 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) dst.type = src.type; dst.color = src.color; dst.colorTemperature = src.colorTemperature; dst.useColorTemperature = src.useColorTemperature; dst.intensity = src.intensity; dst.range = src.range; dst.spotAngle = src.spotAngle; dst.cookie = src.cookie; dst.cookieSize = src.cookieSize; dst.shadows = src.shadows; dst.shadowStrength = src.shadowStrength; dst.shadowResolution = src.shadowResolution; dst.renderMode = src.renderMode; dst.cullingMask = ((src.cullingMask != 0) ? src.cullingMask : dst.cullingMask); ((Behaviour)dst).enabled = ((Behaviour)src).enabled; } private static CircletExtendedApi? GetCircletExtendedApi() { if (_circletExtendedApiInitialized) { return _circletExtendedApi; } _circletExtendedApiInitialized = true; if (!Chainloader.PluginInfos.TryGetValue("shudnal.CircletExtended", out var value)) { return null; } Assembly obj = ((object)value.Instance)?.GetType().Assembly; Type type = obj?.GetType("CircletExtended.HumanoidExtension", throwOnError: false); Type type2 = obj?.GetType("CircletExtended.VisEquipmentExtension", throwOnError: false); Type type3 = obj?.GetType("CircletExtended.VisEquipmentCirclet", throwOnError: false); MethodInfo methodInfo = FindStaticMethod(type, "GetCirclet", typeof(Humanoid)); MethodInfo methodInfo2 = FindStaticMethod(type2, "GetCircletData", typeof(VisEquipment)); FieldInfo fieldInfo = type3?.GetField("m_circletItemInstance", InstanceFieldFlags); _circletExtendedApi = new CircletExtendedApi { GetCircletMethod = methodInfo, GetCircletDataMethod = methodInfo2, CircletItemInstanceField = fieldInfo, VisEquipmentCircletType = type3, GetCircletFast = CreateCircletExtendedGetCircletDelegate(methodInfo), GetCircletDataFast = CreateCircletExtendedGetCircletDataDelegate(methodInfo2), GetCircletInstanceFast = CreateCircletExtendedGetCircletInstanceDelegate(type3, fieldInfo) }; return _circletExtendedApi; } private static MethodInfo? FindStaticMethod(Type? type, string name, params Type[] parameterTypes) { if (type == null) { return null; } MethodInfo[] methods = type.GetMethods(StaticMethodFlags); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name != name) { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length != parameterTypes.Length) { continue; } bool flag = true; for (int j = 0; j < parameters.Length; j++) { if (parameters[j].ParameterType != parameterTypes[j]) { flag = false; break; } } if (flag) { return methodInfo; } } return null; } private static Func? CreateCircletExtendedGetCircletDelegate(MethodInfo? method) { if (method == null) { return null; } try { return (Func)Delegate.CreateDelegate(typeof(Func), method); } catch { return null; } } private static Func? CreateCircletExtendedGetCircletDataDelegate(MethodInfo? method) { if (method == null) { return null; } try { return (Func)Delegate.CreateDelegate(typeof(Func), method); } catch { return null; } } private static Func? CreateCircletExtendedGetCircletInstanceDelegate(Type? circletType, FieldInfo? itemInstanceField) { if (itemInstanceField == null || circletType == null) { return null; } try { ParameterExpression parameterExpression = Expression.Parameter(typeof(object), "obj"); return Expression.Lambda>(Expression.Convert(Expression.Field(Expression.Convert(parameterExpression, circletType), itemInstanceField), typeof(GameObject)), new ParameterExpression[1] { parameterExpression }).Compile(); } catch { return null; } } } [HarmonyPatch(typeof(Player), "SetLocalPlayer")] internal static class ZoneBuildCameraPlayerSetLocalPlayerPatch { private static void Postfix() { ZoneBuildCamera.DisableBuildMode(); HomesteadFeatureBootstrap.OnLocalPlayerSet(); } } [HarmonyPatch(typeof(CraftingStation), "HaveBuildStationInRange")] internal static class ZoneBuildCameraCraftingStationHaveBuildStationInRangePatch { private static void Prefix(ref Vector3 point) { //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) if (ZoneBuildCamera.TryGetBuildCameraOrigin(out var origin)) { point = origin; } } } [HarmonyPatch(typeof(Player), "PieceRayTest")] internal static class ZoneBuildCameraPlayerPieceRayTestPatch { private static void Prefix(Player __instance, ref ZoneBuildCamera.EyeOriginOverrideState __state) { __state = ZoneBuildCamera.BeginEyeOriginOverride(__instance); } private static void Postfix(Player __instance, ZoneBuildCamera.EyeOriginOverrideState __state) { ZoneBuildCamera.EndEyeOriginOverride(__instance, __state); } } [HarmonyPatch(typeof(Player), "UpdateWearNTearHover")] internal static class ZoneBuildCameraPlayerUpdateWearNTearHoverPatch { private static void Prefix(Player __instance, ref ZoneBuildCamera.EyeOriginOverrideState __state) { __state = ZoneBuildCamera.BeginEyeOriginOverride(__instance); } private static void Postfix(Player __instance, ZoneBuildCamera.EyeOriginOverrideState __state) { ZoneBuildCamera.EndEyeOriginOverride(__instance, __state); } } [HarmonyPatch(typeof(Player), "CopyPiece")] internal static class ZoneBuildCameraPlayerCopyPiecePatch { private static void Prefix(Player __instance, ref ZoneBuildCamera.EyeOriginOverrideState __state) { __state = ZoneBuildCamera.BeginEyeOriginOverride(__instance); } private static void Postfix(Player __instance, ZoneBuildCamera.EyeOriginOverrideState __state) { ZoneBuildCamera.EndEyeOriginOverride(__instance, __state); } } [HarmonyPatch(typeof(Player), "RemovePiece")] internal static class ZoneBuildCameraPlayerRemovePiecePatch { private static void Prefix(Player __instance, ref ZoneBuildCamera.EyeOriginOverrideState __state) { __state = ZoneBuildCamera.BeginEyeOriginOverride(__instance); } private static void Postfix(Player __instance, ZoneBuildCamera.EyeOriginOverrideState __state) { ZoneBuildCamera.EndEyeOriginOverride(__instance, __state); } } [HarmonyPatch(typeof(Player), "Update")] internal static class ZoneBuildCameraPlayerUpdatePatch { private static void Prefix(Player __instance, ref bool __runOriginal) { if (!ZoneBuildCamera.IsLocalPlayer(__instance) || !ZoneBuildCamera.InBuildMode()) { return; } if (ZoneBuildCamera.ShouldDeactivateBuildMode(__instance)) { ZoneBuildCamera.DisableBuildMode(); return; } __runOriginal = false; if (!ZoneBuildCamera.IsInputBlocked(blockPieceSelection: false) && ((Character)__instance).TakeInput()) { UpdateHotbarAndHideInputs(__instance); __instance.UpdatePlacement(true, Time.deltaTime); } } private static void Postfix(Player __instance) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (!ZoneBuildCamera.IsLocalPlayer(__instance) || !ZoneBuildCamera.IsEnabled()) { return; } KeyboardShortcut toggleHotkey = BuildCameraConfig.ToggleHotkey; if (((KeyboardShortcut)(ref toggleHotkey)).IsDown() && !ZoneBuildCamera.IsInputBlocked(blockPieceSelection: true) && ((Character)__instance).TakeInput()) { if (ZoneBuildCamera.InBuildMode()) { ZoneBuildCamera.DisableBuildMode(); } else if (ZoneBuildCamera.ToolIsEquipped(__instance) && ZoneBuildCamera.BuildStationInRange(__instance)) { ZoneBuildCamera.EnableBuildMode(); } } } private static void UpdateHotbarAndHideInputs(Player player) { if (Input.GetKeyDown((KeyCode)49) || ZInput.GetButtonDown("Hotbar1")) { player.UseHotbarItem(1); } if (Input.GetKeyDown((KeyCode)50) || ZInput.GetButtonDown("Hotbar2")) { player.UseHotbarItem(2); } if (Input.GetKeyDown((KeyCode)51) || ZInput.GetButtonDown("Hotbar3")) { player.UseHotbarItem(3); } if (Input.GetKeyDown((KeyCode)52) || ZInput.GetButtonDown("Hotbar4")) { player.UseHotbarItem(4); } if (Input.GetKeyDown((KeyCode)53) || ZInput.GetButtonDown("Hotbar5")) { player.UseHotbarItem(5); } if (Input.GetKeyDown((KeyCode)54) || ZInput.GetButtonDown("Hotbar6")) { player.UseHotbarItem(6); } if (Input.GetKeyDown((KeyCode)55) || ZInput.GetButtonDown("Hotbar7")) { player.UseHotbarItem(7); } if (Input.GetKeyDown((KeyCode)56) || ZInput.GetButtonDown("Hotbar8")) { player.UseHotbarItem(8); } if ((ZInput.GetButtonDown("Hide") || ZInput.GetButtonDown("JoyHide")) && (((Humanoid)player).GetRightItem() != null || ((Humanoid)player).GetLeftItem() != null) && !((Character)player).InAttack()) { ((Humanoid)player).HideHandItems(false, true); } } } [HarmonyPatch(typeof(PlayerController), "TakeInput")] internal static class ZoneBuildCameraPlayerControllerTakeInputPatch { private static void Prefix(ref bool __result, ref bool __runOriginal) { if (ZoneBuildCamera.InBuildMode()) { __result = false; __runOriginal = false; } } } [HarmonyPatch(typeof(GameCamera), "UpdateCamera")] [HarmonyBefore(new string[] { "Azumatt.FirstPersonMode" })] [HarmonyPriority(700)] internal static class ZoneBuildCameraGameCameraUpdatePatch { private static void Prefix(float dt, GameCamera __instance, ref bool __runOriginal) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (ZoneBuildCamera.InBuildMode()) { ZoneBuildCamera.UpdateBuildCamera(dt, __instance); if (ZoneBuildCameraWardCompat.CheckAccess(((Component)__instance).transform.position, flash: false)) { ZoneBuildCamera.AutoPickup(dt, __instance); } __runOriginal = false; } } } internal static class ZoneBuildCameraWardCompat { private const string WardIsLoveGuid = "Azumatt.WardIsLove"; private static readonly System.Version WardIsLoveMinimumVersion = new System.Version(2, 3, 3); private static MethodInfo? _checkAccessMethod; private static bool _checkedWardIsLove; internal static bool CheckAccess(Vector3 point, bool flash) { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer)) { return false; } if (IsWardIsLoveLoaded()) { try { object obj = _checkAccessMethod?.Invoke(null, new object[4] { localPlayer.GetPlayerID(), point, 0f, flash }); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch { return false; } } return PrivateArea.CheckAccess(point, 0f, flash, true); } private static bool IsWardIsLoveLoaded() { if (_checkedWardIsLove) { return _checkAccessMethod != null; } _checkedWardIsLove = true; if (!Chainloader.PluginInfos.TryGetValue("Azumatt.WardIsLove", out var value) || value.Metadata.Version < WardIsLoveMinimumVersion) { return false; } _checkAccessMethod = ((((object)value.Instance)?.GetType().Assembly)?.GetType("WardIsLove.Util.CustomCheck", throwOnError: false))?.GetMethod("CheckAccess", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); return _checkAccessMethod != null; } } internal static class ZoneContentsWithinBlueprintChestPreview { private sealed class PreviewCache { public Inventory Inventory { get; } public string Signature { get; } public float LastUsedAt { get; set; } public PreviewCache(Inventory inventory, string signature, float lastUsedAt) { Inventory = inventory; Signature = signature; LastUsedAt = lastUsedAt; } } private const string ContentsWithinPatchTypeName = "ContentsWithin.ContentsWithin+InventoryGuiPatch"; private const int PreviewWidth = 8; private const int MaxPreviewRows = 8; private static readonly Color RequirementIconColor = new Color(1f, 1f, 1f, 0.45f); private static readonly Color RequirementAmountColor = new Color(0.86f, 0.86f, 0.86f, 0.75f); private static readonly Color RequirementBackgroundColor = new Color(0.18f, 0.18f, 0.18f, 0.55f); private static readonly Dictionary PreviewInventories = new Dictionary(StringComparer.Ordinal); private static Type? _contentsWithinPatchType; private static bool _contentsWithinTypeResolved; public static bool IsContentsWithinLoaded() { Type type; return TryGetContentsWithinPatchType(out type); } public static bool TryGetContentsWithinPatchType(out Type type) { if (_contentsWithinTypeResolved) { type = _contentsWithinPatchType; return type != null; } _contentsWithinTypeResolved = true; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { Type type2 = assemblies[i].GetType("ContentsWithin.ContentsWithin+InventoryGuiPatch", throwOnError: false, ignoreCase: false); if (!(type2 == null)) { _contentsWithinPatchType = type2; type = type2; return true; } } type = null; return false; } public static void ResetForWorldSession() { PreviewInventories.Clear(); } public static bool TryHandleAccess(Container? container, ref bool result) { if (!Object.op_Implicit((Object)(object)container)) { return false; } if (IsBlockedPriceChest(container)) { result = false; return true; } if (CanShowVirtualRequirements(container)) { result = true; return true; } return false; } public static bool TryReplacePreviewInventory(Inventory? source, out Inventory preview) { preview = null; if (source == null || (Object)(object)Player.m_localPlayer == (Object)null) { return false; } GameObject hoverObject = ((Humanoid)Player.m_localPlayer).GetHoverObject(); Container val = (((Object)(object)hoverObject != (Object)null) ? hoverObject.GetComponentInParent() : null); if (!Object.op_Implicit((Object)(object)val) || val.GetInventory() != source) { return false; } return TryCreateVirtualRequirementInventory(val, out preview); } public static void GreyOutRequirementGrid(InventoryGrid? grid) { if ((Object)(object)grid == (Object)null || !IsVirtualRequirementInventory(grid.GetInventory())) { return; } Inventory inventory = grid.GetInventory(); int num = Mathf.Max(1, grid.m_width); int num2 = 0; foreach (Element element in grid.m_elements) { ItemData itemAt = inventory.GetItemAt(num2 % num, num2 / num); num2++; if (element.m_used) { ApplyRequirementSlotStyle(element, itemAt); } } } private static bool CanShowVirtualRequirements(Container container) { List requirements; string cacheKey; return TryGetMissingRequirements(container, out requirements, out cacheKey); } private static bool IsVirtualRequirementInventory(Inventory? inventory) { if (inventory == null) { return false; } foreach (PreviewCache value in PreviewInventories.Values) { if (value.Inventory == inventory) { return true; } } return false; } private static bool TryCreateVirtualRequirementInventory(Container container, out Inventory preview) { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown preview = null; if (!TryGetMissingRequirements(container, out List requirements, out string cacheKey)) { return false; } string text = CreateRequirementSignature(requirements); if (PreviewInventories.TryGetValue(cacheKey, out PreviewCache value) && string.Equals(value.Signature, text, StringComparison.Ordinal)) { value.LastUsedAt = Time.realtimeSinceStartup; preview = value.Inventory; return true; } int num = Mathf.Clamp(Mathf.CeilToInt((float)Mathf.Max(1, requirements.Count) / 8f), 1, 8); Inventory val = new Inventory("HomesteadRequirementsPreview", container.m_bkg, 8, num); FillPreviewInventory(val, requirements); PreviewInventories[cacheKey] = new PreviewCache(val, text, Time.realtimeSinceStartup); PrunePreviewInventories(); preview = val; return true; } private static bool TryGetMissingRequirements(Container container, out List requirements, out string cacheKey) { requirements = new List(); cacheKey = ""; if (ZoneBlueprintPlanAnchor.TryGetAnchor(container, out ZoneBlueprintPlanAnchor anchor)) { requirements = anchor.GetMissingRequirementList(); cacheKey = CreateCacheKey(container, "plan"); return true; } ZoneBlueprintStoreChest component = ((Component)container).GetComponent(); if ((Object)(object)component != (Object)null && component.IsPurchaseChest()) { requirements = component.GetMissingPurchaseRequirementList(); cacheKey = CreateCacheKey(container, "purchase"); return true; } return false; } private static void FillPreviewInventory(Inventory inventory, IReadOnlyList requirements) { //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) int num = inventory.m_width * inventory.m_height; int num2 = Mathf.Min(requirements.Count, num); for (int i = 0; i < num2; i++) { ZoneBlueprintRequirement zoneBlueprintRequirement = requirements[i]; GameObject val = ZoneBlueprintStore.FindItemPrefab(zoneBlueprintRequirement.PrefabName) ?? ZoneBlueprintStore.FindItemPrefab(zoneBlueprintRequirement.ItemName); ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent() : null); if (!((Object)(object)val2 == (Object)null)) { ItemData val3 = val2.m_itemData.Clone(); val3.m_stack = Mathf.Max(1, zoneBlueprintRequirement.Amount); val3.m_dropPrefab = val; val3.m_gridPos = new Vector2i(i % inventory.m_width, i / inventory.m_width); inventory.m_inventory.Add(val3); } } inventory.Changed(); } private static void ApplyRequirementSlotStyle(Element element, ItemData? item) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)element.m_icon != (Object)null) { Transform parent = ((Component)element.m_icon).transform.parent; if ((Object)(object)parent != (Object)null) { Image[] componentsInChildren = ((Component)parent).GetComponentsInChildren(true); foreach (Image val in componentsInChildren) { if (!((Object)(object)val == (Object)(object)element.m_icon)) { ((Graphic)val).color = RequirementBackgroundColor; } } } ((Graphic)element.m_icon).color = RequirementIconColor; } if ((Object)(object)element.m_amount != (Object)null) { if (item != null) { element.m_amount.text = item.m_stack.ToString(); } ((Graphic)element.m_amount).color = RequirementAmountColor; } if ((Object)(object)element.m_quality != (Object)null) { ((Behaviour)element.m_quality).enabled = false; } if ((Object)(object)element.m_equiped != (Object)null) { ((Behaviour)element.m_equiped).enabled = false; } if ((Object)(object)element.m_queued != (Object)null) { ((Behaviour)element.m_queued).enabled = false; } if ((Object)(object)element.m_noteleport != (Object)null) { ((Behaviour)element.m_noteleport).enabled = false; } if ((Object)(object)element.m_food != (Object)null) { ((Behaviour)element.m_food).enabled = false; } if ((Object)(object)element.m_durability != (Object)null) { ((Component)element.m_durability).gameObject.SetActive(false); } } private static bool IsBlockedPriceChest(Container container) { ZoneBlueprintStoreChest component = ((Component)container).GetComponent(); if ((Object)(object)component != (Object)null && (component.IsPriceChest() || component.IsPriceChestPrefab())) { return true; } ZNetView component2 = ((Component)container).GetComponent(); if ((Object)(object)component2 != (Object)null && component2.IsValid()) { return component2.GetZDO().GetPrefab() == ZoneBlueprintStoreChestPrefab.PricePrefabHash; } return false; } private static string CreateCacheKey(Container container, string kind) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) ZNetView component = ((Component)container).GetComponent(); if ((Object)(object)component != (Object)null && component.IsValid()) { return $"{kind}:{component.GetZDO().m_uid}"; } return $"{kind}:local:{((Object)container).GetInstanceID()}"; } private static string CreateRequirementSignature(IReadOnlyList requirements) { if (requirements.Count == 0) { return "empty"; } List list = new List(requirements.Count); foreach (ZoneBlueprintRequirement requirement in requirements) { list.Add($"{requirement.ItemName}|{requirement.PrefabName}|{requirement.Amount}"); } return string.Join(";", list); } private static void PrunePreviewInventories() { if (PreviewInventories.Count <= 64) { return; } float num = Time.realtimeSinceStartup - 60f; List list = new List(); foreach (KeyValuePair previewInventory in PreviewInventories) { if (previewInventory.Value.LastUsedAt < num) { list.Add(previewInventory.Key); } } foreach (string item in list) { PreviewInventories.Remove(item); } while (PreviewInventories.Count > 64) { string text = ""; float num2 = float.PositiveInfinity; foreach (KeyValuePair previewInventory2 in PreviewInventories) { if (!(previewInventory2.Value.LastUsedAt >= num2)) { num2 = previewInventory2.Value.LastUsedAt; text = previewInventory2.Key; } } if (!string.IsNullOrEmpty(text)) { PreviewInventories.Remove(text); continue; } break; } } } [HarmonyPatch] internal static class ZoneContentsWithinAccessCompat { private static bool Prepare() { return ZoneContentsWithinBlueprintChestPreview.IsContentsWithinLoaded(); } private static MethodBase? TargetMethod() { if (!ZoneContentsWithinBlueprintChestPreview.TryGetContentsWithinPatchType(out Type type)) { return null; } return AccessTools.Method(type, "HasContainerAccess", new Type[1] { typeof(Container) }, (Type[])null); } private static bool Prefix(Container container, ref bool __result) { return !ZoneContentsWithinBlueprintChestPreview.TryHandleAccess(container, ref __result); } } [HarmonyPatch] internal static class ZoneContentsWithinPreviewCompat { private static bool Prepare() { return ZoneContentsWithinBlueprintChestPreview.IsContentsWithinLoaded(); } private static MethodBase? TargetMethod() { if (!ZoneContentsWithinBlueprintChestPreview.TryGetContentsWithinPatchType(out Type type)) { return null; } return AccessTools.Method(type, "ShowPreviewContainer", new Type[1] { typeof(Inventory) }, (Type[])null); } private static void Prefix(ref Inventory container) { if (ZoneContentsWithinBlueprintChestPreview.TryReplacePreviewInventory(container, out Inventory preview)) { container = preview; } } } [HarmonyPatch(typeof(InventoryGrid), "UpdateGui")] internal static class ZoneContentsWithinRequirementGridCompat { private static void Postfix(InventoryGrid __instance) { ZoneContentsWithinBlueprintChestPreview.GreyOutRequirementGrid(__instance); } } internal static class ZoneBlueprintCommands { internal sealed class BlueprintLoadPlan { public List Entries { get; } public List Positions { get; } public List SupportContacts { get; } public BlueprintLoadPlan(List entries, List positions, List supportContacts) { Entries = entries; Positions = positions; SupportContacts = supportContacts; } } internal sealed class BlueprintLoadEntry { public ZoneBlueprintEntry Entry { get; } public GameObject Prefab { get; } public Vector3 Position { get; } public Quaternion Rotation { get; } public Vector3 Scale { get; } public BlueprintLoadEntry(ZoneBlueprintEntry entry, GameObject prefab, Vector3 position, Quaternion rotation, Vector3 scale) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: 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_0024: 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) Entry = entry; Prefab = prefab; Position = position; Rotation = rotation; Scale = scale; } } [CompilerGenerated] private sealed class <>c__DisplayClass13_0 { public BlueprintLoadPlan plan; public string planError; public bool terrainApplied; public int created; internal void b__0(BlueprintLoadPlan? value, string error) { plan = value; planError = error; } internal void b__1(bool result) { terrainApplied = result; } internal void b__2(int value) { created = value; } } [CompilerGenerated] private sealed class <>c__DisplayClass13_1 { public string accessReason; public List requirements; internal void b__3(string value) { accessReason = value; } internal void b__4(List value) { requirements = value; } } [CompilerGenerated] private sealed class d__38 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public IEnumerable entries; public Action> onComplete; private Dictionary 5__2; private int 5__3; private IEnumerator <>7__wrap3; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__38(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } 5__2 = null; <>7__wrap3 = null; <>1__state = -2; } private bool MoveNext() { try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__2 = new Dictionary(); 5__3 = 0; <>7__wrap3 = entries.GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; break; } while (<>7__wrap3.MoveNext()) { Piece component = <>7__wrap3.Current.Prefab.GetComponent(); if ((Object)(object)component != (Object)null) { Requirement[] resources = component.m_resources; foreach (Requirement val in resources) { if (Object.op_Implicit((Object)(object)val.m_resItem) && val.m_amount > 0) { string name = val.m_resItem.m_itemData.m_shared.m_name; if (!5__2.TryGetValue(name, out ZoneBlueprintRequirement value)) { value = new ZoneBlueprintRequirement { ItemName = name, PrefabName = Utils.GetPrefabName(((Component)val.m_resItem).gameObject), DisplayName = val.m_resItem.m_itemData.m_shared.m_name }; 5__2[name] = value; } value.Amount += val.GetAmount(0); } } } 5__3++; if (5__3 >= 250) { 5__3 = 0; <>2__current = null; <>1__state = 1; return true; } } <>m__Finally1(); <>7__wrap3 = null; onComplete(5__2.Values.OrderBy((ZoneBlueprintRequirement requirement) => requirement.ItemName, StringComparer.Ordinal).ToList()); return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>7__wrap3 != null) { <>7__wrap3.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__34 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public ZoneBlueprintFile blueprint; public Action onComplete; public Vector3 anchor; public Quaternion anchorRotation; private List 5__2; private List 5__3; private int 5__4; private List 5__5; private List.Enumerator <>7__wrap5; private List.Enumerator <>7__wrap6; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__34(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { switch (<>1__state) { case -3: case 1: try { } finally { <>m__Finally1(); } break; case -4: case 2: try { } finally { <>m__Finally2(); } break; } 5__2 = null; 5__3 = null; 5__5 = null; <>7__wrap5 = default(List.Enumerator); <>7__wrap6 = default(List.Enumerator); <>1__state = -2; } private bool MoveNext() { //IL_0294: Unknown result type (might be due to invalid IL or missing references) //IL_029a: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Unknown result type (might be due to invalid IL or missing references) //IL_02b9: Unknown result type (might be due to invalid IL or missing references) //IL_02be: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) bool result; try { switch (<>1__state) { default: result = false; goto end_IL_0000; case 0: <>1__state = -1; 5__2 = new List(); 5__3 = new List(); 5__4 = 0; <>7__wrap5 = blueprint.Entries.GetEnumerator(); <>1__state = -3; goto IL_0213; case 1: <>1__state = -3; goto IL_0213; case 2: { <>1__state = -4; break; } IL_0213: while (true) { if (!<>7__wrap5.MoveNext()) { <>m__Finally1(); <>7__wrap5 = default(List.Enumerator); 5__5 = new List(blueprint.TerrainContacts.Count); <>7__wrap6 = blueprint.TerrainContacts.GetEnumerator(); <>1__state = -4; break; } ZoneBlueprintEntry current = <>7__wrap5.Current; GameObject prefab = ZNetScene.instance.GetPrefab(current.Prefab); if (!Object.op_Implicit((Object)(object)prefab)) { onComplete(null, "Missing prefab '" + current.Prefab + "' while loading blueprint '" + blueprint.Name + "'."); result = false; goto IL_022b; } if ((Object)(object)prefab.GetComponent() != (Object)null && HasBuildRecipe(prefab)) { if (current.LocalPos.Length < 3 || current.LocalRot.Length < 4 || current.Scale.Length < 3) { onComplete(null, "Blueprint '" + blueprint.Name + "' contains an invalid transform for '" + current.Prefab + "'."); result = false; goto IL_022b; } Vector3 val = anchor + anchorRotation * FromVector(current.LocalPos); Quaternion rotation = anchorRotation * FromQuaternion(current.LocalRot); Vector3 scale = FromVector(current.Scale); 5__2.Add(new BlueprintLoadEntry(current, prefab, val, rotation, scale)); 5__3.Add(val); } 5__4++; if (5__4 < 250) { continue; } 5__4 = 0; <>2__current = null; <>1__state = 1; result = true; goto end_IL_0000; IL_022b: <>m__Finally1(); goto end_IL_0000; } break; } while (true) { if (<>7__wrap6.MoveNext()) { ZoneBlueprintTerrainContact current2 = <>7__wrap6.Current; 5__5.Add(anchor + anchorRotation * new Vector3(current2.LocalX, current2.LocalY, current2.LocalZ)); 5__4++; if (5__4 >= 250) { 5__4 = 0; <>2__current = null; <>1__state = 2; result = true; break; } continue; } <>m__Finally2(); <>7__wrap6 = default(List.Enumerator); onComplete(new BlueprintLoadPlan(5__2, 5__3, 5__5), ""); result = false; break; } end_IL_0000:; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>7__wrap5).Dispose(); } private void <>m__Finally2() { <>1__state = -1; ((IDisposable)<>7__wrap6).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__13 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public string name; public Action onComplete; public Vector3 anchor; public Quaternion anchorRotation; private <>c__DisplayClass13_0 <>8__1; public Player player; private <>c__DisplayClass13_1 <>8__2; public Dictionary depositedMaterials; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__13(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>8__1 = null; <>8__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: { <>1__state = -1; <>8__1 = new <>c__DisplayClass13_0(); ZoneBlueprintFile blueprint; try { blueprint = LoadPlanBlueprint(name); } catch (Exception ex) { onComplete(HomesteadCommandResult.Fail(ex.Message)); return false; } <>8__1.plan = null; <>8__1.planError = ""; <>2__current = CreateLoadPlanAsync(blueprint, anchor, anchorRotation, delegate(BlueprintLoadPlan? value, string error) { <>8__1.plan = value; <>8__1.planError = error; }); <>1__state = 1; return true; } case 1: { <>1__state = -1; if (<>8__1.plan == null) { onComplete(HomesteadCommandResult.Fail(string.IsNullOrWhiteSpace(<>8__1.planError) ? HomesteadLocalization.Format("hs_blueprint_load_failed_plain", name) : <>8__1.planError)); return false; } if (<>8__1.plan.Entries.Count == 0) { onComplete(HomesteadCommandResult.Fail(HomesteadLocalization.Format("hs_blueprint_no_valid_entries", name))); return false; } if (!ZoneLimitCompat.CanAddWearNTears(<>8__1.plan.Positions, out string reason)) { onComplete(HomesteadCommandResult.Fail(reason)); return false; } if (!player.NoCostCheat()) { <>8__2 = new <>c__DisplayClass13_1(); <>8__2.accessReason = ""; <>2__current = ValidateBuildAccessWithoutInventoryAsync(player, <>8__1.plan.Entries, delegate(string value) { <>8__2.accessReason = value; }); <>1__state = 2; return true; } goto IL_0318; } case 2: <>1__state = -1; if (!string.IsNullOrEmpty(<>8__2.accessReason)) { onComplete(HomesteadCommandResult.Fail(<>8__2.accessReason)); return false; } <>8__2.requirements = new List(); <>2__current = CollectRequirementsAsync(<>8__1.plan.Entries, delegate(List value) { <>8__2.requirements = value; }); <>1__state = 3; return true; case 3: <>1__state = -1; foreach (ZoneBlueprintRequirement requirement in <>8__2.requirements) { depositedMaterials.TryGetValue(requirement.ItemName, out var value2); if (value2 < requirement.Amount) { onComplete(HomesteadCommandResult.Fail(HomesteadLocalization.Format("hs_blueprint_missing_deposited", HomesteadLocalization.MaybeLocalize(requirement.DisplayName), value2, requirement.Amount))); return false; } } <>8__2 = null; goto IL_0318; case 4: <>1__state = -1; goto IL_0385; case 5: { <>1__state = -1; onComplete(HomesteadCommandResult.Ok(HomesteadLocalization.Format("hs_blueprint_confirmed", name, <>8__1.created, <>8__1.terrainApplied ? HomesteadLocalization.Text("hs_common_yes") : HomesteadLocalization.Text("hs_common_no")))); return false; } IL_0385: <>8__1.created = 0; <>2__current = SpawnPlanAsync(<>8__1.plan, player, delegate(int value) { <>8__1.created = value; }); <>1__state = 5; return true; IL_0318: <>8__1.terrainApplied = false; if (BlueprintConfig.ShouldApplyTerrainSupport(player) && <>8__1.plan.SupportContacts.Count > 0) { <>2__current = BlueprintTerrainApplier.ApplySupportContactsAsync(<>8__1.plan.SupportContacts, delegate(bool result) { <>8__1.terrainApplied = result; }); <>1__state = 4; return true; } goto IL_0385; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__36 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Player player; public BlueprintLoadPlan plan; public Action onComplete; private long 5__2; private string 5__3; private int 5__4; private int 5__5; private List.Enumerator <>7__wrap5; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__36(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } 5__3 = null; <>7__wrap5 = default(List.Enumerator); <>1__state = -2; } private bool MoveNext() { //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__2 = player.GetPlayerID(); 5__3 = player.GetPlayerName(); 5__4 = 0; 5__5 = 0; <>7__wrap5 = plan.Entries.GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; break; } while (<>7__wrap5.MoveNext()) { BlueprintLoadEntry current = <>7__wrap5.Current; SavedZdoData data = (string.IsNullOrEmpty(current.Entry.Data) ? new SavedZdoData() : new SavedZdoData(current.Entry.Data)); SanitizeBlueprintData(data); ZDO val = SavedZdoHelper.Init(current.Prefab, current.Position, current.Rotation, current.Scale, data, EmptyParameters); if (val != null) { val.Set(ZDOVars.s_creator, 5__2); val.Set(ZDOVars.s_creatorName, 5__3); val.Set(BlueprintPlacedHash, true); ZNetScene.instance.CreateObject(val); 5__4++; } 5__5++; if (5__5 >= 250) { 5__5 = 0; <>2__current = null; <>1__state = 1; return true; } } <>m__Finally1(); <>7__wrap5 = default(List.Enumerator); onComplete(5__4); return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>7__wrap5).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__40 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public IEnumerable entries; public Player player; public Action onComplete; private int 5__2; private IEnumerator <>7__wrap2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__40(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <>7__wrap2 = null; <>1__state = -2; } private bool MoveNext() { //IL_00cb: Unknown result type (might be due to invalid IL or missing references) bool result; try { switch (<>1__state) { default: result = false; goto end_IL_0000; case 0: <>1__state = -1; 5__2 = 0; <>7__wrap2 = entries.GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; break; } while (true) { if (<>7__wrap2.MoveNext()) { BlueprintLoadEntry current = <>7__wrap2.Current; Piece component = current.Prefab.GetComponent(); if ((Object)(object)component != (Object)null) { if (!player.HaveRequirements(component, (RequirementMode)1)) { onComplete(HomesteadLocalization.Format("hs_blueprint_missing_known_station_or_materials", current.Entry.Prefab)); result = false; } else { if (!((Object)(object)component.m_craftingStation != (Object)null) || Object.op_Implicit((Object)(object)CraftingStation.HaveBuildStationInRange(component.m_craftingStation.m_name, ((Component)player).transform.position)) || ZoneSystem.instance.GetGlobalKey((GlobalKeys)22)) { goto IL_0117; } onComplete(HomesteadLocalization.Format("hs_blueprint_missing_crafting_station", current.Entry.Prefab)); result = false; } <>m__Finally1(); break; } goto IL_0117; } <>m__Finally1(); <>7__wrap2 = null; onComplete(""); result = false; break; IL_0117: 5__2++; if (5__2 >= 250) { 5__2 = 0; <>2__current = null; <>1__state = 1; result = true; break; } } end_IL_0000:; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>7__wrap2 != null) { <>7__wrap2.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private const int BlueprintPlanBatchSize = 250; private const string BlueprintPieceMarkerKey = "sighsorry.Homestead.blueprint_piece"; private static readonly int BlueprintPlacedHash = StringExtensionMethods.GetStableHashCode("sighsorry.Homestead.blueprint_piece"); private static readonly Dictionary EmptyParameters = new Dictionary(); private static readonly Dictionary BuildRecipeCache = new Dictionary(StringComparer.Ordinal); private static ManualLogSource _logger = null; private static bool _initialized; private static int _buildRecipeCacheObjectDbCount = -1; public static void Initialize(ManualLogSource logger) { if (!_initialized) { _initialized = true; _logger = logger; ZoneBlueprintPlanRpc.Initialize(logger); } } internal static HomesteadCommandResult SaveSelectedBlueprint(string name, Player player) { EnsureWorldReady(); name = (name ?? "").Trim(); if (string.IsNullOrWhiteSpace(name)) { return HomesteadCommandResult.Fail(HomesteadLocalization.Text("hs_blueprint_name_required")); } if (!ZoneBlueprintSaveTool.TryGetSelectedBlueprint(name, player, out ZoneBlueprintFile blueprint, out string reason)) { return HomesteadCommandResult.Fail(reason); } if (blueprint.Entries.Count == 0) { return HomesteadCommandResult.Fail(HomesteadLocalization.Text("hs_blueprint_no_selected_wearnttear")); } string text = SaveBlueprint(name, blueprint); return HomesteadCommandResult.Ok(HomesteadLocalization.Format("hs_blueprint_saved_to_path", name, blueprint.Entries.Count, blueprint.TerrainContacts.Count, text)); } internal static HomesteadCommandResult PlaceBlueprintPlanAt(string name, Player player, Vector3 anchor, Quaternion anchorRotation) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: 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) return PlaceBlueprintPlanAt(name, player, anchor, anchorRotation, anchorRotation); } internal static HomesteadCommandResult PlaceBlueprintPlanAt(string name, Player player, Vector3 anchor, Quaternion anchorRotation, Quaternion chestRotation) { //IL_0008: 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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_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_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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_0084: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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) ZoneBlueprintFile blueprint = LoadBlueprint(name); Vector3 planChestPosition = GetPlanChestPosition(blueprint, anchor, anchorRotation, chestRotation); if ((Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsServer()) { ZoneBlueprintPlanRpc.RequestPlace(name, blueprint, anchor, anchorRotation, planChestPosition, chestRotation); return HomesteadCommandResult.Ok(HomesteadLocalization.Format("hs_blueprint_plan_request_sent", name)); } if (CreateLoadPlan(blueprint, anchor, anchorRotation).Entries.Count == 0) { return HomesteadCommandResult.Fail(HomesteadLocalization.Format("hs_blueprint_no_valid_entries", name)); } return ZoneBlueprintPlanChestPrefab.PlacePlanChest(name, player, anchor, anchorRotation, planChestPosition, chestRotation); } internal static HomesteadCommandResult FinalizeBlueprintPlan(string name, Player player, Vector3 anchor, Quaternion anchorRotation, IReadOnlyDictionary depositedMaterials) { //IL_0006: 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) BlueprintLoadPlan blueprintLoadPlan = CreateLoadPlan(LoadBlueprint(name), anchor, anchorRotation); if (blueprintLoadPlan.Entries.Count == 0) { return HomesteadCommandResult.Fail(HomesteadLocalization.Format("hs_blueprint_no_valid_entries", name)); } if (!ZoneLimitCompat.CanAddWearNTears(blueprintLoadPlan.Positions, out string reason)) { return HomesteadCommandResult.Fail(reason); } if (!player.NoCostCheat()) { string text = ValidateBuildAccessWithoutInventory(player, blueprintLoadPlan.Entries); if (!string.IsNullOrEmpty(text)) { return HomesteadCommandResult.Fail(text); } foreach (ZoneBlueprintRequirement item in CollectRequirements(blueprintLoadPlan)) { depositedMaterials.TryGetValue(item.ItemName, out var value); if (value < item.Amount) { return HomesteadCommandResult.Fail(HomesteadLocalization.Format("hs_blueprint_missing_deposited", HomesteadLocalization.MaybeLocalize(item.DisplayName), value, item.Amount)); } } } bool flag = false; if (BlueprintConfig.ShouldApplyTerrainSupport(player) && blueprintLoadPlan.SupportContacts.Count > 0) { flag = BlueprintTerrainApplier.ApplySupportContacts(blueprintLoadPlan.SupportContacts); } int num = SpawnPlan(blueprintLoadPlan, player); return HomesteadCommandResult.Ok(HomesteadLocalization.Format("hs_blueprint_confirmed", name, num, flag ? HomesteadLocalization.Text("hs_common_yes") : HomesteadLocalization.Text("hs_common_no"))); } [IteratorStateMachine(typeof(d__13))] internal static IEnumerator FinalizeBlueprintPlanAsync(string name, Player player, Vector3 anchor, Quaternion anchorRotation, Dictionary depositedMaterials, Action onComplete) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: 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) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__13(0) { name = name, player = player, anchor = anchor, anchorRotation = anchorRotation, depositedMaterials = depositedMaterials, onComplete = onComplete }; } internal static List GetBlueprintNames() { string worldBlueprintDirectory = GetWorldBlueprintDirectory(); if (!Directory.Exists(worldBlueprintDirectory)) { return new List(); } return (from path in Directory.GetFiles(worldBlueprintDirectory, "*.hsbp.yml") select Path.GetFileName(path).Replace(".hsbp.yml", "")).OrderBy((string name) => name, StringComparer.OrdinalIgnoreCase).ToList(); } internal static bool TryLoadBlueprint(string name, out ZoneBlueprintFile blueprint) { try { blueprint = LoadBlueprint(name); return true; } catch { blueprint = null; return false; } } internal static string SerializeBlueprintForStore(string name) { return HomesteadYaml.Serialize(LoadBlueprint(name)); } internal static string SaveBlueprintFromStore(string preferredName, ZoneBlueprintFile blueprint) { string name = (blueprint.Name = GetUniqueBlueprintName(preferredName)); return SaveBlueprint(name, blueprint); } internal static List FindBlueprintWearNTearZdos(Player player, ZoneAreaSelection selection, BlueprintAreaSaveCreatorMode creatorMode) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) long playerID = player.GetPlayerID(); List list = new List(); List list2 = new List(); ZoneAreaTargetOverlay.CollectNearbyZdos(selection, list2); foreach (ZDO item in list2) { if (!IsHomesteadBlueprintChest(item) && TryReadSavableWearNTear(item, out GameObject _) && selection.Contains(item.GetPosition())) { long @long = item.GetLong(ZDOVars.s_creator, 0L); if (IsAreaSaveCreatorAllowed(playerID, @long, creatorMode)) { list.Add(item); } } } return list; } internal static bool IsAreaSaveCreatorAllowed(long playerId, long creator, BlueprintAreaSaveCreatorMode creatorMode) { if (creator == playerId) { return true; } return creatorMode switch { BlueprintAreaSaveCreatorMode.AllCreators => true, BlueprintAreaSaveCreatorMode.OwnedAndCreatorless => creator == 0, _ => false, }; } internal static bool IsHomesteadBlueprintChest(ZDO zdo) { if (zdo == null || !zdo.IsValid()) { return false; } int prefab = zdo.GetPrefab(); if (prefab != ZoneBlueprintPlanChestPrefab.PrefabHash) { return ZoneBlueprintStoreChestPrefab.IsStorePrefab(prefab); } return true; } internal static bool IsHomesteadBlueprintChestPrefab(GameObject? prefab) { if (!Object.op_Implicit((Object)(object)prefab)) { return false; } string prefabName = Utils.GetPrefabName(prefab); if (!string.Equals(prefabName, "piece_chest_wood_blueprint", StringComparison.OrdinalIgnoreCase)) { return ZoneBlueprintStoreChestPrefab.IsStorePrefabName(prefabName); } return true; } internal static ZoneBlueprintFile CaptureBlueprintFromZdos(string name, Player player, Vector3 anchor, Quaternion anchorRotation, IEnumerable sourceZdos, float radius) { //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_0006: 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_004a: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: 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_007c: 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_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: 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_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) Quaternion val = Quaternion.Inverse(anchorRotation); List list = new List(); List list2 = new List(); int num = 0; foreach (ZDO item in sourceZdos.ToList()) { if (TryReadSavableWearNTear(item, out GameObject prefab)) { Vector3 position = item.GetPosition(); Quaternion rotation = item.GetRotation(); Vector3 val2 = ReadScale(item, prefab); SavedZdoData savedZdoData = new SavedZdoData(item); SanitizeBlueprintData(savedZdoData); Vector3 value = val * (position - anchor); Quaternion value2 = val * rotation; list.Add(new ZoneBlueprintEntry { SaveId = $"w{++num:D4}", Prefab = Utils.GetPrefabName(prefab), LocalPos = ToArray(value), LocalRot = ToArray(value2), Scale = ToArray(val2), Data = savedZdoData.GetBase64(EmptyParameters) }); list2.Add(new TerrainContactSource(prefab, position, rotation, val2)); } } return new ZoneBlueprintFile { Name = name, World = GetWorldName(), SavedAt = HomesteadTimestamp.Now(), Radius = radius, Entries = list.OrderBy((ZoneBlueprintEntry entry) => entry.Prefab, StringComparer.Ordinal).ThenBy((ZoneBlueprintEntry entry) => entry.LocalPos[0]).ThenBy((ZoneBlueprintEntry entry) => entry.LocalPos[2]) .ThenBy((ZoneBlueprintEntry entry) => entry.LocalPos[1]) .ToList(), TerrainContacts = BlueprintTerrainApplier.CaptureContacts(anchor, val, list2) }; } internal static ZoneBlueprintFile LoadBlueprintForPlan(string name) { return LoadPlanBlueprint(name); } internal static BlueprintLoadPlan CreateLoadPlanForBlueprint(string name, Vector3 anchor, Quaternion anchorRotation) { //IL_0006: 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) return CreateLoadPlan(LoadPlanBlueprint(name), anchor, anchorRotation); } internal static BlueprintLoadPlan CreateLoadPlanForBlueprint(ZoneBlueprintFile blueprint, Vector3 anchor, Quaternion anchorRotation) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) return CreateLoadPlan(blueprint, anchor, anchorRotation); } internal static HomesteadCommandResult SaveUploadedBlueprintForPlan(string preferredName, ZoneBlueprintFile blueprint, long playerId, out string savedName) { savedName = ""; string text = ValidateBlueprintFile(blueprint); if (!string.IsNullOrWhiteSpace(text)) { return HomesteadCommandResult.Fail(text); } string text2 = SanitizePathSegment(string.IsNullOrWhiteSpace(preferredName) ? blueprint.Name : preferredName); string planGhostBlueprintPath = GetPlanGhostBlueprintPath(text2); Directory.CreateDirectory(Path.GetDirectoryName(planGhostBlueprintPath)); blueprint.World = GetWorldName(); if (File.Exists(planGhostBlueprintPath)) { try { string a = HomesteadYaml.Serialize(HomesteadYaml.Deserialize(File.ReadAllText(planGhostBlueprintPath))); string b = HomesteadYaml.Serialize(CloneForName(blueprint, text2)); if (string.Equals(a, b, StringComparison.Ordinal)) { savedName = text2; return HomesteadCommandResult.Ok(HomesteadLocalization.Format("hs_blueprint_server_already_has", savedName)); } } catch { } text2 = GetUniquePlanGhostBlueprintName($"{text2}_p{Math.Abs(playerId)}"); } blueprint.Name = text2; string planGhostBlueprintPath2 = GetPlanGhostBlueprintPath(text2); Directory.CreateDirectory(Path.GetDirectoryName(planGhostBlueprintPath2)); File.WriteAllText(planGhostBlueprintPath2, HomesteadYaml.Serialize(blueprint)); savedName = text2; return HomesteadCommandResult.Ok(HomesteadLocalization.Format("hs_blueprint_uploaded_to_server", savedName)); } internal static string SerializePreviewBlueprintForPlan(string name) { if (!ZoneBlueprintNetworkPayload.TryCreatePreviewYaml(LoadPlanBlueprint(name), out string previewYaml, out string reason)) { throw new InvalidOperationException(reason); } return previewYaml; } internal static void EnsureLocalPlanBlueprintCopy(string name, string blueprintYaml) { if (!string.IsNullOrWhiteSpace(name) && !string.IsNullOrWhiteSpace(blueprintYaml)) { ZoneBlueprintFile zoneBlueprintFile = HomesteadYaml.Deserialize(blueprintYaml); zoneBlueprintFile.Name = name; string planGhostBlueprintPath = GetPlanGhostBlueprintPath(name); Directory.CreateDirectory(Path.GetDirectoryName(planGhostBlueprintPath)); File.WriteAllText(planGhostBlueprintPath, HomesteadYaml.Serialize(zoneBlueprintFile)); } } internal static List CollectRequirements(BlueprintLoadPlan plan) { return CollectRequirements(plan.Entries); } internal static List CollectCraftingStations(BlueprintLoadPlan plan) { Dictionary dictionary = new Dictionary(StringComparer.Ordinal); foreach (BlueprintLoadEntry entry in plan.Entries) { Piece component = entry.Prefab.GetComponent(); CraftingStation val = (((Object)(object)component != (Object)null) ? component.m_craftingStation : null); if (!((Object)(object)val == (Object)null)) { string name = val.m_name; if (!string.IsNullOrWhiteSpace(name) && !dictionary.ContainsKey(name)) { dictionary[name] = new ZoneBlueprintCraftingStationRequirement { StationName = name, PrefabName = Utils.GetPrefabName(((Component)val).gameObject), DisplayName = name }; } } } return dictionary.Values.OrderBy((ZoneBlueprintCraftingStationRequirement station) => station.StationName, StringComparer.Ordinal).ToList(); } internal static Vector3 GetPlanChestPosition(ZoneBlueprintFile blueprint, Vector3 anchor, Quaternion anchorRotation) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: 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) return GetPlanChestPosition(blueprint, anchor, anchorRotation, anchorRotation); } internal static Vector3 GetPlanChestPosition(ZoneBlueprintFile blueprint, Vector3 anchor, Quaternion anchorRotation, Quaternion chestRotation) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: 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_0101: Unknown result type (might be due to invalid IL or missing references) if (blueprint.Entries.Count == 0) { return anchor; } Quaternion inverseChestRotation = Quaternion.Inverse(chestRotation); List source = blueprint.Entries.Select((ZoneBlueprintEntry entry) => inverseChestRotation * (anchorRotation * FromVector(entry.LocalPos))).ToList(); float num = source.Min((Vector3 position) => position.x); float num2 = source.Max((Vector3 position) => position.x); float num3 = source.Min((Vector3 position) => position.z); Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor((num + num2) * 0.5f, 0f, num3 - 2.5f); Vector3 val2 = anchor + chestRotation * val; val2.y = SampleGroundY(val2.x, val2.z, anchor.y); return val2; } private static BlueprintLoadPlan CreateLoadPlan(ZoneBlueprintFile blueprint, Vector3 anchor, Quaternion anchorRotation) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //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) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) List list = new List(); List list2 = new List(); foreach (ZoneBlueprintEntry entry in blueprint.Entries) { GameObject prefab = ZNetScene.instance.GetPrefab(entry.Prefab); if (!Object.op_Implicit((Object)(object)prefab)) { throw new InvalidOperationException("Missing prefab '" + entry.Prefab + "' while loading blueprint '" + blueprint.Name + "'."); } if (!((Object)(object)prefab.GetComponent() == (Object)null) && HasBuildRecipe(prefab)) { Vector3 val = anchor + anchorRotation * FromVector(entry.LocalPos); Quaternion rotation = anchorRotation * FromQuaternion(entry.LocalRot); Vector3 scale = FromVector(entry.Scale); list.Add(new BlueprintLoadEntry(entry, prefab, val, rotation, scale)); list2.Add(val); } } List supportContacts = blueprint.TerrainContacts.Select((ZoneBlueprintTerrainContact contact) => anchor + anchorRotation * new Vector3(contact.LocalX, contact.LocalY, contact.LocalZ)).ToList(); return new BlueprintLoadPlan(list, list2, supportContacts); } [IteratorStateMachine(typeof(d__34))] private static IEnumerator CreateLoadPlanAsync(ZoneBlueprintFile blueprint, Vector3 anchor, Quaternion anchorRotation, Action onComplete) { //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) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__34(0) { blueprint = blueprint, anchor = anchor, anchorRotation = anchorRotation, onComplete = onComplete }; } private static int SpawnPlan(BlueprintLoadPlan plan, Player player) { //IL_0067: 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_0075: Unknown result type (might be due to invalid IL or missing references) long playerID = player.GetPlayerID(); string playerName = player.GetPlayerName(); int num = 0; foreach (BlueprintLoadEntry entry in plan.Entries) { SavedZdoData data = (string.IsNullOrEmpty(entry.Entry.Data) ? new SavedZdoData() : new SavedZdoData(entry.Entry.Data)); SanitizeBlueprintData(data); ZDO val = SavedZdoHelper.Init(entry.Prefab, entry.Position, entry.Rotation, entry.Scale, data, EmptyParameters); if (val != null) { val.Set(ZDOVars.s_creator, playerID); val.Set(ZDOVars.s_creatorName, playerName); val.Set(BlueprintPlacedHash, true); ZNetScene.instance.CreateObject(val); num++; } } return num; } [IteratorStateMachine(typeof(d__36))] private static IEnumerator SpawnPlanAsync(BlueprintLoadPlan plan, Player player, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__36(0) { plan = plan, player = player, onComplete = onComplete }; } private static List CollectRequirements(IEnumerable entries) { Dictionary dictionary = new Dictionary(); foreach (BlueprintLoadEntry entry in entries) { Piece component = entry.Prefab.GetComponent(); if ((Object)(object)component == (Object)null) { continue; } Requirement[] resources = component.m_resources; foreach (Requirement val in resources) { if (Object.op_Implicit((Object)(object)val.m_resItem) && val.m_amount > 0) { string name = val.m_resItem.m_itemData.m_shared.m_name; if (!dictionary.TryGetValue(name, out var value)) { value = (dictionary[name] = new ZoneBlueprintRequirement { ItemName = name, PrefabName = Utils.GetPrefabName(((Component)val.m_resItem).gameObject), DisplayName = val.m_resItem.m_itemData.m_shared.m_name }); } value.Amount += val.GetAmount(0); } } } return dictionary.Values.OrderBy((ZoneBlueprintRequirement requirement) => requirement.ItemName, StringComparer.Ordinal).ToList(); } [IteratorStateMachine(typeof(d__38))] private static IEnumerator CollectRequirementsAsync(IEnumerable entries, Action> onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__38(0) { entries = entries, onComplete = onComplete }; } private static string ValidateBuildAccessWithoutInventory(Player player, IEnumerable entries) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) foreach (BlueprintLoadEntry entry in entries) { Piece component = entry.Prefab.GetComponent(); if (!((Object)(object)component == (Object)null)) { if (!player.HaveRequirements(component, (RequirementMode)1)) { return HomesteadLocalization.Format("hs_blueprint_missing_known_station_or_materials", entry.Entry.Prefab); } if ((Object)(object)component.m_craftingStation != (Object)null && !Object.op_Implicit((Object)(object)CraftingStation.HaveBuildStationInRange(component.m_craftingStation.m_name, ((Component)player).transform.position)) && !ZoneSystem.instance.GetGlobalKey((GlobalKeys)22)) { return HomesteadLocalization.Format("hs_blueprint_missing_crafting_station", entry.Entry.Prefab); } } } return ""; } [IteratorStateMachine(typeof(d__40))] private static IEnumerator ValidateBuildAccessWithoutInventoryAsync(Player player, IEnumerable entries, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__40(0) { player = player, entries = entries, onComplete = onComplete }; } internal static bool TryReadWearNTear(ZDO zdo, out GameObject prefab) { prefab = null; if (zdo == null || !zdo.IsValid()) { return false; } prefab = ZNetScene.instance.GetPrefab(zdo.GetPrefab()); if (Object.op_Implicit((Object)(object)prefab) && (Object)(object)prefab.GetComponent() != (Object)null) { return (Object)(object)prefab.GetComponent() != (Object)null; } return false; } internal static bool TryReadSavableWearNTear(ZDO zdo, out GameObject prefab) { if (TryReadWearNTear(zdo, out prefab)) { return HasBuildRecipe(prefab); } return false; } internal static bool HasBuildRecipe(GameObject? prefab) { if (!Object.op_Implicit((Object)(object)prefab)) { return false; } Piece component = prefab.GetComponent(); if ((Object)(object)component == (Object)null || component.m_resources == null) { return false; } if (HasResourceCost(component)) { return IsRegisteredPlayerBuildPiece(prefab); } return false; } private static bool HasResourceCost(Piece piece) { return piece.m_resources.Any((Requirement requirement) => Object.op_Implicit((Object)(object)requirement.m_resItem) && requirement.m_amount > 0); } private static bool IsRegisteredPlayerBuildPiece(GameObject prefab) { string prefabName = Utils.GetPrefabName(prefab); if (string.IsNullOrWhiteSpace(prefabName)) { return false; } ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance == (Object)null || instance.m_items == null) { return false; } if (_buildRecipeCacheObjectDbCount != instance.m_items.Count) { BuildRecipeCache.Clear(); _buildRecipeCacheObjectDbCount = instance.m_items.Count; } if (BuildRecipeCache.TryGetValue(prefabName, out var value)) { return value; } foreach (GameObject item in instance.m_items) { PieceTable val = (Object.op_Implicit((Object)(object)item) ? item.GetComponent() : null)?.m_itemData.m_shared.m_buildPieces; if (val?.m_pieces != null && val.m_pieces.Any((GameObject piecePrefab) => Object.op_Implicit((Object)(object)piecePrefab) && string.Equals(Utils.GetPrefabName(piecePrefab), prefabName, StringComparison.Ordinal))) { BuildRecipeCache[prefabName] = true; return true; } } BuildRecipeCache[prefabName] = false; return false; } private static void SanitizeBlueprintData(SavedZdoData data) { //IL_0001: 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) data.OriginalId = ZDOID.None; data.TargetConnectionId = ZDOID.None; data.ConnectionHash = 0; data.ConnectionType = (ConnectionType)0; RemoveKey(data, ZDOVars.s_creator); RemoveKey(data, ZDOVars.s_creatorName); RemoveKey(data, ZDOVars.s_health); RemoveKey(data, ZDOVars.s_support); RemoveKey(data, ZDOVars.s_inUse); RemoveKey(data, ZDOVars.s_user); KeyValuePair s_zdoidUser = ZDOVars.s_zdoidUser; RemoveKey(data, s_zdoidUser.Key); s_zdoidUser = ZDOVars.s_zdoidUser; RemoveKey(data, s_zdoidUser.Value); RemoveKey(data, ZDOVars.s_bodyAVelHash); RemoveKey(data, ZDOVars.s_bodyVelHash); RemoveKey(data, ZDOVars.s_bodyVelocity); RemoveKey(data, ZDOVars.s_velHash); RemoveKey(data, ZDOVars.s_initVel); RemoveKey(data, ZDOVars.s_forward); RemoveKey(data, ZDOVars.s_landed); RemoveKey(data, ZDOVars.s_inWater); RemoveKey(data, ZDOVars.s_hitDir); RemoveKey(data, ZDOVars.s_hitPoint); RemoveKey(data, ZDOVars.s_startTime); RemoveKey(data, ZDOVars.s_lastTime); RemoveKey(data, ZDOVars.s_aliveTime); RemoveKey(data, ZDOVars.s_accTime); RemoveKey(data, ZDOVars.s_worldTimeHash); } private static void RemoveKey(SavedZdoData data, int hash) { data.Strings?.Remove(hash); data.Floats?.Remove(hash); data.Ints?.Remove(hash); data.Bools?.Remove(hash); data.Hashes?.Remove(hash); data.Longs?.Remove(hash); data.Vecs?.Remove(hash); data.Quats?.Remove(hash); data.ByteArrays?.Remove(hash); } private static ZoneBlueprintFile LoadBlueprint(string name) { string blueprintPath = GetBlueprintPath(name); if (!File.Exists(blueprintPath)) { throw new FileNotFoundException("Homestead blueprint not found: " + blueprintPath); } return HomesteadYaml.Deserialize(File.ReadAllText(blueprintPath)); } private static ZoneBlueprintFile LoadPlanBlueprint(string name) { string planGhostBlueprintPath = GetPlanGhostBlueprintPath(name); if (File.Exists(planGhostBlueprintPath)) { return HomesteadYaml.Deserialize(File.ReadAllText(planGhostBlueprintPath)); } return LoadBlueprint(name); } private static string SaveBlueprint(string name, ZoneBlueprintFile blueprint) { string blueprintPath = GetBlueprintPath(name); Directory.CreateDirectory(Path.GetDirectoryName(blueprintPath)); File.WriteAllText(blueprintPath, HomesteadYaml.Serialize(blueprint)); bool iconReady = false; try { iconReady = (Object)(object)ZoneBlueprintVisuals.RenderAndCacheIcon(name, blueprint) != (Object)null; } catch (Exception ex) { _logger.LogWarning((object)("Failed to render Homestead blueprint icon '" + name + "' immediately: " + ex.Message)); } ZoneBlueprintSaveToolMenu.RefreshAfterBlueprintSaved(name, blueprint, iconReady); return blueprintPath; } private static ZoneBlueprintFile CloneForName(ZoneBlueprintFile blueprint, string name) { return new ZoneBlueprintFile { Version = blueprint.Version, Name = name, World = blueprint.World, SavedAt = blueprint.SavedAt, Radius = blueprint.Radius, Entries = blueprint.Entries.Select((ZoneBlueprintEntry entry) => new ZoneBlueprintEntry { SaveId = entry.SaveId, Prefab = entry.Prefab, LocalPos = entry.LocalPos.ToArray(), LocalRot = entry.LocalRot.ToArray(), Scale = entry.Scale.ToArray(), Data = entry.Data }).ToList(), TerrainContacts = blueprint.TerrainContacts.Select((ZoneBlueprintTerrainContact contact) => new ZoneBlueprintTerrainContact { LocalX = contact.LocalX, LocalY = contact.LocalY, LocalZ = contact.LocalZ }).ToList() }; } private static string ValidateBlueprintFile(ZoneBlueprintFile blueprint) { if (blueprint.Entries.Count == 0) { return HomesteadLocalization.Text("hs_blueprint_no_entries"); } if (!ZoneBlueprintNetworkPayload.TryValidateBlueprintEntryCount(blueprint, upload: true, out string reason)) { return reason; } if ((Object)(object)ZNetScene.instance == (Object)null) { return HomesteadLocalization.Text("hs_common_world_not_ready"); } foreach (ZoneBlueprintEntry entry in blueprint.Entries) { GameObject prefab = ZNetScene.instance.GetPrefab(entry.Prefab); if (!Object.op_Implicit((Object)(object)prefab) || (Object)(object)prefab.GetComponent() == (Object)null || !HasBuildRecipe(prefab)) { return HomesteadLocalization.Format("hs_blueprint_unsupported_prefab", entry.Prefab); } } return ""; } private static string GetUniqueBlueprintName(string preferredName) { string text = SanitizePathSegment(string.IsNullOrWhiteSpace(preferredName) ? "store_blueprint" : preferredName.Trim()); string text2 = text; int num = 2; while (File.Exists(GetBlueprintPath(text2))) { text2 = $"{text}_{num++}"; } return text2; } private static string GetUniquePlanGhostBlueprintName(string preferredName) { string text = SanitizePathSegment(string.IsNullOrWhiteSpace(preferredName) ? "plan_ghost" : preferredName.Trim()); string text2 = text; int num = 2; while (File.Exists(GetPlanGhostBlueprintPath(text2))) { text2 = $"{text}_{num++}"; } return text2; } private static void EnsureWorldReady() { if ((Object)(object)ZNet.instance == (Object)null || (Object)(object)ZNetScene.instance == (Object)null || ZDOMan.instance == null || (Object)(object)ZoneSystem.instance == (Object)null) { throw new InvalidOperationException("World is not ready."); } } private static string GetBlueprintPath(string name) { return Path.Combine(GetWorldBlueprintDirectory(), SanitizePathSegment(name) + ".hsbp.yml"); } private static string GetPlanGhostBlueprintPath(string name) { return Path.Combine(GetPlanGhostBlueprintDirectory(), SanitizePathSegment(name) + ".hsbp.yml"); } internal static string GetBlueprintIconPath(string name) { return Path.Combine(GetWorldBlueprintDirectory(), SanitizePathSegment(name) + ".hsbp.png"); } private static string GetWorldBlueprintDirectory() { return HomesteadPlugin.BlueprintStorageFullPath; } private static string GetPlanGhostBlueprintDirectory() { return HomesteadPlugin.PlanGhostStorageFullPath; } private static string GetWorldName() { ZNet instance = ZNet.instance; return ((instance != null) ? instance.GetWorldName() : null) ?? "unknown"; } private static string SanitizePathSegment(string value) { char[] invalidChars = Path.GetInvalidFileNameChars(); string text = new string(value.Select((char character) => (!invalidChars.Contains(character)) ? character : '_').ToArray()).Trim(); if (text.Length == 0) { throw new InvalidOperationException("Blueprint name resolves to an empty path segment."); } return text; } private static Vector3 ReadScale(ZDO zdo, GameObject prefab) { //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) return zdo.GetVec3(ZDOVars.s_scaleHash, prefab.transform.localScale); } private static float[] ToArray(Vector3 value) { //IL_0008: 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_0024: Unknown result type (might be due to invalid IL or missing references) return new float[3] { Round(value.x), Round(value.y), Round(value.z) }; } private static float[] ToArray(Quaternion value) { //IL_0008: 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_0024: 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) return new float[4] { Round(value.x), Round(value.y), Round(value.z), Round(value.w) }; } private static Vector3 FromVector(float[] value) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) return new Vector3(value[0], value[1], value[2]); } private static Quaternion FromQuaternion(float[] value) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) return new Quaternion(value[0], value[1], value[2], value[3]); } private static float Round(float value) { return Mathf.Round(value * 1000f) / 1000f; } private static float SampleGroundY(float x, float z, float fallbackY) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZoneSystem.instance == (Object)null) { return fallbackY; } Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(x, fallbackY, z); Vector3 val2 = default(Vector3); Biome val3 = default(Biome); BiomeArea val4 = default(BiomeArea); Heightmap val5 = default(Heightmap); ZoneSystem.instance.GetGroundData(ref val, ref val2, ref val3, ref val4, ref val5); return val.y; } } internal static class ZoneDvergrCirclet { [HarmonyPatch(typeof(ObjectDB), "Awake")] private static class ObjectDbAwakePatch { private static void Postfix() { PatchObjectDbItem(); } } [HarmonyPatch(typeof(ItemDrop), "Awake")] private static class ItemDropAwakePatch { private static void Postfix(ItemDrop __instance) { PatchItemData(__instance.m_itemData, initializeDurability: true); } } [HarmonyPatch(typeof(ItemDrop), "Start")] private static class ItemDropStartPatch { private static void Postfix(ItemDrop __instance) { PatchItemData(__instance.m_itemData, initializeDurability: true); } } [HarmonyPatch(typeof(Inventory), "Load")] private static class InventoryLoadPatch { private static void Postfix(Inventory __instance) { PatchInventoryItems(__instance); } } [HarmonyPatch(typeof(Inventory), "Changed")] private static class InventoryChangedPatch { private static void Postfix(Inventory __instance) { PatchInventoryItems(__instance); } } [HarmonyPatch(typeof(VisEquipment), "AttachItem")] private static class VisEquipmentAttachItemPatch { private static void Postfix(VisEquipment __instance, GameObject __result, int itemHash) { if (Active && Object.op_Implicit((Object)(object)__result) && itemHash == PrefabHash) { ItemData val = TryGetVisualHelmetItem(__instance); ZNetView nview; if (val != null) { PatchItemData(val, initializeDurability: true); (__result.GetComponent() ?? __result.AddComponent()).Initialize(val); } else if (TryGetRemoteCircletNview(__instance, out nview) && (Object)(object)nview != (Object)null) { (__result.GetComponent() ?? __result.AddComponent()).InitializeRemote(nview); } } } } [HarmonyPatch(typeof(VisEquipment), "UpdateEquipmentVisuals")] private static class VisEquipmentUpdateEquipmentVisualsPatch { private static void Postfix(VisEquipment __instance) { if (ShouldSyncRemoteVisuals() && Object.op_Implicit((Object)(object)__instance) && __instance.m_isPlayer && !IsLocalVisEquipment(__instance) && (Object)(object)((Component)__instance).GetComponent() == (Object)null) { ((Component)__instance).gameObject.AddComponent().RefreshNow(); } } } [HarmonyPatch(typeof(Humanoid), "DrainEquipedItemDurability")] private static class HumanoidDrainEquipedItemDurabilityPatch { private static bool Prefix(ItemData item) { if (Active) { return !IsDvergrCircletItem(item); } return true; } } [HarmonyPatch(typeof(Humanoid), "UpdateEquipment")] private static class HumanoidUpdateEquipmentPatch { private static void Postfix(Humanoid __instance, float dt) { if (!Active) { return; } Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val == null || (Object)(object)val != (Object)(object)Player.m_localPlayer || !TryGetEquippedDvergrCirclet(val, out ItemData item) || item == null) { return; } CircletState circletState = LoadState(item); if (PatchItemData(item, initializeDurability: true) && circletState.LightOn && !(item.m_durability <= 0f) && IsCircletLightOn(val, item)) { float durability = item.m_durability; item.m_durability = Mathf.Max(0f, item.m_durability - GetDurabilityDrainPerSecond(item) * dt); if (Mathf.Abs(durability - item.m_durability) > 0.001f) { PublishLocalCircletState(val, item, circletState); } if (durability > 0f && item.m_durability <= 0f) { ((Character)val).Message((MessageType)1, HomesteadLocalization.Text("hs_dvergr_depleted"), 0, item.GetIcon()); ((Humanoid)val).GetInventory().Changed(); } } } } [HarmonyPatch(typeof(Player), "DamageArmorDurability")] private static class PlayerDamageArmorDurabilityPatch { private static void Prefix(Player __instance, ref float __state) { __state = float.NaN; if (TryGetEquippedDvergrCirclet(__instance, out ItemData item) && item != null && Active && PatchItemData(item, initializeDurability: true)) { __state = item.m_durability; } } private static void Postfix(Player __instance, float __state) { if (!float.IsNaN(__state) && TryGetEquippedDvergrCirclet(__instance, out ItemData item) && item != null && IsDvergrCircletItem(item)) { item.m_durability = Mathf.Clamp(__state, 0f, item.GetMaxDurability()); } } } [HarmonyPatch(typeof(InventoryGui), "CanRepair")] private static class InventoryGuiCanRepairPatch { private static bool Prefix(ItemData item, ref bool __result) { if (!Active || !IsDvergrCircletItem(item)) { return true; } PatchItemData(item, initializeDurability: true); Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer) || !item.m_shared.m_canBeReparied) { __result = false; return false; } if (localPlayer.NoCostCheat()) { __result = true; return false; } CraftingStation currentCraftingStation = localPlayer.GetCurrentCraftingStation(); __result = MatchesRepairStation(currentCraftingStation); return false; } } [HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[] { typeof(ItemData), typeof(int), typeof(bool), typeof(float), typeof(int) })] private static class ItemDataGetTooltipPatch { [HarmonyPriority(200)] private static void Postfix(ItemData item, bool crafting, ref string __result) { if (!crafting && Active && PatchItemData(item, initializeDurability: true)) { __result += BuildTooltip(item); } } } private sealed class CircletState { internal bool LightOn = true; internal bool HasFuel = true; internal float IntensityMultiplier = 1f; internal float RangeMultiplier = 1f; } private sealed class ZoneDvergrCircletVisual : MonoBehaviour { private readonly List _lights = new List(); private float[] _baseIntensities = Array.Empty(); private float[] _baseRanges = Array.Empty(); private bool[] _baseEnabled = Array.Empty(); private ItemData? _item; private ZNetView? _remoteStateView; private bool _remoteCulled; internal bool IsFor(ItemData? item) { if ((Object)(object)_remoteStateView == (Object)null && _item == item) { return _lights.Count > 0; } return false; } internal bool IsRemoteFor(ZNetView nview) { if ((Object)(object)_remoteStateView == (Object)(object)nview) { return _lights.Count > 0; } return false; } internal void Initialize(ItemData? item) { _item = item; _remoteStateView = null; _remoteCulled = false; CaptureLights(); Apply(); } internal void InitializeRemote(ZNetView nview) { _item = null; _remoteStateView = nview; _remoteCulled = false; CaptureLights(); Apply(); } internal void SetRemoteCulled(bool culled) { if (!((Object)(object)_remoteStateView == (Object)null) && _remoteCulled != culled) { _remoteCulled = culled; Apply(); } } private void CaptureLights() { _lights.Clear(); ((Component)this).gameObject.GetComponentsInChildren(true, _lights); _baseIntensities = new float[_lights.Count]; _baseRanges = new float[_lights.Count]; _baseEnabled = new bool[_lights.Count]; for (int i = 0; i < _lights.Count; i++) { Light val = _lights[i]; _baseIntensities[i] = (Object.op_Implicit((Object)(object)val) ? val.intensity : 0f); _baseRanges[i] = (Object.op_Implicit((Object)(object)val) ? val.range : 0f); _baseEnabled[i] = Object.op_Implicit((Object)(object)val) && ((Behaviour)val).enabled; } } internal void ApplyNow() { Apply(); } private void LateUpdate() { Apply(); } private void Apply() { CircletState circletState = (((Object)(object)_remoteStateView != (Object)null) ? LoadRemoteState(_remoteStateView) : LoadState(_item)); bool flag = Active && !_remoteCulled && circletState.LightOn && circletState.HasFuel; float intensityMultiplier = circletState.IntensityMultiplier; float rangeMultiplier = circletState.RangeMultiplier; for (int i = 0; i < _lights.Count; i++) { Light val = _lights[i]; if (Object.op_Implicit((Object)(object)val)) { val.intensity = _baseIntensities[i] * intensityMultiplier; val.range = _baseRanges[i] * rangeMultiplier; ((Behaviour)val).enabled = flag && _baseEnabled[i]; } } } } private sealed class ZoneDvergrCircletRemoteVisual : MonoBehaviour { private const float RefreshInterval = 0.25f; private VisEquipment? _visEquipment; private GameObject? _customRoot; private float _nextRefreshTime; private void Awake() { _visEquipment = ((Component)this).GetComponent(); } private void LateUpdate() { if (Time.time >= _nextRefreshTime) { Refresh(force: false); } } private void OnDestroy() { DestroyCustomRoot(); } internal void RefreshNow() { Refresh(force: true); } private void Refresh(bool force) { if (!force && Time.time < _nextRefreshTime) { return; } _nextRefreshTime = Time.time + 0.25f; VisEquipment val = (((Object)(object)_visEquipment != (Object)null) ? _visEquipment : (_visEquipment = ((Component)this).GetComponent())); if (!ShouldSyncRemoteVisuals() || !Object.op_Implicit((Object)(object)val) || !val.m_isPlayer || IsLocalVisEquipment(val) || (Object)(object)val.m_nview == (Object)null || !val.m_nview.IsValid()) { DestroyCustomRoot(); return; } ZNetView nview = val.m_nview; ZDO zDO = nview.GetZDO(); if (zDO == null || zDO.GetInt(RemoteItemKey, 0) != PrefabHash) { CullRemoteVisualComponent(val.m_helmetItemInstance, nview); DestroyCustomRoot(); return; } bool flag = !IsWithinRemoteLightRange(val); if (val.m_currentHelmetItemHash == PrefabHash && Object.op_Implicit((Object)(object)val.m_helmetItemInstance)) { DestroyCustomRoot(); EnsureRemoteVisualComponent(val.m_helmetItemInstance, nview, flag); return; } CullRemoteVisualComponent(val.m_helmetItemInstance, nview); if (flag || !Object.op_Implicit((Object)(object)val.m_helmet)) { DestroyCustomRoot(); return; } if (!Object.op_Implicit((Object)(object)_customRoot)) { try { _customRoot = val.AttachItem(PrefabHash, 0, val.m_helmet, false, false); if (Object.op_Implicit((Object)(object)_customRoot)) { ((Object)_customRoot).name = "HomesteadDvergrCircletRemoteVisual"; ((Object)_customRoot).hideFlags = (HideFlags)52; } } catch (Exception ex) { ManualLogSource? logger = _logger; if (logger != null) { logger.LogWarning((object)("Failed to attach remote Dvergr circlet visual; remote light sync skipped for this refresh. " + ex.GetType().Name + ": " + ex.Message)); } DestroyCustomRoot(); return; } } if (Object.op_Implicit((Object)(object)_customRoot)) { EnsureRemoteVisualComponent(_customRoot, nview, culled: false); } } private void DestroyCustomRoot() { if (Object.op_Implicit((Object)(object)_customRoot)) { Object.Destroy((Object)(object)_customRoot); } _customRoot = null; } } private const string PrefabName = "HelmetDverger"; private const string CircletExtendedGuid = "shudnal.CircletExtended"; private const string InitKey = "sighsorry.Homestead.dvergr_circlet_initialized"; private const string StateKey = "sighsorry.Homestead.dvergr_circlet_state"; private static readonly int RemoteItemKey = StringExtensionMethods.GetStableHashCode("sighsorry.Homestead.dvergr_circlet_item"); private static readonly int RemoteStateKey = StringExtensionMethods.GetStableHashCode("sighsorry.Homestead.dvergr_circlet_remote_state"); private static readonly int RemoteStateHashKey = StringExtensionMethods.GetStableHashCode("sighsorry.Homestead.dvergr_circlet_remote_state_hash"); private static readonly int PrefabHash = StringExtensionMethods.GetStableHashCode("HelmetDverger"); private static readonly List TempLights = new List(); private static readonly List TempVisualRoots = new List(); private static ManualLogSource? _logger; private static bool _loggedCircletExtendedSkip; private static bool? _circletExtendedLoaded; private static GameObject? _fallbackLightObject; private static Light? _fallbackLight; private static ItemData? _fallbackLightItem; private static GameObject? _fallbackVisualRoot; private static ItemData? _fallbackVisualItem; private static float _nextDebugLogTime; private static readonly Dictionary RepairStationDisplayNameCache = new Dictionary(StringComparer.OrdinalIgnoreCase); private static bool Active { get { if (!DvergrCircletConfig.ExtensionEnabled) { return false; } if (!IsCircletExtendedLoaded()) { return true; } if (!_loggedCircletExtendedSkip) { _loggedCircletExtendedSkip = true; ManualLogSource? logger = _logger; if (logger != null) { logger.LogInfo((object)"Circlet Extended is installed, so Homestead Dvergr circlet handling is disabled to avoid conflicts."); } } return false; } } internal static void Initialize(ManualLogSource logger) { _logger = logger; } internal static void ResetForWorldSession() { Player localPlayer = Player.m_localPlayer; if (Object.op_Implicit((Object)(object)localPlayer)) { PublishLocalCircletState(localPlayer, null, null); } CleanupFallbackVisuals(); ResetRemoteVisualsForWorldSession(); TempLights.Clear(); TempVisualRoots.Clear(); RepairStationDisplayNameCache.Clear(); _nextDebugLogTime = 0f; _loggedCircletExtendedSkip = false; _circletExtendedLoaded = null; AzuExtendedPlayerInventoryCompat.ResetForWorldSession(); } internal static void Update() { //IL_00ab: Unknown result type (might be due to invalid IL or missing references) bool active = Active; bool flag = ShouldBlockInput(); Player localPlayer = Player.m_localPlayer; ItemData item; ItemData val = ((Object.op_Implicit((Object)(object)localPlayer) && TryGetEquippedDvergrCirclet(localPlayer, out item)) ? item : null); if (!active) { if (Object.op_Implicit((Object)(object)localPlayer)) { PublishLocalCircletState(localPlayer, null, null); } CleanupFallbackVisuals(); return; } if (!Object.op_Implicit((Object)(object)localPlayer) || ((Character)localPlayer).IsDead()) { if (Object.op_Implicit((Object)(object)localPlayer)) { PublishLocalCircletState(localPlayer, null, null); } CleanupFallbackVisuals(); return; } if (!PatchItemData(val, initializeDurability: true)) { PublishLocalCircletState(localPlayer, null, null); CleanupFallbackVisuals(); return; } ItemData item2 = val; CircletState circletState = LoadState(item2); EnsureLocalCircletVisual(localPlayer, item2, circletState); PublishLocalCircletState(localPlayer, item2, circletState); LogDebugStatus(localPlayer, item2, circletState); if (!flag) { if (IsShortcutDownLenient(DvergrCircletConfig.ToggleLightHotkey)) { circletState.LightOn = !circletState.LightOn; SaveState(item2, circletState); ((Humanoid)localPlayer).GetInventory().Changed(); EnsureLocalCircletVisual(localPlayer, item2, circletState); PublishLocalCircletState(localPlayer, item2, circletState); ShowStateHud(circletState); } else if (TryAdjustHotkey((KeyCode)273, circletState, 1f, 0f) || TryAdjustHotkey((KeyCode)274, circletState, -1f, 0f) || TryAdjustHotkey((KeyCode)275, circletState, 0f, 1f) || TryAdjustHotkey((KeyCode)276, circletState, 0f, -1f)) { SaveState(item2, circletState); ((Humanoid)localPlayer).GetInventory().Changed(); EnsureLocalCircletVisual(localPlayer, item2, circletState); PublishLocalCircletState(localPlayer, item2, circletState); ShowStateHud(circletState); } } } private static bool IsCircletExtendedLoaded() { if (_circletExtendedLoaded.HasValue) { return _circletExtendedLoaded.Value; } _circletExtendedLoaded = Chainloader.PluginInfos.ContainsKey("shudnal.CircletExtended"); return _circletExtendedLoaded.Value; } private static bool TryAdjustHotkey(KeyCode arrowKey, CircletState state, float intensityDelta, float rangeDelta) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if (!Input.GetKeyDown(arrowKey) || !IsAdjustmentModifierHeld()) { return false; } float perItemAdjustmentStep = DvergrCircletConfig.PerItemAdjustmentStep; if (Mathf.Abs(intensityDelta) > 0.001f) { state.IntensityMultiplier = ClampAndRoundIntensityMultiplier(state.IntensityMultiplier + intensityDelta * perItemAdjustmentStep); } if (Mathf.Abs(rangeDelta) > 0.001f) { state.RangeMultiplier = ClampAndRoundRangeMultiplier(state.RangeMultiplier + rangeDelta * perItemAdjustmentStep); } return true; } private static bool IsAdjustmentModifierHeld() { //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_0008: 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_0031: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut adjustmentModifierKey = DvergrCircletConfig.AdjustmentModifierKey; if ((int)((KeyboardShortcut)(ref adjustmentModifierKey)).MainKey == 0) { return true; } if (!IsShortcutModifierHeld(((KeyboardShortcut)(ref adjustmentModifierKey)).MainKey)) { return false; } foreach (KeyCode modifier in ((KeyboardShortcut)(ref adjustmentModifierKey)).Modifiers) { if (!IsShortcutModifierHeld(modifier)) { return false; } } return true; } private static bool IsShortcutDownLenient(KeyboardShortcut shortcut) { //IL_0002: 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_0029: Unknown result type (might be due to invalid IL or missing references) if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0 || !Input.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey)) { return false; } foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers) { if (!IsShortcutModifierHeld(modifier)) { return false; } } return true; } private static bool IsShortcutModifierHeld(KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: 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_0027: Expected I4, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) if ((int)key != 0) { switch (key - 303) { case 0: case 1: return Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303); case 2: case 3: return Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305); case 4: case 5: return Input.GetKey((KeyCode)308) || Input.GetKey((KeyCode)307); default: return Input.GetKey(key); } } return true; } private static bool ShouldBlockInput() { if (!Hud.IsPieceSelectionVisible() && !Console.IsVisible() && !TextInput.IsVisible() && !Menu.IsVisible() && !InventoryGui.IsVisible()) { return Minimap.IsOpen(); } return true; } private static bool PatchItemData(ItemData? item, bool initializeDurability) { if (!Active || item == null || item.m_shared == null || !IsDvergrCircletItem(item)) { return false; } PatchSharedData(item.m_shared); float maxDurability = item.GetMaxDurability(); if (initializeDurability && !item.m_customData.ContainsKey("sighsorry.Homestead.dvergr_circlet_initialized")) { item.m_durability = maxDurability; item.m_customData["sighsorry.Homestead.dvergr_circlet_initialized"] = "1"; } else { item.m_durability = Mathf.Clamp(item.m_durability, 0f, maxDurability); } return true; } private static void PatchSharedData(SharedData shared) { shared.m_useDurability = true; shared.m_destroyBroken = false; shared.m_canBeReparied = true; shared.m_maxDurability = 100f; shared.m_durabilityPerLevel = 0f; shared.m_durabilityDrain = 0f; shared.m_useDurabilityDrain = 0f; } private static void PatchObjectDbItem() { if (Active && !((Object)(object)ObjectDB.instance == (Object)null)) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("HelmetDverger"); if (Object.op_Implicit((Object)(object)itemPrefab)) { PatchItemData(itemPrefab.GetComponent()?.m_itemData, initializeDurability: false); } } } private static void PatchInventoryItems(Inventory? inventory) { if (!Active || inventory == null) { return; } foreach (ItemData allItem in inventory.GetAllItems()) { PatchItemData(allItem, initializeDurability: true); } } private static float GetDurabilityDrainPerSecond() { return 100f / DvergrCircletConfig.FuelSeconds; } private static float GetDurabilityDrainPerSecond(ItemData item) { CircletState circletState = LoadState(item); return GetDurabilityDrainPerSecond() * circletState.IntensityMultiplier * circletState.RangeMultiplier; } private static bool MatchesRepairStation(CraftingStation? station) { if (!Object.op_Implicit((Object)(object)station)) { return false; } string text = NormalizeStationName(DvergrCircletConfig.RepairStation); if (text.Length == 0) { return true; } if (!(NormalizeStationName(station.m_name) == text) && !(NormalizeStationName(((Object)((Component)station).gameObject).name) == text)) { return NormalizeStationName(Utils.GetPrefabName(((Object)((Component)station).gameObject).name)) == text; } return true; } private static string NormalizeStationName(string value) { string text = (value ?? string.Empty).Trim(); if (text.EndsWith("(Clone)", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(0, text.Length - 7).Trim(); } text = text.ToLowerInvariant(); if (text.StartsWith("$piece_", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(7); } else if (text.StartsWith("piece_", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(6); } return text.Replace(" ", "").Replace("_", ""); } private static void ShowStateHud(CircletState state) { ZoneAreaToolStatusHud.ShowDvergrCirclet(state.LightOn, state.IntensityMultiplier, state.RangeMultiplier); } private static string BuildTooltip(ItemData item) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) CircletState circletState = LoadState(item); string text = (circletState.LightOn ? "$hud_on" : "$hud_off"); return "\n\n" + HomesteadLocalization.Text("hs_dvergr_title") + "\n" + HomesteadLocalization.Format("hs_dvergr_tooltip_light", text, FormatShortcut(DvergrCircletConfig.ToggleLightHotkey)) + "\n" + HomesteadLocalization.Format("hs_dvergr_tooltip_intensity", circletState.IntensityMultiplier * 100f, FormatAdjustmentShortcutPair("↑ ↓")) + "\n" + HomesteadLocalization.Format("hs_dvergr_tooltip_range", circletState.RangeMultiplier * 100f, FormatAdjustmentShortcutPair("← →")) + "\n" + HomesteadLocalization.Format("hs_dvergr_tooltip_repair_station", GetRepairStationDisplayName()); } private static string GetRepairStationDisplayName() { string text = DvergrCircletConfig.RepairStation; if (string.IsNullOrWhiteSpace(text)) { text = "forge"; } if (RepairStationDisplayNameCache.TryGetValue(text, out string value)) { return value; } string text2 = ResolveRepairStationDisplayName(text); RepairStationDisplayNameCache[text] = text2; return text2; } private static string ResolveRepairStationDisplayName(string configured) { string text = configured.Trim(); GameObject val = FindCraftingStationPrefab(text); if ((Object)(object)val != (Object)null) { Piece component = val.GetComponent(); if ((Object)(object)component != (Object)null && !string.IsNullOrWhiteSpace(component.m_name)) { Localization instance = Localization.instance; string text2 = ((instance != null) ? instance.Localize(component.m_name) : null) ?? ""; if (!string.IsNullOrWhiteSpace(text2) && !string.Equals(text2, component.m_name, StringComparison.Ordinal)) { return text2; } string text3 = StripLocalizationToken(component.m_name); if (!string.IsNullOrWhiteSpace(text3)) { return text3; } } } if (text.StartsWith("$", StringComparison.Ordinal)) { Localization instance2 = Localization.instance; string text4 = ((instance2 != null) ? instance2.Localize(text) : null) ?? ""; if (!string.IsNullOrWhiteSpace(text4) && !string.Equals(text4, text, StringComparison.Ordinal)) { return text4; } string text5 = StripLocalizationToken(text); if (!string.IsNullOrWhiteSpace(text5)) { return text5; } } return text; } private static GameObject? FindCraftingStationPrefab(string configured) { string text = NormalizeStationName(configured); if (text.Length == 0) { return null; } GameObject[] array = new GameObject[4]; ZNetScene instance = ZNetScene.instance; array[0] = ((instance != null) ? instance.GetPrefab(configured) : null); ZNetScene instance2 = ZNetScene.instance; array[1] = ((instance2 != null) ? instance2.GetPrefab(Utils.GetPrefabName(configured)) : null); array[2] = PrefabManager.Instance.GetPrefab(configured); array[3] = PrefabManager.Instance.GetPrefab(Utils.GetPrefabName(configured)); GameObject[] array2 = (GameObject[])(object)array; foreach (GameObject val in array2) { if (IsMatchingCraftingStation(val, text)) { return val; } } if ((Object)(object)ZNetScene.instance != (Object)null) { foreach (GameObject prefab in ZNetScene.instance.m_prefabs) { if (IsMatchingCraftingStation(prefab, text)) { return prefab; } } } return null; } private static bool IsMatchingCraftingStation(GameObject? prefab, string wanted) { if (!Object.op_Implicit((Object)(object)prefab) || (Object)(object)prefab.GetComponent() == (Object)null) { return false; } Piece component = prefab.GetComponent(); if (!(NormalizeStationName(((Object)prefab).name) == wanted) && !(NormalizeStationName(Utils.GetPrefabName(((Object)prefab).name)) == wanted)) { if ((Object)(object)component != (Object)null) { return NormalizeStationName(component.m_name) == wanted; } return false; } return true; } private static string StripLocalizationToken(string value) { string text = (value ?? string.Empty).Trim(); if (text.StartsWith("$piece_", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(7); } else if (text.StartsWith("$item_", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(6); } else if (text.StartsWith("$", StringComparison.Ordinal)) { text = text.Substring(1); } text = text.Replace("_", " ").Trim(); if (text.Length != 0) { return CultureInfo.InvariantCulture.TextInfo.ToTitleCase(text); } return value ?? string.Empty; } private static string FormatShortcut(KeyboardShortcut shortcut) { string text = ((object)(KeyboardShortcut)(ref shortcut)).ToString(); if (!string.IsNullOrWhiteSpace(text)) { return text.Replace(" + ", "+"); } return "Unbound"; } private static string FormatAdjustmentShortcutPair(string arrows) { //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_0008: 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) KeyboardShortcut adjustmentModifierKey = DvergrCircletConfig.AdjustmentModifierKey; if ((int)((KeyboardShortcut)(ref adjustmentModifierKey)).MainKey == 0) { return arrows; } return FormatShortcut(adjustmentModifierKey) + " + " + arrows; } internal static bool IsDvergrCircletItem(ItemData? item) { if (item == null) { return false; } string text = (Object.op_Implicit((Object)(object)item.m_dropPrefab) ? ((Object)item.m_dropPrefab).name : string.Empty); if (text.Equals("HelmetDverger", StringComparison.OrdinalIgnoreCase) || text.StartsWith("HelmetDverger", StringComparison.OrdinalIgnoreCase)) { return true; } string text2 = item.m_shared?.m_name ?? string.Empty; if (text2.IndexOf("helmet_dverger", StringComparison.OrdinalIgnoreCase) < 0) { if (text2.IndexOf("dverger", StringComparison.OrdinalIgnoreCase) >= 0) { if (text2.IndexOf("helmet", StringComparison.OrdinalIgnoreCase) < 0) { return text2.IndexOf("circlet", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } return false; } return true; } internal static bool TryGetEquippedDvergrCirclet(Player player, out ItemData? item) { item = null; if (!Object.op_Implicit((Object)(object)player)) { return false; } if (IsDvergrCircletItem(((Humanoid)player).m_helmetItem)) { item = ((Humanoid)player).m_helmetItem; return true; } return AzuExtendedPlayerInventoryCompat.TryGetCustomEquippedItem(player, IsDvergrCircletItem, out item); } private static ItemData? TryGetVisualHelmetItem(VisEquipment visEquipment) { Player localPlayer = Player.m_localPlayer; if (Object.op_Implicit((Object)(object)localPlayer) && (Object)(object)((Humanoid)localPlayer).m_visEquipment == (Object)(object)visEquipment && TryGetEquippedDvergrCirclet(localPlayer, out ItemData item)) { return item; } Player componentInParent = ((Component)visEquipment).GetComponentInParent(); if (Object.op_Implicit((Object)(object)componentInParent) && TryGetEquippedDvergrCirclet(componentInParent, out ItemData item2)) { return item2; } return null; } private static bool IsCircletLightOn(Player player, ItemData item) { TempLights.Clear(); CollectCircletLights(player, item, TempLights); foreach (Light tempLight in TempLights) { if (Object.op_Implicit((Object)(object)tempLight) && ((Behaviour)tempLight).enabled && ((Component)tempLight).gameObject.activeInHierarchy) { return true; } } return false; } internal static bool TryAppendFallbackLight(List output) { int count = output.Count; if ((Object)(object)_fallbackVisualRoot != (Object)null && Object.op_Implicit((Object)(object)_fallbackVisualRoot) && _fallbackVisualRoot.activeInHierarchy) { _fallbackVisualRoot.GetComponentsInChildren(true, output); } if ((Object)(object)_fallbackLight == (Object)null || !Object.op_Implicit((Object)(object)_fallbackLight) || !((Behaviour)_fallbackLight).enabled || !((Component)_fallbackLight).gameObject.activeInHierarchy) { return output.Count > count; } output.Add(_fallbackLight); return output.Count > count; } private static void CollectCircletLights(Player player, ItemData item, List output) { VisEquipment visEquipment = ((Humanoid)player).m_visEquipment; if (!Object.op_Implicit((Object)(object)visEquipment)) { CleanupFallbackVisuals(); return; } if (item == ((Humanoid)player).m_helmetItem && Object.op_Implicit((Object)(object)visEquipment.m_helmetItemInstance)) { visEquipment.m_helmetItemInstance.GetComponentsInChildren(true, output); } if (AzuExtendedPlayerInventoryCompat.TryGetCustomEquipVisualRoots(visEquipment, item, TempVisualRoots)) { foreach (GameObject tempVisualRoot in TempVisualRoots) { if (Object.op_Implicit((Object)(object)tempVisualRoot)) { tempVisualRoot.GetComponentsInChildren(true, output); } } } TryAppendFallbackLight(output); } private static void EnsureLocalCircletVisual(Player player, ItemData item, CircletState state) { VisEquipment visEquipment = ((Humanoid)player).m_visEquipment; if (!Object.op_Implicit((Object)(object)visEquipment)) { return; } int num = 0; if (item == ((Humanoid)player).m_helmetItem && Object.op_Implicit((Object)(object)visEquipment.m_helmetItemInstance)) { EnsureVisualComponent(visEquipment.m_helmetItemInstance, item); num++; } if (AzuExtendedPlayerInventoryCompat.TryGetCustomEquipVisualRoots(visEquipment, item, TempVisualRoots)) { foreach (GameObject tempVisualRoot in TempVisualRoots) { if (Object.op_Implicit((Object)(object)tempVisualRoot)) { EnsureVisualComponent(tempVisualRoot, item); num++; } } } TempLights.Clear(); CollectCircletLights(player, item, TempLights); bool flag = TempLights.Any((Light light) => Object.op_Implicit((Object)(object)light) && (Object)(object)light != (Object)(object)_fallbackLight); if (num == 0 || !flag) { if (EnsureFallbackVisual(player, item)) { TempLights.Clear(); CollectCircletLights(player, item, TempLights); if (TempLights.Any((Light light) => Object.op_Implicit((Object)(object)light) && (Object)(object)light != (Object)(object)_fallbackLight)) { DisableFallbackLight(); return; } } UpdateFallbackLight(player, item, state); } else { DestroyFallbackVisual(); DisableFallbackLight(); } } private static void EnsureVisualComponent(GameObject root, ItemData item) { ZoneDvergrCircletVisual zoneDvergrCircletVisual = root.GetComponent() ?? root.AddComponent(); if (!zoneDvergrCircletVisual.IsFor(item)) { zoneDvergrCircletVisual.Initialize(item); } zoneDvergrCircletVisual.ApplyNow(); } private static void UpdateFallbackLight(Player player, ItemData item, CircletState state) { //IL_004d: 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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_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_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) EnsureFallbackLight(); if (!((Object)(object)_fallbackLight == (Object)null) && !((Object)(object)_fallbackLightObject == (Object)null)) { _fallbackLightItem = item; Transform val = ((Component)player).transform; if (TryGetHelmetTransform(player, out Transform helmetTransform) && (Object)(object)helmetTransform != (Object)null) { val = helmetTransform; } _fallbackLightObject.transform.position = val.position + val.up * 0.05f + val.forward * 0.28f; _fallbackLightObject.transform.rotation = val.rotation; _fallbackLight.type = (LightType)2; _fallbackLight.color = new Color(1f, 0.82f, 0.58f, 1f); _fallbackLight.intensity = 1.25f * state.IntensityMultiplier; _fallbackLight.range = 14f * state.RangeMultiplier; _fallbackLight.shadows = (LightShadows)2; ((Behaviour)_fallbackLight).enabled = Active && state.LightOn && item.m_durability > 0f; _fallbackLightObject.SetActive(((Behaviour)_fallbackLight).enabled); } } private static void EnsureFallbackLight() { //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_004a: Expected O, but got Unknown if (!((Object)(object)_fallbackLightObject != (Object)null) || !Object.op_Implicit((Object)(object)_fallbackLightObject) || !((Object)(object)_fallbackLight != (Object)null) || !Object.op_Implicit((Object)(object)_fallbackLight)) { _fallbackLightObject = new GameObject("HomesteadDvergrCircletFallbackLight") { hideFlags = (HideFlags)61 }; _fallbackLight = _fallbackLightObject.AddComponent(); _fallbackLightObject.SetActive(false); } } private static void DisableFallbackLight() { _fallbackLightItem = null; if ((Object)(object)_fallbackLight != (Object)null && Object.op_Implicit((Object)(object)_fallbackLight)) { ((Behaviour)_fallbackLight).enabled = false; } if ((Object)(object)_fallbackLightObject != (Object)null && Object.op_Implicit((Object)(object)_fallbackLightObject)) { _fallbackLightObject.SetActive(false); } } private static bool EnsureFallbackVisual(Player player, ItemData item) { if (!TryGetHelmetTransform(player, out Transform helmetTransform) || (Object)(object)helmetTransform == (Object)null) { return false; } if ((Object)(object)_fallbackVisualRoot != (Object)null && Object.op_Implicit((Object)(object)_fallbackVisualRoot) && _fallbackVisualItem == item) { _fallbackVisualRoot.SetActive(true); EnsureVisualComponent(_fallbackVisualRoot, item); return true; } DestroyFallbackVisual(); try { GameObject val = ((Humanoid)player).m_visEquipment.AttachItem(PrefabHash, 0, helmetTransform, false, false); if (!Object.op_Implicit((Object)(object)val)) { return false; } ((Object)val).name = "HomesteadDvergrCircletFallbackVisual"; ((Object)val).hideFlags = (HideFlags)52; _fallbackVisualRoot = val; _fallbackVisualItem = item; EnsureVisualComponent(val, item); return true; } catch (Exception ex) { ManualLogSource? logger = _logger; if (logger != null) { logger.LogWarning((object)("Failed to attach fallback Dvergr circlet visual to helmet joint; using point light fallback. " + ex.GetType().Name + ": " + ex.Message)); } DestroyFallbackVisual(); return false; } } private static bool TryGetHelmetTransform(Player player, out Transform? helmetTransform) { helmetTransform = null; VisEquipment visEquipment = ((Humanoid)player).m_visEquipment; if (!Object.op_Implicit((Object)(object)visEquipment) || !Object.op_Implicit((Object)(object)visEquipment.m_helmet)) { return false; } helmetTransform = visEquipment.m_helmet; return true; } private static void CleanupFallbackVisuals() { DestroyFallbackVisual(); DisableFallbackLight(); } private static void DestroyFallbackVisual() { _fallbackVisualItem = null; if ((Object)(object)_fallbackVisualRoot != (Object)null && Object.op_Implicit((Object)(object)_fallbackVisualRoot)) { Object.Destroy((Object)(object)_fallbackVisualRoot); } _fallbackVisualRoot = null; } private static void LogDebugStatus(Player player, ItemData item, CircletState state) { if (!DvergrCircletConfig.DebugLogging || Time.time < _nextDebugLogTime) { return; } _nextDebugLogTime = Time.time + 5f; bool flag = item == ((Humanoid)player).m_helmetItem; bool flag2 = !flag && AzuExtendedPlayerInventoryCompat.IsLoaded; int num = 0; int num2 = 0; int num3 = 0; VisEquipment visEquipment = ((Humanoid)player).m_visEquipment; if (Object.op_Implicit((Object)(object)visEquipment)) { if (flag && Object.op_Implicit((Object)(object)visEquipment.m_helmetItemInstance)) { num++; TempLights.Clear(); visEquipment.m_helmetItemInstance.GetComponentsInChildren(true, TempLights); num2 += TempLights.Count; } if (AzuExtendedPlayerInventoryCompat.TryGetCustomEquipVisualRoots(visEquipment, item, TempVisualRoots)) { num += TempVisualRoots.Count; foreach (GameObject tempVisualRoot in TempVisualRoots) { if (Object.op_Implicit((Object)(object)tempVisualRoot)) { TempLights.Clear(); tempVisualRoot.GetComponentsInChildren(true, TempLights); num2 += TempLights.Count; } } } } if ((Object)(object)_fallbackVisualRoot != (Object)null && Object.op_Implicit((Object)(object)_fallbackVisualRoot)) { TempLights.Clear(); _fallbackVisualRoot.GetComponentsInChildren(true, TempLights); num3 = TempLights.Count; } GameObject dropPrefab = item.m_dropPrefab; string text = ((dropPrefab != null) ? ((Object)dropPrefab).name : null) ?? item.m_shared?.m_name ?? "unknown"; ManualLogSource? logger = _logger; if (logger != null) { logger.LogInfo((object)$"Dvergr circlet debug: item={text}, vanillaHelmet={flag}, azuLoaded={AzuExtendedPlayerInventoryCompat.IsLoaded}, azuCustomEquipped={flag2}, visualRoots={num}, visualLights={num2}, fallbackVisualActive={(Object)(object)_fallbackVisualRoot != (Object)null && _fallbackVisualRoot.activeInHierarchy}, fallbackVisualLights={num3}, fallbackPointActive={(Object)(object)_fallbackLightObject != (Object)null && _fallbackLightObject.activeSelf}, lightOn={state.LightOn}, durability={item.m_durability:0.0}/{item.GetMaxDurability():0.0}, intensity={state.IntensityMultiplier:0.##}, range={state.RangeMultiplier:0.##}"); } } private static void PublishLocalCircletState(Player player, ItemData? item, CircletState? state) { if (!Object.op_Implicit((Object)(object)player) || (Object)(object)((Character)player).m_nview == (Object)null || !((Character)player).m_nview.IsValid() || !((Character)player).m_nview.IsOwner()) { return; } ZDO zDO = ((Character)player).m_nview.GetZDO(); if (zDO != null) { if (!Active || !DvergrCircletConfig.RemoteVisualSync || item == null || !IsDvergrCircletItem(item)) { SetRemoteCircletZdo(zDO, 0, ""); return; } string serializedState = SerializeState(state ?? LoadState(item), item.m_durability > 0f, includeFuel: true); SetRemoteCircletZdo(zDO, PrefabHash, serializedState); } } private static void SetRemoteCircletZdo(ZDO zdo, int itemHash, string serializedState) { int num = ((!string.IsNullOrEmpty(serializedState)) ? StringExtensionMethods.GetStableHashCode(serializedState) : 0); if (zdo.GetInt(RemoteItemKey, 0) != itemHash) { zdo.Set(RemoteItemKey, itemHash, false); } if (zdo.GetString(RemoteStateKey, "") != serializedState) { zdo.Set(RemoteStateKey, serializedState); } if (zdo.GetInt(RemoteStateHashKey, 0) != num) { zdo.Set(RemoteStateHashKey, num, false); } } private static bool ShouldSyncRemoteVisuals() { if (Active) { return DvergrCircletConfig.RemoteVisualSync; } return false; } private static bool IsLocalVisEquipment(VisEquipment visEquipment) { Player localPlayer = Player.m_localPlayer; if (Object.op_Implicit((Object)(object)localPlayer)) { return (Object)(object)((Humanoid)localPlayer).m_visEquipment == (Object)(object)visEquipment; } return false; } private static bool IsWithinRemoteLightRange(VisEquipment visEquipment) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) float remoteLightMaxDistance = DvergrCircletConfig.RemoteLightMaxDistance; if (remoteLightMaxDistance <= 0f) { return true; } Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer)) { return true; } Vector3 val = ((Component)visEquipment).transform.position - ((Component)localPlayer).transform.position; return ((Vector3)(ref val)).sqrMagnitude <= remoteLightMaxDistance * remoteLightMaxDistance; } private static void EnsureRemoteVisualComponent(GameObject root, ZNetView nview, bool culled) { ZoneDvergrCircletVisual zoneDvergrCircletVisual = root.GetComponent() ?? root.AddComponent(); if (!zoneDvergrCircletVisual.IsRemoteFor(nview)) { zoneDvergrCircletVisual.InitializeRemote(nview); } zoneDvergrCircletVisual.SetRemoteCulled(culled); zoneDvergrCircletVisual.ApplyNow(); } private static bool TryGetRemoteCircletNview(VisEquipment visEquipment, out ZNetView? nview) { nview = null; if (!ShouldSyncRemoteVisuals() || !Object.op_Implicit((Object)(object)visEquipment) || !visEquipment.m_isPlayer || IsLocalVisEquipment(visEquipment) || (Object)(object)visEquipment.m_nview == (Object)null || !visEquipment.m_nview.IsValid()) { return false; } ZDO zDO = visEquipment.m_nview.GetZDO(); if (zDO == null || zDO.GetInt(RemoteItemKey, 0) != PrefabHash) { return false; } nview = visEquipment.m_nview; return true; } private static void CullRemoteVisualComponent(GameObject? root, ZNetView? nview) { if (Object.op_Implicit((Object)(object)root) && !((Object)(object)nview == (Object)null)) { ZoneDvergrCircletVisual component = root.GetComponent(); if ((Object)(object)component != (Object)null && component.IsRemoteFor(nview)) { component.SetRemoteCulled(culled: true); } } } private static CircletState LoadState(ItemData? item) { if (item == null || !item.m_customData.TryGetValue("sighsorry.Homestead.dvergr_circlet_state", out var value)) { return new CircletState(); } CircletState circletState = LoadStateFromString(value); circletState.HasFuel = item.m_durability > 0f; return circletState; } private static CircletState LoadRemoteState(ZNetView? nview) { if ((Object)(object)nview == (Object)null || !nview.IsValid()) { return new CircletState { HasFuel = false }; } ZDO zDO = nview.GetZDO(); if (zDO == null || zDO.GetInt(RemoteItemKey, 0) != PrefabHash) { return new CircletState { HasFuel = false }; } return LoadStateFromString(zDO.GetString(RemoteStateKey, "")); } private static CircletState LoadStateFromString(string? serialized) { CircletState circletState = new CircletState(); if (serialized == null) { return circletState; } if (string.IsNullOrWhiteSpace(serialized)) { return circletState; } string[] array = serialized.Split(new char[1] { ';' }); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(new char[1] { '=' }, 2); if (array2.Length == 2) { string text = array2[0].Trim(); string text2 = array2[1].Trim(); float result; float result2; if (text.Equals("on", StringComparison.OrdinalIgnoreCase)) { circletState.LightOn = text2 == "1" || text2.Equals("true", StringComparison.OrdinalIgnoreCase); } else if (text.Equals("intensity", StringComparison.OrdinalIgnoreCase) && float.TryParse(text2, NumberStyles.Float, CultureInfo.InvariantCulture, out result)) { circletState.IntensityMultiplier = ClampAndRoundIntensityMultiplier(result); } else if (text.Equals("range", StringComparison.OrdinalIgnoreCase) && float.TryParse(text2, NumberStyles.Float, CultureInfo.InvariantCulture, out result2)) { circletState.RangeMultiplier = ClampAndRoundRangeMultiplier(result2); } else if ((text.Equals("fuel", StringComparison.OrdinalIgnoreCase) || text.Equals("active", StringComparison.OrdinalIgnoreCase)) && (text2 == "0" || text2.Equals("false", StringComparison.OrdinalIgnoreCase))) { circletState.HasFuel = false; } } } return circletState; } private static void SaveState(ItemData item, CircletState state) { state.IntensityMultiplier = ClampAndRoundIntensityMultiplier(state.IntensityMultiplier); state.RangeMultiplier = ClampAndRoundRangeMultiplier(state.RangeMultiplier); item.m_customData["sighsorry.Homestead.dvergr_circlet_state"] = SerializeState(state, hasFuel: true, includeFuel: false); } private static string SerializeState(CircletState state, bool hasFuel, bool includeFuel) { state.IntensityMultiplier = ClampAndRoundIntensityMultiplier(state.IntensityMultiplier); state.RangeMultiplier = ClampAndRoundRangeMultiplier(state.RangeMultiplier); string text = string.Format("on={0};intensity={1};range={2}", state.LightOn ? 1 : 0, state.IntensityMultiplier.ToString("0.##", CultureInfo.InvariantCulture), state.RangeMultiplier.ToString("0.##", CultureInfo.InvariantCulture)); if (includeFuel) { text += $";fuel={(hasFuel ? 1 : 0)}"; } return text; } private static float ClampAndRoundIntensityMultiplier(float value) { return ClampAndRoundMultiplier(value, DvergrCircletConfig.PerItemMaxIntensityMultiplier); } private static float ClampAndRoundRangeMultiplier(float value) { return ClampAndRoundMultiplier(value, DvergrCircletConfig.PerItemMaxRangeMultiplier); } private static float ClampAndRoundMultiplier(float value, float maxMultiplier) { float perItemAdjustmentStep = DvergrCircletConfig.PerItemAdjustmentStep; return Mathf.Clamp((perItemAdjustmentStep > 0f) ? (Mathf.Round(value / perItemAdjustmentStep) * perItemAdjustmentStep) : value, 1f, maxMultiplier); } private static void ResetRemoteVisualsForWorldSession() { ZoneDvergrCircletRemoteVisual[] array = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (ZoneDvergrCircletRemoteVisual zoneDvergrCircletRemoteVisual in array) { if (Object.op_Implicit((Object)(object)zoneDvergrCircletRemoteVisual)) { Object.Destroy((Object)(object)zoneDvergrCircletRemoteVisual); } } ZoneDvergrCircletVisual[] array2 = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (ZoneDvergrCircletVisual zoneDvergrCircletVisual in array2) { if (Object.op_Implicit((Object)(object)zoneDvergrCircletVisual)) { Object.Destroy((Object)(object)zoneDvergrCircletVisual); } } } } internal sealed class ZoneBlueprintFile { public int Version { get; set; } = 1; public string Name { get; set; } = ""; public string World { get; set; } = ""; public string SavedAt { get; set; } = ""; public float Radius { get; set; } public List Entries { get; set; } = new List(); public List TerrainContacts { get; set; } = new List(); } internal sealed class ZoneBlueprintEntry { public string SaveId { get; set; } = ""; public string Prefab { get; set; } = ""; public float[] LocalPos { get; set; } = new float[3]; public float[] LocalRot { get; set; } = new float[4]; public float[] Scale { get; set; } = new float[3]; public string Data { get; set; } = ""; } internal sealed class ZoneBlueprintTerrainContact { public float LocalX { get; set; } public float LocalY { get; set; } public float LocalZ { get; set; } } internal sealed class ZoneBlueprintRequirement { public string ItemName { get; set; } = ""; public string PrefabName { get; set; } = ""; public string DisplayName { get; set; } = ""; public int Amount { get; set; } } internal sealed class ZoneBlueprintCraftingStationRequirement { public string StationName { get; set; } = ""; public string PrefabName { get; set; } = ""; public string DisplayName { get; set; } = ""; } internal sealed class ZoneBlueprintStoreCatalog { public int Version { get; set; } = 1; public List Listings { get; set; } = new List(); public List Offers { get; set; } = new List(); public List Notifications { get; set; } = new List(); public List Balances { get; set; } = new List(); } internal sealed class ZoneBlueprintStoreListing { public string ListingId { get; set; } = ""; public string Name { get; set; } = ""; public string SellerName { get; set; } = ""; public long SellerPlayerId { get; set; } public string SellerPlatformId { get; set; } = ""; public string CreatedAt { get; set; } = ""; public string ExpiresAt { get; set; } = ""; public List PriceItems { get; set; } = new List(); public int EntryCount { get; set; } public int PurchaseCount { get; set; } public string BlueprintFile { get; set; } = ""; public string IconPngBase64 { get; set; } = ""; public bool Active { get; set; } = true; } internal sealed class ZoneBlueprintStoreBalance { public long SellerPlayerId { get; set; } public string SellerPlatformId { get; set; } = ""; public string SellerName { get; set; } = ""; public int Coins { get; set; } public List Materials { get; set; } = new List(); } internal sealed class ZoneBlueprintStoreOffer { public string OfferId { get; set; } = ""; public string ListingId { get; set; } = ""; public string BuyerName { get; set; } = ""; public long BuyerPlayerId { get; set; } public string BuyerPlatformId { get; set; } = ""; public string CreatedAt { get; set; } = ""; public string UpdatedAt { get; set; } = ""; public string Status { get; set; } = "Pending"; public List PriceItems { get; set; } = new List(); } internal static class ZoneBlueprintStoreOfferStatus { public const string Pending = "Pending"; public const string Accepted = "Accepted"; public const string Declined = "Declined"; public const string Deleted = "Deleted"; } internal sealed class ZoneBlueprintStoreNotification { public string NotificationId { get; set; } = ""; public string Type { get; set; } = ""; public string RecipientPlatformId { get; set; } = ""; public long RecipientPlayerId { get; set; } public string RecipientName { get; set; } = ""; public string ActorName { get; set; } = ""; public string ListingId { get; set; } = ""; public string ListingName { get; set; } = ""; public string OfferId { get; set; } = ""; public string Message { get; set; } = ""; public string CreatedAt { get; set; } = ""; public bool Read { get; set; } public List ReadByPlatformIds { get; set; } = new List(); public List ReadByPlayerIds { get; set; } = new List(); } internal static class ZoneBlueprintStoreNotificationType { public const string NewListing = "NewListing"; public const string OfferReceived = "OfferReceived"; public const string OfferAccepted = "OfferAccepted"; public const string OfferDeclined = "OfferDeclined"; public const string BlueprintPurchased = "BlueprintPurchased"; } internal sealed class ZoneBlueprintStoreListingSummaryDto { public string ListingId { get; set; } = ""; public string Name { get; set; } = ""; public string SellerName { get; set; } = ""; public ZoneBlueprintStoreListingIdentityDebugDto? DebugIdentity { get; set; } public List PriceItems { get; set; } = new List(); public int PurchaseCount { get; set; } public int OfferCount { get; set; } public bool CanDelist { get; set; } public bool CanManage { get; set; } } internal sealed class ZoneBlueprintStoreListingIdentityDebugDto { public long SellerPlayerId { get; set; } public long RequesterPlayerId { get; set; } public string IdentityMode { get; set; } = ""; } internal sealed class ZoneBlueprintStoreListingIconDto { public string ListingId { get; set; } = ""; public string IconPngBase64 { get; set; } = ""; } internal sealed class ZoneBlueprintStoreOfferDto { public string OfferId { get; set; } = ""; public string ListingId { get; set; } = ""; public string BuyerName { get; set; } = ""; public List PriceItems { get; set; } = new List(); public string PriceText { get; set; } = ""; public string Status { get; set; } = ""; public bool CanAccept { get; set; } public bool CanDecline { get; set; } public bool CanDelete { get; set; } public bool CanBuy { get; set; } } internal sealed class ZoneBlueprintStoreNotificationDto { public string NotificationId { get; set; } = ""; public string Type { get; set; } = ""; public string ActorName { get; set; } = ""; public string ListingId { get; set; } = ""; public string ListingName { get; set; } = ""; public string OfferId { get; set; } = ""; public string Message { get; set; } = ""; public string CreatedAt { get; set; } = ""; public bool Read { get; set; } } internal sealed class ZoneBlueprintStorePriceItem { public string ItemName { get; set; } = ""; public string PrefabName { get; set; } = ""; public string DisplayName { get; set; } = ""; public int Amount { get; set; } } internal static class ZoneBlueprintStoreRpcType { public const string Error = "error"; public const string List = "list"; public const string PriceChest = "price_chest"; public const string Publish = "publish"; public const string Preview = "preview"; public const string PreviewRestore = "preview_restore"; public const string Buy = "buy"; public const string ConfirmPurchase = "confirm"; public const string ConfirmListing = "confirm_listing"; public const string Delist = "delist"; public const string EditPrice = "edit_price"; public const string CreateOffer = "create_offer"; public const string ListOffers = "list_offers"; public const string DecideOffer = "decide_offer"; public const string DeleteOffer = "delete_offer"; public const string Notify = "notify"; public const string GetNotifications = "get_notifications"; public const string RecentNotifications = "recent_notifications"; public const string ReadNotifications = "read_notifications"; public const string SyncHidden = "sync_hidden"; public const string Withdraw = "withdraw"; public const string PurchaseComplete = "purchase_complete"; public const string WithdrawComplete = "withdraw_complete"; } internal sealed class ZoneBlueprintStoreRpcEnvelope : IZoneBlueprintRpcEnvelope { public string Type { get; set; } = ""; public string PayloadYaml { get; set; } = ""; [YamlIgnore] public byte[] BlueprintPayload { get; set; } = Array.Empty(); } internal sealed class ZoneBlueprintStoreTransformPayload { public float[] Pos { get; set; } = new float[3]; public float[] Rot { get; set; } = new float[4]; } internal sealed class ZoneBlueprintStoreListRequest { public int RequestId { get; set; } public int Offset { get; set; } public int Limit { get; set; } public bool ShowHidden { get; set; } public bool IncludeNotifications { get; set; } public bool IncludeDebugIdentity { get; set; } public bool IconsOnly { get; set; } public List IconListingIds { get; set; } = new List(); public int FirstIconCount { get; set; } = 6; } internal sealed class ZoneBlueprintStoreListResponse { public bool Success { get; set; } public string Message { get; set; } = ""; public int RequestId { get; set; } public int TotalListings { get; set; } public int Offset { get; set; } public int Limit { get; set; } public int HiddenListings { get; set; } public bool HasMore { get; set; } public bool HasWithdrawableBalance { get; set; } public bool IconsOnly { get; set; } public List Listings { get; set; } = new List(); public List Icons { get; set; } = new List(); public List Notifications { get; set; } = new List(); } internal sealed class ZoneBlueprintStoreSyncHiddenRequest { public List HiddenListingIds { get; set; } = new List(); } internal interface IZoneBlueprintPayloadCarrier { string BlueprintEncoding { get; set; } byte[] BlueprintPayload { get; set; } } internal interface IZoneBlueprintRpcEnvelope { string Type { get; set; } string PayloadYaml { get; set; } byte[] BlueprintPayload { get; set; } } internal sealed class ZoneBlueprintStorePriceChestRequest : IZoneBlueprintPayloadCarrier { public string Name { get; set; } = ""; public string BlueprintEncoding { get; set; } = "gzip"; [YamlIgnore] public byte[] BlueprintPayload { get; set; } = Array.Empty(); public string IconPngBase64 { get; set; } = ""; public ZoneBlueprintStoreTransformPayload? Target { get; set; } public ZoneBlueprintStoreTransformPayload? PreviewAnchor { get; set; } } internal sealed class ZoneBlueprintStorePriceChestResponse { public bool Success { get; set; } public string Message { get; set; } = ""; public string ListingId { get; set; } = ""; public string Name { get; set; } = ""; public ZoneBlueprintStoreTransformPayload? Chest { get; set; } } internal sealed class ZoneBlueprintStorePublishRequest : IZoneBlueprintPayloadCarrier { public string Name { get; set; } = ""; public List PriceItems { get; set; } = new List(); public string BlueprintEncoding { get; set; } = "gzip"; [YamlIgnore] public byte[] BlueprintPayload { get; set; } = Array.Empty(); public string IconPngBase64 { get; set; } = ""; } internal sealed class ZoneBlueprintStoreStatusResponse { public bool Success { get; set; } public string Message { get; set; } = ""; public string ListingId { get; set; } = ""; public bool RemoveListing { get; set; } public ZoneBlueprintStoreListingSummaryDto? Listing { get; set; } } internal sealed class ZoneBlueprintStorePreviewRequest { public string ListingId { get; set; } = ""; public string OfferId { get; set; } = ""; } internal sealed class ZoneBlueprintStorePreviewResponse : IZoneBlueprintPayloadCarrier { public bool Success { get; set; } public string Message { get; set; } = ""; public string ListingId { get; set; } = ""; public string OfferId { get; set; } = ""; public string Name { get; set; } = ""; public string BlueprintEncoding { get; set; } = "gzip"; [YamlIgnore] public byte[] BlueprintPayload { get; set; } = Array.Empty(); } internal sealed class ZoneBlueprintStorePreviewRestoreRequest { public string Mode { get; set; } = ""; public string ListingId { get; set; } = ""; public string Name { get; set; } = ""; public string BlueprintFile { get; set; } = ""; } internal sealed class ZoneBlueprintStorePreviewRestoreResponse : IZoneBlueprintPayloadCarrier { public bool Success { get; set; } public string Message { get; set; } = ""; public string Mode { get; set; } = ""; public string ListingId { get; set; } = ""; public string Name { get; set; } = ""; public string BlueprintFile { get; set; } = ""; public string BlueprintEncoding { get; set; } = "gzip"; [YamlIgnore] public byte[] BlueprintPayload { get; set; } = Array.Empty(); } internal sealed class ZoneBlueprintStoreBuyRequest { public string ListingId { get; set; } = ""; public string OfferId { get; set; } = ""; public ZoneBlueprintStoreTransformPayload? Target { get; set; } public ZoneBlueprintStoreTransformPayload? PreviewAnchor { get; set; } } internal sealed class ZoneBlueprintStoreBuyResponse { public bool Success { get; set; } public string Message { get; set; } = ""; public string ListingId { get; set; } = ""; public string OfferId { get; set; } = ""; public string Name { get; set; } = ""; public ZoneBlueprintStoreTransformPayload? Chest { get; set; } } internal sealed class ZoneBlueprintStoreConfirmPurchaseRequest { public string ListingId { get; set; } = ""; public string OfferId { get; set; } = ""; } internal sealed class ZoneBlueprintStoreConfirmListingRequest { public string ListingId { get; set; } = ""; public List PriceItems { get; set; } = new List(); } internal sealed class ZoneBlueprintStoreConfirmListingResponse { public bool Success { get; set; } public string Message { get; set; } = ""; public string ListingId { get; set; } = ""; } internal sealed class ZoneBlueprintStoreDelistRequest { public string ListingId { get; set; } = ""; } internal sealed class ZoneBlueprintStoreEditPriceRequest { public string ListingId { get; set; } = ""; public List PriceItems { get; set; } = new List(); } internal sealed class ZoneBlueprintStoreCreateOfferRequest { public string ListingId { get; set; } = ""; public List PriceItems { get; set; } = new List(); } internal sealed class ZoneBlueprintStoreListOffersRequest { public string ListingId { get; set; } = ""; } internal sealed class ZoneBlueprintStoreListOffersResponse { public bool Success { get; set; } public string Message { get; set; } = ""; public string ListingId { get; set; } = ""; public string ListingName { get; set; } = ""; public bool CanManage { get; set; } public List Offers { get; set; } = new List(); } internal sealed class ZoneBlueprintStoreDecideOfferRequest { public string ListingId { get; set; } = ""; public string OfferId { get; set; } = ""; public string Decision { get; set; } = ""; } internal sealed class ZoneBlueprintStoreDeleteOfferRequest { public string ListingId { get; set; } = ""; public string OfferId { get; set; } = ""; } internal sealed class ZoneBlueprintStoreNotificationResponse { public List Notifications { get; set; } = new List(); } internal sealed class ZoneBlueprintStoreGetNotificationsRequest { } internal sealed class ZoneBlueprintStoreRecentNotificationsRequest { public int Limit { get; set; } = 32; } internal sealed class ZoneBlueprintStoreReadNotificationsRequest { public List NotificationIds { get; set; } = new List(); } internal sealed class ZoneBlueprintStorePurchaseCompleteResponse : IZoneBlueprintPayloadCarrier { public bool Success { get; set; } public string Message { get; set; } = ""; public string ListingId { get; set; } = ""; public string OfferId { get; set; } = ""; public string Name { get; set; } = ""; public string BlueprintEncoding { get; set; } = "gzip"; [YamlIgnore] public byte[] BlueprintPayload { get; set; } = Array.Empty(); } internal sealed class ZoneBlueprintStoreWithdrawRequest { public ZoneBlueprintStoreTransformPayload? Target { get; set; } } internal sealed class ZoneBlueprintStoreWithdrawResponse { public bool Success { get; set; } public string Message { get; set; } = ""; public List Chests { get; set; } = new List(); } internal static class ZoneBlueprintPlanRpcType { public const string Place = "place"; public const string Preview = "preview"; } internal sealed class ZoneBlueprintPlanRpcEnvelope : IZoneBlueprintRpcEnvelope { public string Type { get; set; } = ""; public string PayloadYaml { get; set; } = ""; [YamlIgnore] public byte[] BlueprintPayload { get; set; } = Array.Empty(); } internal sealed class ZoneBlueprintPlanPlaceRequest : IZoneBlueprintPayloadCarrier { public string Name { get; set; } = ""; public string BlueprintEncoding { get; set; } = "gzip"; [YamlIgnore] public byte[] BlueprintPayload { get; set; } = Array.Empty(); public ZoneBlueprintStoreTransformPayload? Anchor { get; set; } public ZoneBlueprintStoreTransformPayload? Chest { get; set; } } internal sealed class ZoneBlueprintPlanPlaceResponse : IZoneBlueprintPayloadCarrier { public bool Success { get; set; } public string Message { get; set; } = ""; public string RequestedName { get; set; } = ""; public string BlueprintName { get; set; } = ""; public ZoneBlueprintStoreTransformPayload? Chest { get; set; } public string BlueprintEncoding { get; set; } = "gzip"; [YamlIgnore] public byte[] BlueprintPayload { get; set; } = Array.Empty(); } internal sealed class ZoneBlueprintPlanPreviewRequest { public string Name { get; set; } = ""; } internal sealed class ZoneBlueprintPlanPreviewResponse : IZoneBlueprintPayloadCarrier { public bool Success { get; set; } public string Message { get; set; } = ""; public string Name { get; set; } = ""; public string BlueprintEncoding { get; set; } = "gzip"; [YamlIgnore] public byte[] BlueprintPayload { get; set; } = Array.Empty(); } internal sealed class ZoneBlueprintGhostOwner { public GameObject? Root { get; private set; } public Material? Material { get; private set; } public bool HasRoot { get { if ((Object)(object)Root != (Object)null) { return Object.op_Implicit((Object)(object)Root); } return false; } } public GameObject CreateBlueprint(ZoneBlueprintFile blueprint, string objectName, Vector3 position, Quaternion rotation, Transform? parent = null) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) Destroy(); Root = ZoneBlueprintVisuals.CreateBlueprintVisualRoot(blueprint, objectName); SetTransform(position, rotation); if ((Object)(object)parent != (Object)null) { Root.transform.SetParent(parent, true); } return Root; } public GameObject CreateEmpty(string objectName) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown Destroy(); Root = new GameObject(objectName); return Root; } public void Adopt(GameObject root, Material? material) { Destroy(); Root = root; Material = material; } public void SetTransform(Vector3 position, Quaternion rotation) { //IL_0014: 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 (HasRoot) { Root.transform.position = position; Root.transform.rotation = rotation; } } public Material ApplyMaterial(Color color) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) Material = ApplyMaterial(Root, color, Material); return Material; } public Material ApplyMaterial(GameObject target, Color color) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) Material = ApplyMaterial(target, color, Material); return Material; } public void UpdateMaterialColor(Color color) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Material != (Object)null) { Material.color = color; } } public void Destroy() { if ((Object)(object)Root != (Object)null && Object.op_Implicit((Object)(object)Root)) { Object.Destroy((Object)(object)Root); } if ((Object)(object)Material != (Object)null) { Object.Destroy((Object)(object)Material); } Root = null; Material = null; } public static Material ApplyMaterial(GameObject? root, Color color, Material? material = null) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) if (material == null) { material = CreateMaterial(color); } material.color = color; if ((Object)(object)root == (Object)null) { return material; } Renderer[] componentsInChildren = root.GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { Material[] sharedMaterials = val.sharedMaterials; for (int j = 0; j < sharedMaterials.Length; j++) { sharedMaterials[j] = material; } val.sharedMaterials = sharedMaterials; val.shadowCastingMode = (ShadowCastingMode)0; val.receiveShadows = false; } return material; } private static Material CreateMaterial(Color color) { //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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown return new Material(Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Color") ?? Shader.Find("Standard")) { color = color }; } } internal static class ZoneBlueprintNetworkPayload { private readonly struct QueuedWork { public string Label { get; } public ManualLogSource Logger { get; } public long Sender { get; } public int EstimatedBytes { get; } public Action Execute { get; } public QueuedWork(string label, ManualLogSource logger, long sender, int estimatedBytes, Action execute) { Label = label; Logger = logger; Sender = sender; EstimatedBytes = estimatedBytes; Execute = execute; } } public readonly struct RawEnvelopePayload { public byte[] CompressedEnvelope { get; } public byte[] BlueprintPayload { get; } public int MaxOutputBytes { get; } public RawEnvelopePayload(byte[] compressedEnvelope, byte[] blueprintPayload, int maxOutputBytes) { CompressedEnvelope = compressedEnvelope ?? Array.Empty(); BlueprintPayload = blueprintPayload ?? Array.Empty(); MaxOutputBytes = Math.Max(1, maxOutputBytes); } } private readonly struct IngressWindow { public float StartedAt { get; } public int Count { get; } public IngressWindow(float startedAt, int count) { StartedAt = startedAt; Count = count; } } public const string GzipEncoding = "gzip"; private const int MaxEnvelopeOverheadBytes = 524288; private const int MaxCompressedEnvelopeBytes = 8388608; private const int MaxQueuedWorkItems = 32; private const int MaxQueuedWorkItemsPerSender = 4; private const int MaxIngressRequestsPerSender = 12; private const float IngressWindowSeconds = 2f; private const float IngressCleanupSeconds = 60f; private static readonly Queue WorkQueue = new Queue(); private static readonly Dictionary IngressBySender = new Dictionary(); private static int _queuedBytes; private static float _nextIngressCleanup; public static int MaxUploadEnvelopeBytes => Math.Max(1048576, BlueprintConfig.NetworkSettings.MaxIconBytes + 524288); private static int MaxGeneralEnvelopeBytes => Math.Max(16777216, MaxUploadEnvelopeBytes); private static int MaxCompressedBlueprintPayloadBytes => Math.Max(1048576, BlueprintConfig.NetworkSettings.MaxUploadBytes); private static int MaxGeneralBlueprintBytes => Math.Max(16777216, BlueprintConfig.NetworkSettings.MaxUploadBytes); private static int MaxQueuedPayloadBytes => Math.Max(4194304, BlueprintConfig.NetworkSettings.MaxUploadBytes * 4); public static void Update() { if (WorkQueue.Count == 0) { return; } QueuedWork queuedWork = WorkQueue.Dequeue(); _queuedBytes = Math.Max(0, _queuedBytes - queuedWork.EstimatedBytes); try { queuedWork.Execute(); } catch (Exception arg) { ManualLogSource logger = queuedWork.Logger; if (logger != null) { logger.LogError((object)$"{queuedWork.Label} failed: {arg}"); } } } public static bool TryEnqueue(string label, ManualLogSource logger, long sender, int estimatedBytes, Action execute, out string reason) { reason = ""; estimatedBytes = Math.Max(1, estimatedBytes); if (WorkQueue.Count >= 32) { reason = HomesteadLocalization.Format("hs_blueprint_rpc_queue_busy", WorkQueue.Count, 32); return false; } if (sender != 0L && WorkQueue.Count((QueuedWork item) => item.Sender == sender) >= 4) { reason = HomesteadLocalization.Format("hs_blueprint_rpc_queue_busy_player", 4); return false; } int maxQueuedPayloadBytes = MaxQueuedPayloadBytes; if (_queuedBytes + estimatedBytes > maxQueuedPayloadBytes) { reason = HomesteadLocalization.Format("hs_blueprint_rpc_queue_full", FormatBytes(_queuedBytes), FormatBytes(maxQueuedPayloadBytes)); return false; } WorkQueue.Enqueue(new QueuedWork(label, logger, sender, estimatedBytes, execute)); _queuedBytes += estimatedBytes; return true; } public static bool TryReserveIngress(long sender, out string reason) { reason = ""; if (sender == 0L) { return true; } float realtimeSinceStartup = Time.realtimeSinceStartup; if (realtimeSinceStartup >= _nextIngressCleanup) { _nextIngressCleanup = realtimeSinceStartup + 60f; List list = null; foreach (KeyValuePair item in IngressBySender) { if (!(realtimeSinceStartup - item.Value.StartedAt <= 60f)) { if (list == null) { list = new List(); } list.Add(item.Key); } } if (list != null) { foreach (long item2 in list) { IngressBySender.Remove(item2); } } } if (!IngressBySender.TryGetValue(sender, out var value) || realtimeSinceStartup - value.StartedAt >= 2f) { IngressBySender[sender] = new IngressWindow(realtimeSinceStartup, 1); return true; } if (value.Count >= 12) { reason = HomesteadLocalization.Format("hs_blueprint_rpc_ingress_busy_player", 12, 2f); return false; } IngressBySender[sender] = new IngressWindow(value.StartedAt, value.Count + 1); return true; } public static void WriteEnvelope(ZPackage package, string yaml, byte[]? blueprintPayload = null) { package.Write(CompressUtf8(yaml)); bool flag = blueprintPayload != null && blueprintPayload.Length > 0; package.Write(flag); if (flag) { package.Write(blueprintPayload); } } public static string ReadEnvelope(ZPackage package) { byte[] blueprintPayload; return ReadEnvelope(package, out blueprintPayload, MaxGeneralEnvelopeBytes); } public static string ReadEnvelope(ZPackage package, int maxOutputBytes) { byte[] blueprintPayload; return ReadEnvelope(package, out blueprintPayload, maxOutputBytes); } public static string ReadEnvelope(ZPackage package, out byte[] blueprintPayload) { return ReadEnvelope(package, out blueprintPayload, MaxGeneralEnvelopeBytes); } public static string ReadEnvelope(ZPackage package, out byte[] blueprintPayload, int maxOutputBytes) { return ReadEnvelope(ReadRawEnvelope(package, maxOutputBytes), out blueprintPayload); } public static RawEnvelopePayload ReadRawEnvelope(ZPackage package, int maxOutputBytes) { byte[] array = package.ReadByteArray().ToArray(); if (array.Length > 8388608) { throw new InvalidDataException(HomesteadLocalization.Format("hs_rpc_payload_too_large_compressed", FormatBytes(array.Length))); } byte[] array2 = Array.Empty(); if (package.ReadBool()) { array2 = package.ReadByteArray().ToArray(); if (array2.Length > MaxCompressedBlueprintPayloadBytes) { throw new InvalidDataException(HomesteadLocalization.Format("hs_blueprint_payload_too_large_throw", FormatBytes(array2.Length))); } } return new RawEnvelopePayload(array, array2, maxOutputBytes); } public static string ReadEnvelope(RawEnvelopePayload raw, out byte[] blueprintPayload) { blueprintPayload = raw.BlueprintPayload; return DecompressUtf8(raw.CompressedEnvelope, raw.MaxOutputBytes); } public static bool TryCreateBlueprintPayload(string yaml, bool enforceUploadLimit, out byte[] payload, out string reason) { payload = Array.Empty(); if (enforceUploadLimit && !TryValidateBlueprintYamlSize(yaml, out reason)) { return false; } payload = CompressUtf8(yaml ?? ""); if (payload.Length > MaxCompressedBlueprintPayloadBytes) { reason = HomesteadLocalization.Format("hs_blueprint_payload_too_large_compressed", FormatBytes(payload.Length), FormatBytes(MaxCompressedBlueprintPayloadBytes)); payload = Array.Empty(); return false; } reason = ""; return true; } public static int EstimateQueuedBytes(string envelopeYaml, byte[] blueprintPayload) { long num = Encoding.UTF8.GetByteCount(envelopeYaml ?? "") + ((blueprintPayload != null) ? blueprintPayload.Length : 0); if (num < int.MaxValue) { return Math.Max(1, (int)num); } return int.MaxValue; } public static int EstimateQueuedBytes(RawEnvelopePayload raw) { long num = Math.Min(raw.MaxOutputBytes, Math.Max((long)raw.CompressedEnvelope.Length + 65536L, (long)raw.CompressedEnvelope.Length * 8L)) + raw.BlueprintPayload.Length; if (num < int.MaxValue) { return Math.Max(1, (int)num); } return int.MaxValue; } public static TEnvelope CreateEnvelope(string type, TPayload payload) where TEnvelope : IZoneBlueprintRpcEnvelope, new() { TEnvelope val = new TEnvelope { Type = type, PayloadYaml = HomesteadYaml.Serialize(payload) }; TEnvelope result = val; if ((object)payload is IZoneBlueprintPayloadCarrier zoneBlueprintPayloadCarrier && zoneBlueprintPayloadCarrier.BlueprintPayload.Length != 0) { ref TEnvelope reference = ref result; val = default(TEnvelope); if (val == null) { val = reference; reference = ref val; } reference.BlueprintPayload = zoneBlueprintPayloadCarrier.BlueprintPayload; } return result; } public static TPayload ReadPayload(TEnvelope envelope) where TEnvelope : IZoneBlueprintRpcEnvelope { TPayload val = HomesteadYaml.Deserialize(envelope.PayloadYaml); if ((object)val is IZoneBlueprintPayloadCarrier zoneBlueprintPayloadCarrier && envelope.BlueprintPayload.Length != 0) { zoneBlueprintPayloadCarrier.BlueprintPayload = envelope.BlueprintPayload; } return val; } public static bool TryDeserializeBlueprintUpload(byte[] payload, string encoding, out ZoneBlueprintFile blueprint, out string reason) { blueprint = null; if (!TryDecodeBlueprintPayloadToYaml(payload, encoding, BlueprintConfig.NetworkSettings.MaxUploadBytes, out string yaml, out reason)) { return false; } try { blueprint = HomesteadYaml.Deserialize(yaml); } catch (Exception ex) { reason = HomesteadLocalization.Format("hs_blueprint_payload_invalid", ex.Message); return false; } if (!TryValidateBlueprintEntryCount(blueprint, upload: true, out reason)) { return false; } return true; } public static bool TryDeserializeBlueprintPayload(byte[] payload, string encoding, out ZoneBlueprintFile blueprint, out string reason) { blueprint = null; if (!TryDecodeBlueprintPayloadToYaml(payload, encoding, MaxGeneralBlueprintBytes, out string yaml, out reason)) { return false; } try { blueprint = HomesteadYaml.Deserialize(yaml); } catch (Exception ex) { reason = HomesteadLocalization.Format("hs_blueprint_payload_invalid", ex.Message); return false; } return true; } public static bool TryDecodeBlueprintPayloadToYaml(byte[] payload, string encoding, out string yaml, out string reason) { return TryDecodeBlueprintPayloadToYaml(payload, encoding, MaxGeneralBlueprintBytes, out yaml, out reason); } public static bool TryDecodeBlueprintPayloadToYaml(byte[] payload, string encoding, int maxOutputBytes, out string yaml, out string reason) { yaml = ""; reason = ""; if (payload == null || payload.Length == 0) { reason = HomesteadLocalization.Text("hs_blueprint_payload_missing"); return false; } if (payload.Length > MaxCompressedBlueprintPayloadBytes) { reason = HomesteadLocalization.Format("hs_blueprint_payload_too_large_compressed", FormatBytes(payload.Length), FormatBytes(MaxCompressedBlueprintPayloadBytes)); return false; } if (!string.Equals(encoding, "gzip", StringComparison.OrdinalIgnoreCase)) { reason = HomesteadLocalization.Format("hs_blueprint_payload_encoding_unsupported", encoding); return false; } try { yaml = DecompressUtf8(payload, maxOutputBytes); return true; } catch (Exception ex) { reason = HomesteadLocalization.Format("hs_blueprint_payload_invalid", ex.Message); return false; } } public static bool TryCreatePreviewYaml(ZoneBlueprintFile source, out string previewYaml, out string reason) { previewYaml = ""; ZoneBlueprintFile zoneBlueprintFile = ZoneBlueprintStorePreviewPayload.CreatePreviewBlueprint(source); if (!TryValidateBlueprintEntryCount(zoneBlueprintFile, upload: false, out reason)) { return false; } previewYaml = HomesteadYaml.Serialize(zoneBlueprintFile); int byteCount = Encoding.UTF8.GetByteCount(previewYaml); int maxUploadBytes = BlueprintConfig.NetworkSettings.MaxUploadBytes; if (byteCount > maxUploadBytes) { reason = HomesteadLocalization.Format("hs_blueprint_preview_payload_too_large", FormatBytes(byteCount), FormatBytes(maxUploadBytes)); previewYaml = ""; return false; } return true; } public static bool TryCreatePreviewPayload(ZoneBlueprintFile source, out byte[] payload, out string reason) { payload = Array.Empty(); if (!TryCreatePreviewYaml(source, out string previewYaml, out reason)) { return false; } return TryCreateBlueprintPayload(previewYaml, enforceUploadLimit: false, out payload, out reason); } public static bool TryValidateIconBase64(string payload, out string reason) { reason = ""; if (string.IsNullOrWhiteSpace(payload)) { return true; } int maxIconBytes = BlueprintConfig.NetworkSettings.MaxIconBytes; if (maxIconBytes <= 0) { reason = HomesteadLocalization.Text("hs_store_icon_upload_disabled"); return false; } int num = EstimateBase64Bytes(payload); if (num > maxIconBytes) { reason = HomesteadLocalization.Format("hs_store_icon_too_large", FormatBytes(num), FormatBytes(maxIconBytes)); return false; } try { byte[] array = Convert.FromBase64String(payload); if (array.Length > maxIconBytes) { reason = HomesteadLocalization.Format("hs_store_icon_too_large", FormatBytes(array.Length), FormatBytes(maxIconBytes)); return false; } } catch (Exception ex) { reason = HomesteadLocalization.Format("hs_store_icon_payload_invalid", ex.Message); return false; } return true; } public static bool ShouldSendIconBase64(string payload) { if (!string.IsNullOrWhiteSpace(payload)) { if (BlueprintConfig.NetworkSettings.MaxIconBytes > 0) { return EstimateBase64Bytes(payload) <= BlueprintConfig.NetworkSettings.MaxIconBytes; } return false; } return true; } public static bool TryValidateBlueprintYamlSize(string yaml, out string reason) { reason = ""; int byteCount = Encoding.UTF8.GetByteCount(yaml ?? ""); int maxUploadBytes = BlueprintConfig.NetworkSettings.MaxUploadBytes; if (byteCount > maxUploadBytes) { reason = HomesteadLocalization.Format("hs_blueprint_upload_too_large", FormatBytes(byteCount), FormatBytes(maxUploadBytes)); return false; } return true; } public static bool TryValidateBlueprintEntryCount(ZoneBlueprintFile blueprint, bool upload, out string reason) { reason = ""; BlueprintNetworkSettings networkSettings = BlueprintConfig.NetworkSettings; int num = (upload ? networkSettings.MaxEntries : networkSettings.MaxPreviewEntries); int valueOrDefault = (blueprint?.Entries?.Count).GetValueOrDefault(); if (valueOrDefault > num) { string text = (upload ? HomesteadLocalization.Text("hs_blueprint_payload_kind_upload") : HomesteadLocalization.Text("hs_blueprint_payload_kind_preview")); reason = HomesteadLocalization.Format("hs_blueprint_entry_count_too_high", text, valueOrDefault, num); return false; } return true; } public static string FormatBytes(int bytes) { if (bytes >= 1048576) { return $"{(float)bytes / 1024f / 1024f:0.##} MB"; } return $"{Mathf.CeilToInt((float)bytes / 1024f)} KB"; } private static byte[] CompressUtf8(string value) { byte[] bytes = Encoding.UTF8.GetBytes(value ?? ""); using MemoryStream memoryStream = new MemoryStream(); using (GZipStream gZipStream = new GZipStream(memoryStream, CompressionMode.Compress)) { gZipStream.Write(bytes, 0, bytes.Length); } return memoryStream.ToArray(); } private static string DecompressUtf8(byte[] compressed, int maxOutputBytes) { using MemoryStream stream = new MemoryStream(compressed); using GZipStream gZipStream = new GZipStream(stream, CompressionMode.Decompress); using MemoryStream memoryStream = new MemoryStream(); byte[] array = new byte[16384]; int count; while ((count = gZipStream.Read(array, 0, array.Length)) > 0) { memoryStream.Write(array, 0, count); if (memoryStream.Length > maxOutputBytes) { throw new InvalidDataException(HomesteadLocalization.Format("hs_rpc_payload_too_large_uncompressed", FormatBytes((int)memoryStream.Length))); } } return Encoding.UTF8.GetString(memoryStream.ToArray()); } private static int EstimateBase64Bytes(string payload) { string text = payload.Trim(); int num = 0; if (text.EndsWith("==", StringComparison.Ordinal)) { num = 2; } else if (text.EndsWith("=", StringComparison.Ordinal)) { num = 1; } return Math.Max(0, text.Length * 3 / 4 - num); } } internal static class ZoneBlueprintPlanRpc { private const string RequestRpcName = "sighsorry.Homestead_BlueprintPlanRequest"; private const string ResponseRpcName = "sighsorry.Homestead_BlueprintPlanResponse"; private const float MaxRequestedChestDistanceFromAnchor = 512f; private static ManualLogSource _logger = null; private static bool _initialized; private static readonly ZoneRpcRegistrar RpcRegistrar = new ZoneRpcRegistrar(); private static readonly Dictionary PreviewCache = new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly HashSet PendingPreviewRequests = new HashSet(StringComparer.OrdinalIgnoreCase); public static void Initialize(ManualLogSource logger) { if (!_initialized) { _initialized = true; _logger = logger; RegisterRpcs(); } } public static void Update() { RegisterRpcs(); } public static void ResetForWorldSession() { PreviewCache.Clear(); PendingPreviewRequests.Clear(); } public static void RequestPlace(string name, ZoneBlueprintFile blueprint, Vector3 anchor, Quaternion anchorRotation, Vector3 chestPosition, Quaternion chestRotation) { //IL_00f0: 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_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: 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_0067: 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_0075: Unknown result type (might be due to invalid IL or missing references) byte[] payload; string reason; if ((Object)(object)ZNet.instance == (Object)null) { Message(HomesteadLocalization.Text("hs_common_world_not_ready"), (MessageType)2); } else if (!ZoneBlueprintNetworkPayload.TryCreateBlueprintPayload(HomesteadYaml.Serialize(blueprint), enforceUploadLimit: true, out payload, out reason)) { Message(reason, (MessageType)2); } else if (ZNet.instance.IsServer()) { HandleResponse(ExecutePlace(new ZoneBlueprintPlanPlaceRequest { Name = name, BlueprintEncoding = "gzip", BlueprintPayload = payload, Anchor = ToTransformPayload(anchor, anchorRotation), Chest = ToTransformPayload(chestPosition, chestRotation) }, 0L, ((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetPlayerID() : 0, ((Object)(object)Player.m_localPlayer != (Object)null) ? HomesteadPlayerIdentity.ResolveLocalPlatformId(Player.m_localPlayer.GetPlayerID()) : "")); } else { SendRequest("place", new ZoneBlueprintPlanPlaceRequest { Name = name, BlueprintEncoding = "gzip", BlueprintPayload = payload, Anchor = ToTransformPayload(anchor, anchorRotation), Chest = ToTransformPayload(chestPosition, chestRotation) }); } } public static void RequestPreview(string name) { if (!string.IsNullOrWhiteSpace(name) && !PreviewCache.ContainsKey(name) && !PendingPreviewRequests.Contains(name) && !((Object)(object)ZNet.instance == (Object)null) && !ZNet.instance.IsServer()) { PendingPreviewRequests.Add(name); SendRequest("preview", new ZoneBlueprintPlanPreviewRequest { Name = name }); } } public static bool TryGetCachedPreview(string name, out ZoneBlueprintFile blueprint) { return PreviewCache.TryGetValue(name, out blueprint); } public static bool IsPreviewPending(string name) { if (!string.IsNullOrWhiteSpace(name)) { return PendingPreviewRequests.Contains(name); } return false; } private static void CachePreview(string name, ZoneBlueprintFile blueprint) { if (!string.IsNullOrWhiteSpace(name) && blueprint != null) { blueprint.Name = name; PreviewCache[name] = blueprint; PendingPreviewRequests.Remove(name); } } private static void RegisterRpcs() { RpcRegistrar.EnsureRegistered(delegate(ZRoutedRpc routedRpc) { routedRpc.Register("sighsorry.Homestead_BlueprintPlanRequest", (Action)RPC_HandleRequest); routedRpc.Register("sighsorry.Homestead_BlueprintPlanResponse", (Action)RPC_HandleResponse); }); } private static void SendRequest(string type, TPayload payload) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown RegisterRpcs(); if (ZRoutedRpc.instance != null) { ZoneBlueprintPlanRpcEnvelope zoneBlueprintPlanRpcEnvelope = CreateEnvelope(type, payload); ZPackage val = new ZPackage(); ZoneBlueprintNetworkPayload.WriteEnvelope(val, HomesteadYaml.Serialize(zoneBlueprintPlanRpcEnvelope), zoneBlueprintPlanRpcEnvelope.BlueprintPayload); ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), "sighsorry.Homestead_BlueprintPlanRequest", new object[1] { val }); } } private static void RPC_HandleRequest(long sender, ZPackage package) { if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return; } if (!ZoneBlueprintNetworkPayload.TryReserveIngress(sender, out string reason)) { SendResponse(sender, CreateEnvelope("place", new ZoneBlueprintPlanPlaceResponse { Success = false, Message = reason })); return; } ZoneBlueprintNetworkPayload.RawEnvelopePayload rawPayload; try { rawPayload = ZoneBlueprintNetworkPayload.ReadRawEnvelope(package, ZoneBlueprintNetworkPayload.MaxUploadEnvelopeBytes); } catch (Exception ex) { _logger.LogError((object)$"Blueprint plan RPC failed: {ex}"); SendResponse(sender, CreateEnvelope("place", new ZoneBlueprintPlanPlaceResponse { Success = false, Message = ex.Message })); return; } int estimatedBytes = ZoneBlueprintNetworkPayload.EstimateQueuedBytes(rawPayload); if (!ZoneBlueprintNetworkPayload.TryEnqueue("Blueprint plan RPC", _logger, sender, estimatedBytes, delegate { ZoneBlueprintPlanRpcEnvelope response; try { byte[] blueprintPayload; ZoneBlueprintPlanRpcEnvelope zoneBlueprintPlanRpcEnvelope = HomesteadYaml.Deserialize(ZoneBlueprintNetworkPayload.ReadEnvelope(rawPayload, out blueprintPayload)); zoneBlueprintPlanRpcEnvelope.BlueprintPayload = blueprintPayload; response = ExecuteRequest(zoneBlueprintPlanRpcEnvelope, sender); } catch (Exception ex2) { _logger.LogError((object)$"Blueprint plan RPC failed: {ex2}"); response = CreateEnvelope("place", new ZoneBlueprintPlanPlaceResponse { Success = false, Message = ex2.Message }); } SendResponse(sender, response); }, out string reason2)) { SendResponse(sender, CreateEnvelope("place", new ZoneBlueprintPlanPlaceResponse { Success = false, Message = reason2 })); } } private static void RPC_HandleResponse(long sender, ZPackage package) { if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { return; } try { byte[] blueprintPayload; ZoneBlueprintPlanRpcEnvelope zoneBlueprintPlanRpcEnvelope = HomesteadYaml.Deserialize(ZoneBlueprintNetworkPayload.ReadEnvelope(package, out blueprintPayload)); zoneBlueprintPlanRpcEnvelope.BlueprintPayload = blueprintPayload; HandleResponse(zoneBlueprintPlanRpcEnvelope); } catch (Exception ex) { _logger.LogWarning((object)("Failed to read blueprint plan response: " + ex.Message)); } } private static ZoneBlueprintPlanRpcEnvelope ExecuteRequest(ZoneBlueprintPlanRpcEnvelope request, long sender) { if (request.Type == "preview") { return ExecutePreview(ReadPayload(request)); } if (!TryResolveRequester(sender, out long playerId, out string reason)) { return CreateEnvelope(request.Type, new ZoneBlueprintPlanPlaceResponse { Success = false, Message = reason }); } if (request.Type == "place") { return ExecutePlace(ReadPayload(request), sender, playerId, HomesteadPlayerIdentity.ResolvePlatformId(null, sender, playerId)); } return CreateEnvelope(request.Type, new ZoneBlueprintPlanPlaceResponse { Success = false, Message = HomesteadLocalization.Format("hs_blueprint_plan_unknown_action", request.Type) }); } private static ZoneBlueprintPlanRpcEnvelope ExecutePlace(ZoneBlueprintPlanPlaceRequest request, long sender, long playerId, string ownerPlatformId) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) ZoneBlueprintPlanPlaceRequest request2 = request; if (!TryReadTransform(request2.Anchor, out var position, out var rotation) || !TryReadTransform(request2.Chest, out var position2, out var rotation2) || !IsFinite(position) || !IsFinite(rotation) || !IsFinite(rotation2)) { return CreateEnvelope("place", Fail(HomesteadLocalization.Text("hs_blueprint_place_payload_missing_transform"))); } if (!ZoneBlueprintNetworkPayload.TryDeserializeBlueprintUpload(request2.BlueprintPayload, request2.BlueprintEncoding, out ZoneBlueprintFile blueprint, out string reason)) { return CreateEnvelope("place", Fail(reason)); } string savedName; HomesteadCommandResult homesteadCommandResult = ZoneBlueprintCommands.SaveUploadedBlueprintForPlan(request2.Name, blueprint, playerId, out savedName); if (!homesteadCommandResult.Success) { return CreateEnvelope("place", Fail(homesteadCommandResult.Message)); } try { ZoneBlueprintFile zoneBlueprintFile = ZoneBlueprintCommands.LoadBlueprintForPlan(savedName); if (ZoneBlueprintCommands.CreateLoadPlanForBlueprint(zoneBlueprintFile, position, rotation).Entries.Count == 0) { return CreateEnvelope("place", Fail(HomesteadLocalization.Format("hs_blueprint_no_valid_entries", savedName))); } if (!ZoneBlueprintNetworkPayload.TryCreateBlueprintPayload(HomesteadYaml.Serialize(zoneBlueprintFile), enforceUploadLimit: false, out byte[] payload, out string reason2)) { return CreateEnvelope("place", Fail(reason2)); } Vector3 val = ResolvePlanChestPosition(zoneBlueprintFile, position, rotation, position2, rotation2); ownerPlatformId = (string.IsNullOrWhiteSpace(ownerPlatformId) ? HomesteadPlayerIdentity.ResolvePlatformId(null, sender, playerId) : ownerPlatformId); HomesteadCommandResult homesteadCommandResult2 = ZoneBlueprintPlanChestPrefab.PlacePlanChest(savedName, playerId, ownerPlatformId, position, rotation, val, rotation2, sender); return CreateEnvelope("place", new ZoneBlueprintPlanPlaceResponse { Success = homesteadCommandResult2.Success, Message = ((homesteadCommandResult2.Success && !string.Equals(savedName, request2.Name, StringComparison.OrdinalIgnoreCase)) ? HomesteadLocalization.Format("hs_blueprint_server_saved_as_existing", homesteadCommandResult2.Message, savedName) : homesteadCommandResult2.Message), RequestedName = request2.Name, BlueprintName = savedName, Chest = (homesteadCommandResult2.Success ? ToTransformPayload(val, rotation2) : null), BlueprintEncoding = "gzip", BlueprintPayload = (homesteadCommandResult2.Success ? payload : Array.Empty()) }); } catch (Exception ex) { return CreateEnvelope("place", Fail(ex.Message)); } ZoneBlueprintPlanPlaceResponse Fail(string message) { return new ZoneBlueprintPlanPlaceResponse { Success = false, Message = message, RequestedName = request2.Name }; } } private static ZoneBlueprintPlanRpcEnvelope ExecutePreview(ZoneBlueprintPlanPreviewRequest request) { try { if (!ZoneBlueprintNetworkPayload.TryCreateBlueprintPayload(ZoneBlueprintCommands.SerializePreviewBlueprintForPlan(request.Name), enforceUploadLimit: false, out byte[] payload, out string reason)) { throw new InvalidOperationException(reason); } return CreateEnvelope("preview", new ZoneBlueprintPlanPreviewResponse { Success = true, Name = request.Name, BlueprintEncoding = "gzip", BlueprintPayload = payload }); } catch (Exception ex) { return CreateEnvelope("preview", new ZoneBlueprintPlanPreviewResponse { Success = false, Name = request.Name, Message = ex.Message }); } } private static void SendResponse(long target, ZoneBlueprintPlanRpcEnvelope response) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown ZPackage val = new ZPackage(); ZoneBlueprintNetworkPayload.WriteEnvelope(val, HomesteadYaml.Serialize(response), response.BlueprintPayload); ZRoutedRpc.instance.InvokeRoutedRPC(target, "sighsorry.Homestead_BlueprintPlanResponse", new object[1] { val }); } private static void HandleResponse(ZoneBlueprintPlanRpcEnvelope response) { if (response.Type == "preview") { ZoneBlueprintPlanPreviewResponse zoneBlueprintPlanPreviewResponse = ReadPayload(response); PendingPreviewRequests.Remove(zoneBlueprintPlanPreviewResponse.Name); if (!zoneBlueprintPlanPreviewResponse.Success) { return; } try { if (ZoneBlueprintNetworkPayload.TryDeserializeBlueprintPayload(zoneBlueprintPlanPreviewResponse.BlueprintPayload, zoneBlueprintPlanPreviewResponse.BlueprintEncoding, out ZoneBlueprintFile blueprint, out string reason)) { CachePreview(zoneBlueprintPlanPreviewResponse.Name, blueprint); } else { _logger.LogWarning((object)("Failed to cache server blueprint preview '" + zoneBlueprintPlanPreviewResponse.Name + "': " + reason)); } return; } catch (Exception ex) { _logger.LogWarning((object)("Failed to cache server blueprint preview '" + zoneBlueprintPlanPreviewResponse.Name + "': " + ex.Message)); return; } } ZoneBlueprintPlanPlaceResponse zoneBlueprintPlanPlaceResponse = ReadPayload(response); if (zoneBlueprintPlanPlaceResponse.Success) { TryPlayPlanChestPlaceVfx(zoneBlueprintPlanPlaceResponse.Chest); } if (zoneBlueprintPlanPlaceResponse.Success && !string.IsNullOrWhiteSpace(zoneBlueprintPlanPlaceResponse.BlueprintName) && zoneBlueprintPlanPlaceResponse.BlueprintPayload.Length != 0) { try { if (ZoneBlueprintNetworkPayload.TryDecodeBlueprintPayloadToYaml(zoneBlueprintPlanPlaceResponse.BlueprintPayload, zoneBlueprintPlanPlaceResponse.BlueprintEncoding, out string yaml, out string reason2)) { ZoneBlueprintFile blueprint2 = HomesteadYaml.Deserialize(yaml); CachePreview(zoneBlueprintPlanPlaceResponse.BlueprintName, blueprint2); ZoneBlueprintCommands.EnsureLocalPlanBlueprintCopy(zoneBlueprintPlanPlaceResponse.BlueprintName, yaml); } else { _logger.LogWarning((object)("Failed to decode server blueprint copy '" + zoneBlueprintPlanPlaceResponse.BlueprintName + "': " + reason2)); } } catch (Exception ex2) { _logger.LogWarning((object)("Failed to save server blueprint copy '" + zoneBlueprintPlanPlaceResponse.BlueprintName + "' locally: " + ex2.Message)); } } if (!string.IsNullOrWhiteSpace(zoneBlueprintPlanPlaceResponse.Message)) { Message(zoneBlueprintPlanPlaceResponse.Message, (MessageType)(zoneBlueprintPlanPlaceResponse.Success ? 1 : 2)); } } private static void TryPlayPlanChestPlaceVfx(ZoneBlueprintStoreTransformPayload? chest) { //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) if ((!((Object)(object)ZNet.instance != (Object)null) || !ZNet.instance.IsServer()) && TryReadTransform(chest, out var position, out var rotation)) { ZoneBlueprintPlanChestPrefab.PlayPlaceEffect(position, rotation); } } private static bool TryResolveRequester(long sender, out long playerId, out string reason) { //IL_0073: Unknown result type (might be due to invalid IL or missing references) playerId = 0L; reason = ""; if ((Object)(object)ZNet.instance == (Object)null || ZDOMan.instance == null) { reason = HomesteadLocalization.Text("hs_common_world_not_ready"); return false; } ZNetPeer peer = ZNet.instance.GetPeer(sender); if (peer == null || !peer.IsReady()) { reason = HomesteadLocalization.Text("hs_common_player_not_ready"); return false; } if (((ZDOID)(ref peer.m_characterID)).IsNone()) { reason = HomesteadLocalization.Text("hs_store_character_missing"); return false; } ZDO zDO = ZDOMan.instance.GetZDO(peer.m_characterID); if (zDO == null) { reason = HomesteadLocalization.Text("hs_store_character_missing"); return false; } playerId = zDO.GetLong(ZDOVars.s_playerID, 0L); if (playerId == 0L) { reason = HomesteadLocalization.Text("hs_dismantle_playerid_missing"); return false; } return true; } private static ZoneBlueprintPlanRpcEnvelope CreateEnvelope(string type, TPayload payload) { return ZoneBlueprintNetworkPayload.CreateEnvelope(type, payload); } private static TPayload ReadPayload(ZoneBlueprintPlanRpcEnvelope envelope) { return ZoneBlueprintNetworkPayload.ReadPayload(envelope); } private static ZoneBlueprintStoreTransformPayload ToTransformPayload(Vector3 position, Quaternion rotation) { //IL_000f: 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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) ZoneBlueprintStoreTransformPayload zoneBlueprintStoreTransformPayload = new ZoneBlueprintStoreTransformPayload(); zoneBlueprintStoreTransformPayload.Pos = new float[3] { position.x, position.y, position.z }; zoneBlueprintStoreTransformPayload.Rot = new float[4] { rotation.x, rotation.y, rotation.z, rotation.w }; return zoneBlueprintStoreTransformPayload; } private static bool TryReadTransform(ZoneBlueprintStoreTransformPayload? payload, out Vector3 position, out Quaternion rotation) { //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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_005a: 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_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) position = Vector3.zero; rotation = Quaternion.identity; if (payload == null || payload.Pos == null || payload.Rot == null || payload.Pos.Length < 3 || payload.Rot.Length < 4) { return false; } position = new Vector3(payload.Pos[0], payload.Pos[1], payload.Pos[2]); rotation = new Quaternion(payload.Rot[0], payload.Rot[1], payload.Rot[2], payload.Rot[3]); return true; } private static Vector3 ResolvePlanChestPosition(ZoneBlueprintFile blueprint, Vector3 anchor, Quaternion anchorRotation, Vector3 requestedChestPosition, Quaternion chestRotation) { //IL_0000: 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_0029: 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_0017: 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) if (!IsFinite(requestedChestPosition) || ((Vector3)(ref requestedChestPosition)).sqrMagnitude < 0.0001f || !IsWithinHorizontalDistance(anchor, requestedChestPosition, 512f)) { return ZoneBlueprintCommands.GetPlanChestPosition(blueprint, anchor, anchorRotation, chestRotation); } return requestedChestPosition; } private static bool IsWithinHorizontalDistance(Vector3 origin, Vector3 target, float maxDistance) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) float num = target.x - origin.x; float num2 = target.z - origin.z; return num * num + num2 * num2 <= maxDistance * maxDistance; } private static bool IsFinite(Vector3 value) { //IL_0000: 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_001a: Unknown result type (might be due to invalid IL or missing references) if (IsFinite(value.x) && IsFinite(value.y)) { return IsFinite(value.z); } return false; } private static bool IsFinite(Quaternion value) { //IL_0000: 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_001a: 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) if (IsFinite(value.x) && IsFinite(value.y) && IsFinite(value.z)) { return IsFinite(value.w); } return false; } private static bool IsFinite(float value) { if (!float.IsNaN(value)) { return !float.IsInfinity(value); } return false; } private static void Message(string message, MessageType type) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) ManualLogSource logger = _logger; if (logger != null) { logger.LogInfo((object)message); } Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message(type, message, 0, (Sprite)null); } } } internal sealed class ZoneBlueprintPlacementTool : MonoBehaviour { private const float MaxPlacementDistance = 128f; private static ManualLogSource? _logger; private static ZoneBlueprintPlacementTool? _instance; private string _blueprintName = ""; private ZoneBlueprintFile? _blueprint; private GameObject? _previewRoot; private GameObject? _chestPreviewRoot; private bool _active; private int _suppressInputFrames; private Vector3 _anchor; private Quaternion _anchorRotation = Quaternion.identity; private Quaternion _chestRotation = Quaternion.identity; private float _placementYaw; private float _heightOffset; private Vector3 _horizontalOffset; public static bool IsActive => _instance?._active ?? false; public static void Initialize(ManualLogSource logger) { _logger = logger; EnsureInstance(); } public static void Activate(Player player, string blueprintName) { EnsureInstance(); _instance?.ActivateInternal(player, blueprintName); } public static void Deactivate() { _instance?.DeactivateInternal(); } private static void EnsureInstance() { //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_002a: Expected O, but got Unknown if (!((Object)(object)_instance != (Object)null) || !Object.op_Implicit((Object)(object)_instance)) { GameObject val = new GameObject("HomesteadBlueprintPlacementTool"); Object.DontDestroyOnLoad((Object)val); _instance = val.AddComponent(); } } private void ActivateInternal(Player player, string blueprintName) { //IL_003a: 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_0042: 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_0058: 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_006e: Unknown result type (might be due to invalid IL or missing references) if (_active && string.Equals(_blueprintName, blueprintName, StringComparison.OrdinalIgnoreCase)) { return; } ClearPreview(); _active = true; _blueprintName = blueprintName; _suppressInputFrames = 2; Quaternion rotation = ((Component)player).transform.rotation; _placementYaw = ((Quaternion)(ref rotation)).eulerAngles.y; _chestRotation = GetAimYawRotation(player); _heightOffset = 0f; _horizontalOffset = Vector3.zero; if (!ZoneBlueprintCommands.TryLoadBlueprint(blueprintName, out ZoneBlueprintFile blueprint)) { Message(player, HomesteadLocalization.Format("hs_blueprint_load_failed_plain", blueprintName)); DeactivateInternal(); return; } _blueprint = blueprint; _previewRoot = ZoneBlueprintVisuals.CreateBlueprintVisualRoot(blueprint, "HomesteadBlueprintPreview_" + blueprintName); _previewRoot.transform.SetParent(((Component)this).transform, false); _chestPreviewRoot = ZoneBlueprintPlanChestPrefab.CreatePreview(); GameObject? chestPreviewRoot = _chestPreviewRoot; if (chestPreviewRoot != null) { chestPreviewRoot.transform.SetParent(((Component)this).transform, false); } } private void DeactivateInternal() { //IL_0025: 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) _active = false; _blueprintName = ""; _blueprint = null; _heightOffset = 0f; _horizontalOffset = Vector3.zero; ZoneAreaToolStatusHud.Hide(); ClearPreview(); } private void Update() { //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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) if (!_active) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || !IsHoldingBuildTool(localPlayer)) { DeactivateInternal(); return; } if (!TryGetAimPoint(localPlayer, out var point)) { SetPreviewVisible(visible: false); ZoneAreaToolStatusHud.Hide(); return; } _anchorRotation = Quaternion.Euler(0f, _placementYaw, 0f); _anchor = GetAdjustedAnchor(point, _anchorRotation); _chestRotation = GetAimYawRotation(localPlayer); if (ShouldBlockInput()) { UpdatePreviewTransform(); UpdateStatusHud(); return; } if (_suppressInputFrames > 0) { _suppressInputFrames--; UpdatePreviewTransform(); UpdateStatusHud(); return; } if (Input.GetKeyDown((KeyCode)27)) { ResetOffsets(); } float axis = Input.GetAxis("Mouse ScrollWheel"); if (Mathf.Abs(axis) > 0.001f) { ZoneAreaCameraZoomGuard.SuppressWheelZoomThisFrame(); float num = ((axis > 0f) ? PlacementControlConfig.RotationStep : (0f - PlacementControlConfig.RotationStep)); _placementYaw = Mathf.Repeat(_placementYaw + num, 360f); } if (PlacementControlConfig.IsPlacementAdjustModifierHeld() && (Input.GetKeyDown((KeyCode)280) || Input.GetKeyDown((KeyCode)281))) { float num2 = (Input.GetKeyDown((KeyCode)280) ? 1f : (-1f)); _heightOffset = RoundHeightOffset(_heightOffset + num2 * PlacementControlConfig.HeightStep); } Vector3 val = (PlacementControlConfig.IsPlacementAdjustModifierHeld() ? ZonePlacementOffset.GetArrowKeyLocalNudge() : Vector3.zero); if (((Vector3)(ref val)).sqrMagnitude > 0.0001f) { _horizontalOffset += val * PlacementControlConfig.HorizontalStep; } _anchorRotation = Quaternion.Euler(0f, _placementYaw, 0f); _anchor = GetAdjustedAnchor(point, _anchorRotation); UpdatePreviewTransform(); UpdateStatusHud(); if (Input.GetMouseButtonDown(0)) { Place(localPlayer); } } private void UpdateStatusHud() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) ZoneAreaToolStatusHud.ShowBlueprint("Blueprint Placement", _placementYaw, _horizontalOffset, _heightOffset); } private void OnDestroy() { ClearPreview(); if ((Object)(object)_instance == (Object)(object)this) { _instance = null; } } private void Place(Player player) { //IL_001e: 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_002a: Unknown result type (might be due to invalid IL or missing references) if (_blueprint != null && !string.IsNullOrWhiteSpace(_blueprintName)) { HomesteadCommandResult homesteadCommandResult = ZoneBlueprintCommands.PlaceBlueprintPlanAt(_blueprintName, player, _anchor, _anchorRotation, _chestRotation); Message(player, homesteadCommandResult.Message, (MessageType)(homesteadCommandResult.Success ? 1 : 2)); } } private void UpdatePreviewTransform() { //IL_0027: 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_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: 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_00db: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_previewRoot == (Object)null) { return; } _previewRoot.SetActive(true); _previewRoot.transform.position = _anchor; _previewRoot.transform.rotation = _anchorRotation; if (_blueprint == null) { return; } if ((Object)(object)_chestPreviewRoot == (Object)null) { _chestPreviewRoot = ZoneBlueprintPlanChestPrefab.CreatePreview(); GameObject? chestPreviewRoot = _chestPreviewRoot; if (chestPreviewRoot != null) { chestPreviewRoot.transform.SetParent(((Component)this).transform, false); } } if ((Object)(object)_chestPreviewRoot != (Object)null) { _chestPreviewRoot.SetActive(true); _chestPreviewRoot.transform.position = ZoneBlueprintCommands.GetPlanChestPosition(_blueprint, _anchor, _anchorRotation, _chestRotation); _chestPreviewRoot.transform.rotation = _chestRotation; } } private void SetPreviewVisible(bool visible) { if ((Object)(object)_previewRoot != (Object)null) { _previewRoot.SetActive(visible); } if ((Object)(object)_chestPreviewRoot != (Object)null) { _chestPreviewRoot.SetActive(visible); } } private void ClearPreview() { if ((Object)(object)_previewRoot != (Object)null) { Object.Destroy((Object)(object)_previewRoot); _previewRoot = null; } if ((Object)(object)_chestPreviewRoot != (Object)null) { Object.Destroy((Object)(object)_chestPreviewRoot); _chestPreviewRoot = null; } } private static bool TryGetAimPoint(Player player, out Vector3 point) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: 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_002d: 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) Camera mainCamera = Utils.GetMainCamera(); RaycastHit val = default(RaycastHit); if ((Object)(object)mainCamera != (Object)null && Physics.Raycast(mainCamera.ScreenPointToRay(new Vector3((float)Screen.width * 0.5f, (float)Screen.height * 0.5f)), ref val, 128f, -5, (QueryTriggerInteraction)1)) { point = ((RaycastHit)(ref val)).point; point.y = SampleGroundY(point.x, point.z, point.y); return true; } point = ((Component)player).transform.position + ((Component)player).transform.forward * 8f; point.y = SampleGroundY(point.x, point.z, ((Component)player).transform.position.y); return true; } private Vector3 GetAdjustedAnchor(Vector3 aimPoint, Quaternion rotation) { //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_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000e: 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) return aimPoint + ZonePlacementOffset.ToWorldOffset(rotation, _horizontalOffset, _heightOffset); } private void ResetOffsets() { //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) _heightOffset = 0f; _horizontalOffset = Vector3.zero; } private static float SampleGroundY(float x, float z, float fallbackY) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZoneSystem.instance == (Object)null) { return fallbackY; } Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(x, fallbackY, z); Vector3 val2 = default(Vector3); Biome val3 = default(Biome); BiomeArea val4 = default(BiomeArea); Heightmap val5 = default(Heightmap); ZoneSystem.instance.GetGroundData(ref val, ref val2, ref val3, ref val4, ref val5); return val.y; } private static Quaternion GetYawRotation(Quaternion rotation) { //IL_0007: 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) return Quaternion.Euler(0f, ((Quaternion)(ref rotation)).eulerAngles.y, 0f); } private static Quaternion GetAimYawRotation(Player player) { //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_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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) Camera mainCamera = Utils.GetMainCamera(); if ((Object)(object)mainCamera != (Object)null) { Vector3 forward = ((Component)mainCamera).transform.forward; forward.y = 0f; if (((Vector3)(ref forward)).sqrMagnitude > 0.0001f) { return Quaternion.LookRotation(((Vector3)(ref forward)).normalized, Vector3.up); } } return GetYawRotation(((Component)player).transform.rotation); } private static float RoundHeightOffset(float value) { return Mathf.Round(value * 1000f) / 1000f; } private static bool IsHoldingBuildTool(Player player) { return (Object)(object)((Humanoid)player).GetRightItem()?.m_shared?.m_buildPieces != (Object)null; } private static bool ShouldBlockInput() { if (Hud.IsPieceSelectionVisible() || Console.IsVisible() || TextInput.IsVisible() || Menu.IsVisible() || InventoryGui.IsVisible() || Minimap.IsOpen()) { return true; } if ((Object)(object)Chat.instance != (Object)null) { return Chat.instance.HasFocus(); } return false; } private static void Message(Player player, string message) { Message(player, message, (MessageType)1); } private static void Message(Player player, string message, MessageType type) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) ManualLogSource? logger = _logger; if (logger != null) { logger.LogInfo((object)message); } ((Character)player).Message(type, message, 0, (Sprite)null); } } internal static class ZoneBlueprintChestCommands { private enum BlueprintChestKind { Build, StorePrice, StorePurchase, StorePayout } private sealed class BlueprintChestCommandRequest { public bool DryRun { get; set; } } private sealed class BlueprintChestCommandResult { public bool Success { get; set; } public bool DryRun { get; set; } public int Total { get; set; } public int Deleted { get; set; } public int Build { get; set; } public int StorePrice { get; set; } public int StorePurchase { get; set; } public int StorePayout { get; set; } public int DraftFilesDeleted { get; set; } public string Message { get; set; } = ""; public static BlueprintChestCommandResult Fail(string message) { return new BlueprintChestCommandResult { Success = false, Message = message }; } } [CompilerGenerated] private static class <>O { public static ConsoleEvent <0>__HandleClearCommand; public static Action <1>__RPC_HandleRequest; public static Action <2>__RPC_HandleResult; } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleOptionsFetcher <>9__6_0; public static Action <>9__7_0; public static Func <>9__8_0; public static Func <>9__12_0; internal List b__6_0() { return new List(1) { "dry" }; } internal void b__7_0(ZRoutedRpc routedRpc) { routedRpc.Register("sighsorry.Homestead_BlueprintChestCommandRequest", (Action)RPC_HandleRequest); routedRpc.Register("sighsorry.Homestead_BlueprintChestCommandResult", (Action)RPC_HandleResult); } internal bool b__8_0(string arg) { if (!arg.Equals("dry", StringComparison.OrdinalIgnoreCase)) { return arg.Equals("dry-run", StringComparison.OrdinalIgnoreCase); } return true; } internal bool b__12_0(ZDO zdo) { BlueprintChestKind kind; if (zdo != null && zdo.IsValid()) { return TryGetChestKind(zdo, out kind); } return false; } } private const string ClearCommand = "hs_clearchests"; private const string RequestRpcName = "sighsorry.Homestead_BlueprintChestCommandRequest"; private const string ResultRpcName = "sighsorry.Homestead_BlueprintChestCommandResult"; private static ManualLogSource _logger = null; private static bool _initialized; private static readonly ZoneRpcRegistrar RpcRegistrar = new ZoneRpcRegistrar(); public static void Initialize(ManualLogSource logger) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_0060: 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_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown if (_initialized) { return; } _initialized = true; _logger = logger; object obj = <>O.<0>__HandleClearCommand; if (obj == null) { ConsoleEvent val = HandleClearCommand; <>O.<0>__HandleClearCommand = val; obj = (object)val; } object obj2 = <>c.<>9__6_0; if (obj2 == null) { ConsoleOptionsFetcher val2 = () => new List(1) { "dry" }; <>c.<>9__6_0 = val2; obj2 = (object)val2; } new ConsoleCommand("hs_clearchests", "[dry] - Deletes all Homestead blueprint/build/store chests in the world.", (ConsoleEvent)obj, false, false, false, false, false, (ConsoleOptionsFetcher)obj2, false, false, false); RegisterRpcs(); } internal static void RegisterRpcs() { RpcRegistrar.EnsureRegistered(delegate(ZRoutedRpc routedRpc) { routedRpc.Register("sighsorry.Homestead_BlueprintChestCommandRequest", (Action)RPC_HandleRequest); routedRpc.Register("sighsorry.Homestead_BlueprintChestCommandResult", (Action)RPC_HandleResult); }); } private static void HandleClearCommand(ConsoleEventArgs args) { EnsureCommandReady(); bool dryRun = args.Args.Skip(1).Any((string arg) => arg.Equals("dry", StringComparison.OrdinalIgnoreCase) || arg.Equals("dry-run", StringComparison.OrdinalIgnoreCase)); DispatchRequest(new BlueprintChestCommandRequest { DryRun = dryRun }, args.Context); } private static void DispatchRequest(BlueprintChestCommandRequest request, Terminal? context) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown if (ZNet.instance.IsServer()) { ShowResult(Execute(request), context); return; } RegisterRpcs(); ZPackage val = new ZPackage(); val.Write(HomesteadYaml.Serialize(request)); ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), "sighsorry.Homestead_BlueprintChestCommandRequest", new object[1] { val }); if (context != null) { context.AddString("hs_clearchests request sent to server."); } } private static void RPC_HandleRequest(long sender, ZPackage package) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer()) { BlueprintChestCommandResult value; try { value = (IsAuthorizedSender(sender) ? Execute(HomesteadYaml.Deserialize(package.ReadString())) : BlueprintChestCommandResult.Fail("Admin only.")); } catch (Exception ex) { _logger.LogError((object)$"Blueprint chest command RPC failed: {ex}"); value = BlueprintChestCommandResult.Fail(ex.Message); } ZPackage val = new ZPackage(); val.Write(HomesteadYaml.Serialize(value)); ZRoutedRpc.instance.InvokeRoutedRPC(sender, "sighsorry.Homestead_BlueprintChestCommandResult", new object[1] { val }); } } private static void RPC_HandleResult(long sender, ZPackage package) { if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { return; } try { ShowResult(HomesteadYaml.Deserialize(package.ReadString()), (Terminal?)(object)Console.instance); } catch (Exception arg) { _logger.LogError((object)$"Blueprint chest command result RPC failed: {arg}"); } } private static BlueprintChestCommandResult Execute(BlueprintChestCommandRequest request) { if (ZDOMan.instance == null) { return BlueprintChestCommandResult.Fail("World is not ready."); } List list = ZoneBlueprintChestZdoRegistry.EnumerateChestZdos().ToList(); if (list.Count == 0) { list = ZDOMan.instance.m_objectsByID.Values.Where((ZDO zdo) => zdo != null && zdo.IsValid() && TryGetChestKind(zdo, out var _)).ToList(); } BlueprintChestCommandResult blueprintChestCommandResult = new BlueprintChestCommandResult { Success = true, DryRun = request.DryRun }; foreach (ZDO item in list) { if (!TryGetChestKind(item, out var kind)) { continue; } blueprintChestCommandResult.Total++; switch (kind) { case BlueprintChestKind.Build: blueprintChestCommandResult.Build++; break; case BlueprintChestKind.StorePrice: blueprintChestCommandResult.StorePrice++; if (!request.DryRun && TryCleanupOwnedDraft(item)) { blueprintChestCommandResult.DraftFilesDeleted++; } break; case BlueprintChestKind.StorePurchase: blueprintChestCommandResult.StorePurchase++; break; case BlueprintChestKind.StorePayout: blueprintChestCommandResult.StorePayout++; break; } if (!request.DryRun) { SavedZdoHelper.Destroy(item); blueprintChestCommandResult.Deleted++; } } if (!request.DryRun) { SavedZdoHelper.FlushDestroyed(); } blueprintChestCommandResult.Message = BuildMessage(blueprintChestCommandResult); return blueprintChestCommandResult; } private static bool TryGetChestKind(ZDO zdo, out BlueprintChestKind kind) { kind = BlueprintChestKind.Build; int prefab = zdo.GetPrefab(); if (prefab == ZoneBlueprintPlanChestPrefab.PrefabHash) { kind = BlueprintChestKind.Build; return true; } if (prefab == ZoneBlueprintStoreChestPrefab.PricePrefabHash) { kind = BlueprintChestKind.StorePrice; return true; } if (prefab == ZoneBlueprintStoreChestPrefab.PurchasePrefabHash) { kind = BlueprintChestKind.StorePurchase; return true; } if (prefab == ZoneBlueprintStoreChestPrefab.PayoutPrefabHash) { kind = BlueprintChestKind.StorePayout; return true; } return false; } private static bool TryCleanupOwnedDraft(ZDO zdo) { if (!string.Equals(zdo.GetString("hs_store_mode", ""), "price", StringComparison.Ordinal) || zdo.GetBool("hs_store_confirmed", false) || !zdo.GetBool("hs_store_draft_owned_by_chest", false)) { return false; } string @string = zdo.GetString("hs_store_blueprint_file", ""); ZoneBlueprintStoreDraftRepository.DeleteFile(@string); zdo.Set("hs_store_draft_owned_by_chest", false); ZoneBlueprintChestZdoRegistry.Refresh(zdo); return !string.IsNullOrWhiteSpace(@string); } private static string BuildMessage(BlueprintChestCommandResult result) { string text = (result.DryRun ? "Found" : "Deleted"); return $"{text} {result.Total} Homestead blueprint chest(s): build={result.Build}, price={result.StorePrice}, purchase={result.StorePurchase}, payout={result.StorePayout}, draft files deleted={result.DraftFilesDeleted}."; } private static void EnsureCommandReady() { if ((Object)(object)ZNet.instance == (Object)null) { throw new InvalidOperationException("World is not ready."); } if (!ZNet.instance.IsServer() && ZRoutedRpc.instance == null) { throw new InvalidOperationException("Server RPC is not ready."); } if ((!ZNet.instance.IsServer() || !((Object)(object)Player.m_localPlayer == (Object)null)) && !ZNet.instance.LocalPlayerIsAdminOrHost()) { throw new InvalidOperationException("Admin only."); } } private static bool IsAuthorizedSender(long sender) { ZNetPeer peer = ZNet.instance.GetPeer(sender); object obj; if (peer == null) { obj = null; } else { ZRpc rpc = peer.m_rpc; if (rpc == null) { obj = null; } else { ISocket socket = rpc.m_socket; obj = ((socket != null) ? socket.GetHostName() : null); } } if (obj == null) { obj = ""; } string text = (string)obj; if (text.Length > 0) { return ZNet.instance.IsAdmin(text); } return false; } private static void ShowResult(BlueprintChestCommandResult result, Terminal? terminal) { string message = result.Message; _logger.LogInfo((object)message); if (terminal != null) { terminal.AddString(message); } Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)(result.Success ? 1 : 2), message, 0, (Sprite)null); } } } internal static class ZoneBlueprintChestInventoryScroll { [HarmonyPatch(typeof(InventoryGui), "Show")] private static class InventoryGuiShowPatch { private static void Postfix(InventoryGui __instance, Container container) { Request(container, ((Object)(object)__instance != (Object)null) ? __instance.m_containerGrid : null); } } private const int KeepTopFrames = 3; private static Container? _container; private static int _untilFrame; public static void TryKeepContainerGridAtTop(InventoryGrid? grid) { InventoryGui instance = InventoryGui.instance; if (!((Object)(object)instance == (Object)null) && !((Object)(object)grid == (Object)null) && !((Object)(object)instance.m_containerGrid != (Object)(object)grid) && ShouldKeepAtTop(instance.m_currentContainer) && Time.frameCount <= _untilFrame && !((Object)(object)_container != (Object)(object)instance.m_currentContainer)) { ScrollToTop(grid); } } private static void Request(Container? container, InventoryGrid? grid) { if (ShouldKeepAtTop(container)) { _container = container; _untilFrame = Time.frameCount + 3; ScrollToTop(grid); } } private static bool ShouldKeepAtTop(Container? container) { if (!Object.op_Implicit((Object)(object)container)) { return false; } if (ZoneBlueprintPlanAnchor.TryGetAnchor(container, out ZoneBlueprintPlanAnchor _)) { return true; } if (ZoneBlueprintStoreChestPatchHelper.TryGetStoreChest(container, out ZoneBlueprintStoreChest chest)) { if (!chest.IsPurchaseChest()) { return chest.IsPayoutChest(); } return true; } return false; } private static void ScrollToTop(InventoryGrid? grid) { if (!((Object)(object)grid == (Object)null)) { grid.ResetView(); if ((Object)(object)grid.m_scrollbar != (Object)null) { grid.m_scrollbar.value = 1f; } } } } internal sealed class ZoneBlueprintPlanAnchor : MonoBehaviour { private sealed class RefundMaterial { public string ItemName { get; set; } = ""; public string PrefabName { get; set; } = ""; public int Amount { get; set; } } [HarmonyPatch(typeof(Container), "GetHoverText")] private static class ContainerGetHoverTextPatch { private static bool Prefix(Container __instance, ref string __result) { ZoneBlueprintPlanAnchor component = ((Component)__instance).GetComponent(); if ((Object)(object)component == (Object)null) { return true; } __result = component.GetPlanHoverText(); return false; } } [HarmonyPatch(typeof(Container), "Interact")] private static class ContainerInteractPatch { private static bool Prefix(Container __instance, Humanoid character, bool hold, ref bool __result) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) ZoneBlueprintPlanAnchor component = ((Component)__instance).GetComponent(); if (!((Object)(object)component == (Object)null || hold)) { Player val = (Player)(object)((character is Player) ? character : null); if (val != null) { KeyboardShortcut chestConfirmHotkey = BlueprintConfig.ChestConfirmHotkey; if (((KeyboardShortcut)(ref chestConfirmHotkey)).IsDown()) { _lastConfirmInputFrame = Time.frameCount; __result = component.TryConfirm(val); return false; } if (BlueprintConfig.AzuCraftyBoxesPullOnOpen) { component.TryPullAvailableMaterials(val, "open", message: true); } component.Touch(); return true; } } return true; } } [HarmonyPatch(typeof(Player), "Update")] private static class PlayerUpdatePatch { private static void Postfix(Player __instance) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) if (Time.frameCount == _lastConfirmInputFrame || (Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || !((Character)__instance).TakeInput() || ((Character)__instance).IsDead()) { return; } KeyboardShortcut chestConfirmHotkey = BlueprintConfig.ChestConfirmHotkey; if (!((KeyboardShortcut)(ref chestConfirmHotkey)).IsDown()) { return; } GameObject hoverObject = ((Humanoid)__instance).GetHoverObject(); if (!((Object)(object)hoverObject == (Object)null)) { ZoneBlueprintPlanAnchor componentInParent = hoverObject.GetComponentInParent(); if (!((Object)(object)componentInParent == (Object)null)) { _lastConfirmInputFrame = Time.frameCount; componentInParent.TryConfirm(__instance); } } } } [HarmonyPatch(typeof(InventoryGrid), "UpdateGui")] private static class InventoryGridUpdateGuiPatch { private static void Postfix(InventoryGrid __instance) { ZoneBlueprintChestInventoryScroll.TryKeepContainerGridAtTop(__instance); InventoryGui instance = InventoryGui.instance; if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance.m_containerGrid != (Object)(object)__instance) && TryGetAnchor(instance.m_currentContainer, out ZoneBlueprintPlanAnchor anchor)) { anchor.DrawRequirementOverlay(__instance); } } } [HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")] private static class InventoryGuiOnSelectedItemPatch { private static bool Prefix(InventoryGui __instance, InventoryGrid grid, ItemData item, Vector2i pos, Modifier mod) { //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Invalid comparison between Unknown and I4 if ((Object)(object)__instance == (Object)null || (Object)(object)grid == (Object)null || !TryGetAnchor(__instance.m_currentContainer, out ZoneBlueprintPlanAnchor anchor)) { return true; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsTeleporting()) { return true; } Inventory inventory = __instance.m_currentContainer.GetInventory(); bool flag = grid.GetInventory() == inventory; if (Object.op_Implicit((Object)(object)__instance.m_dragGo)) { if (!flag || __instance.m_dragInventory == inventory) { return true; } if (__instance.m_dragItem != null && !__instance.m_dragItem.m_shared.m_questItem) { anchor.TryAcceptMaterialFromInventory(__instance.m_dragInventory, __instance.m_dragItem, __instance.m_dragAmount, message: true); } __instance.SetupDragItem((ItemData)null, (Inventory)null, 1); __instance.UpdateCraftingPanel(false); return false; } if (item == null) { return !flag; } if ((int)mod == 2 && !flag && !item.m_shared.m_questItem) { anchor.TryAcceptMaterialFromInventory(grid.GetInventory(), item, item.m_stack, message: true); __instance.UpdateCraftingPanel(false); return false; } return true; } } [HarmonyPatch(typeof(InventoryGui), "OnStackAll")] private static class InventoryGuiOnStackAllPatch { private static bool Prefix(InventoryGui __instance) { if ((Object)(object)__instance == (Object)null || !TryGetAnchor(__instance.m_currentContainer, out ZoneBlueprintPlanAnchor anchor) || (Object)(object)Player.m_localPlayer == (Object)null) { return true; } __instance.SetupDragItem((ItemData)null, (Inventory)null, 1); anchor.TryAcceptAllFromPlayer(Player.m_localPlayer); return false; } } [HarmonyPatch(typeof(Container), "StackAll")] private static class ContainerStackAllPatch { private static bool Prefix(Container __instance) { if (!TryGetAnchor(__instance, out ZoneBlueprintPlanAnchor anchor) || (Object)(object)Player.m_localPlayer == (Object)null) { return true; } anchor.TryAcceptAllFromPlayer(Player.m_localPlayer); return false; } } [HarmonyPatch(typeof(WearNTear), "Destroy")] private static class WearNTearDestroyPatch { private static void Prefix(WearNTear __instance) { ZoneBlueprintPlanAnchor component = ((Component)__instance).GetComponent(); if (!((Object)(object)component == (Object)null)) { component.ReleaseAzuCraftyBoxesContainer("PlanChest.WearNTear.Destroy prefix"); component.TryRefundDepositedMaterials("WearNTear.Destroy prefix"); } } } [HarmonyPatch(typeof(ZNetScene), "Destroy")] private static class ZNetSceneDestroyPatch { private static void Prefix(GameObject go) { if (Object.op_Implicit((Object)(object)go)) { ZoneBlueprintPlanAnchor component = go.GetComponent(); if (!((Object)(object)component == (Object)null)) { component.ReleaseAzuCraftyBoxesContainer("PlanChest.ZNetScene.Destroy prefix"); component.TryRefundDepositedMaterials("ZNetScene.Destroy prefix"); } } } } [CompilerGenerated] private sealed class <>c__DisplayClass45_0 { public HomesteadCommandResult result; internal void b__0(HomesteadCommandResult value) { result = value; } } [CompilerGenerated] private sealed class d__45 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public string name; public Player player; public Vector3 anchorPosition; public Quaternion anchorRotation; public Dictionary deposited; public ZoneBlueprintPlanAnchor <>4__this; private <>c__DisplayClass45_0 <>8__1; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__45(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>8__1 = null; <>1__state = -2; } private bool MoveNext() { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) int num = <>1__state; ZoneBlueprintPlanAnchor zoneBlueprintPlanAnchor = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass45_0(); <>8__1.result = HomesteadCommandResult.Fail(HomesteadLocalization.Text("hs_blueprint_confirmation_incomplete")); <>2__current = ZoneBlueprintCommands.FinalizeBlueprintPlanAsync(name, player, anchorPosition, anchorRotation, deposited, delegate(HomesteadCommandResult value) { <>8__1.result = value; }); <>1__state = 1; return true; case 1: <>1__state = -1; zoneBlueprintPlanAnchor._confirmInProgress = false; Message(player, <>8__1.result.Message, (MessageType)(<>8__1.result.Success ? 1 : 2)); if (!<>8__1.result.Success) { return false; } if ((Object)(object)zoneBlueprintPlanAnchor._nview == (Object)null || !zoneBlueprintPlanAnchor._nview.IsValid()) { return false; } zoneBlueprintPlanAnchor.PlayConfirmSfx(); zoneBlueprintPlanAnchor._nview.GetZDO().Set("hs_plan_confirmed", true); zoneBlueprintPlanAnchor.ClearDepositedMaterials(); zoneBlueprintPlanAnchor._nview.Destroy(); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__103 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public List refundMaterials; public Vector3 dropPosition; public string source; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__103(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_0039: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 1; return true; case 1: <>1__state = -1; DropRefundMaterials(refundMaterials, dropPosition, source); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private const string BlueprintNameKey = "hs_blueprint_name"; private const string AnchorXKey = "hs_anchor_x"; private const string AnchorYKey = "hs_anchor_y"; private const string AnchorZKey = "hs_anchor_z"; private const string AnchorRotXKey = "hs_anchor_rot_x"; private const string AnchorRotYKey = "hs_anchor_rot_y"; private const string AnchorRotZKey = "hs_anchor_rot_z"; private const string AnchorRotWKey = "hs_anchor_rot_w"; private const string ConfirmedKey = "hs_plan_confirmed"; private const string MaterialPrefix = "hs_plan_material_"; private const string RefundPayloadKey = "hs_plan_refund_payload"; private const int RefundPayloadVersion = 1; private const string ProgressSfxPrefab = "sfx_build_hammer_wood"; private const string ConfirmSfxPrefab = "vfx_StaminaUpgrade"; private const float CleanupCheckInterval = 30f; private const float FailedPlanReloadRetryInterval = 5f; private const float FailedPlanWarningInterval = 60f; private static int _lastConfirmInputFrame = -1; private ZNetView? _nview; private Container? _container; private WearNTear? _wearNTear; private ZoneBlueprintFile? _blueprint; private ZoneBlueprintCommands.BlueprintLoadPlan? _plan; private List _requirements = new List(); private List _stationRequirements = new List(); private string _loadedBlueprintName = ""; private readonly ZoneBlueprintGhostOwner _previewGhost = new ZoneBlueprintGhostOwner(); private readonly ZoneBlueprintGhostOwner _stationGhost = new ZoneBlueprintGhostOwner(); private bool _absorbing; private bool _refundStarted; private bool _confirmInProgress; private string _lastReadySignature = ""; private string _lastPreviewStyleSignature = ""; private string _failedBlueprintName = ""; private string _lastPlanLoadFailure = ""; private int _lastInventorySignatureHash; private bool _hasInventorySignature; private float _nextCleanupCheck; private float _nextFailedPlanReloadAt; private float _nextFailedPlanWarningAt; private void Awake() { _nview = ((Component)this).GetComponent(); _container = ((Component)this).GetComponent(); _wearNTear = ((Component)this).GetComponent(); if ((Object)(object)_wearNTear != (Object)null) { WearNTear? wearNTear = _wearNTear; wearNTear.m_onDestroyed = (Action)Delegate.Combine(wearNTear.m_onDestroyed, new Action(OnDestroyed)); } ZoneBlueprintChestZdoRegistry.Refresh(((Object)(object)_nview != (Object)null && _nview.IsValid()) ? _nview.GetZDO() : null); ((MonoBehaviour)this).InvokeRepeating("Tick", 0.5f, 0.5f); } private void OnDestroy() { ReleaseAzuCraftyBoxesContainer("PlanChest.OnDestroy"); TryRefundDepositedMaterials("Unity.OnDestroy"); ClearPreview(); } public void SetPlan(string blueprintName, Vector3 anchor, Quaternion anchorRotation) { //IL_0039: 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) //IL_005b: 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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_nview == (Object)null) && _nview.IsValid()) { ZDO zDO = _nview.GetZDO(); zDO.Set("hs_blueprint_name", blueprintName); zDO.Set("hs_anchor_x", anchor.x); zDO.Set("hs_anchor_y", anchor.y); zDO.Set("hs_anchor_z", anchor.z); zDO.Set("hs_anchor_rot_x", anchorRotation.x); zDO.Set("hs_anchor_rot_y", anchorRotation.y); zDO.Set("hs_anchor_rot_z", anchorRotation.z); zDO.Set("hs_anchor_rot_w", anchorRotation.w); zDO.Set("hs_plan_confirmed", false); ZoneBlueprintChestLifecycle.Initialize(zDO); ReloadPlan(force: true); RebuildPreview(); } } public string GetPlanHoverText() { //IL_00a6: Unknown result type (might be due to invalid IL or missing references) string blueprintName = GetBlueprintName(); if (!ReloadPlan()) { return HomesteadLocalization.MaybeLocalize(HomesteadLocalization.Text("hs_blueprint_chest_data_missing")); } int requiredTotal = GetRequiredTotal(); int depositedTotal = GetDepositedTotal(); bool flag = requiredTotal == 0 || depositedTotal >= requiredTotal; string text = HomesteadLocalization.Format("hs_blueprint_chest_header", blueprintName, depositedTotal, requiredTotal); text = text + HomesteadLocalization.Format("hs_hover_action", "$KEY_Use", HomesteadLocalization.Text("hs_blueprint_open_materials")) + "\n"; text = text + HomesteadLocalization.Format("hs_hover_action", FormatShortcut(BlueprintConfig.ChestConfirmHotkey), HomesteadLocalization.Text("hs_blueprint_confirm_build")) + "\n"; if (!flag) { text = text + "\n" + HomesteadLocalization.Text("hs_blueprint_missing") + "\n"; foreach (ZoneBlueprintRequirement item in GetMissingRequirements().Take(6)) { text += $" {item.Amount} {Localization.instance.Localize(item.DisplayName)}\n"; } } return Localization.instance.Localize(text); } public bool TryConfirm(Player player) { //IL_0103: 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) if ((Object)(object)_nview == (Object)null || !_nview.IsValid()) { return true; } _nview.ClaimOwnership(); Touch(); Tick(); long @long = _nview.GetZDO().GetLong(ZDOVars.s_creator, 0L); if (@long != 0L && player.GetPlayerID() != @long) { Message(player, HomesteadLocalization.Text("hs_blueprint_other_creator"), (MessageType)2); return true; } string blueprintName = GetBlueprintName(); if (!ReloadPlan()) { Message(player, HomesteadLocalization.Format("hs_blueprint_not_available", blueprintName), (MessageType)2); return true; } if (BlueprintConfig.AzuCraftyBoxesPullOnConfirm) { TryPullAvailableMaterials(player, "confirm", message: true); } Dictionary depositedMaterials = GetDepositedMaterials(); if (_confirmInProgress) { Message(player, HomesteadLocalization.Text("hs_blueprint_confirmation_in_progress"), (MessageType)2); return true; } if (!TryGetAnchorTransform(out var position, out var rotation)) { Message(player, HomesteadLocalization.Format("hs_blueprint_not_available", blueprintName), (MessageType)2); return true; } _confirmInProgress = true; ((MonoBehaviour)this).StartCoroutine(ConfirmAsync(player, blueprintName, position, rotation, depositedMaterials)); return true; } [IteratorStateMachine(typeof(d__45))] private IEnumerator ConfirmAsync(Player player, string name, Vector3 anchorPosition, Quaternion anchorRotation, Dictionary deposited) { //IL_001c: 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: 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) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__45(0) { <>4__this = this, player = player, name = name, anchorPosition = anchorPosition, anchorRotation = anchorRotation, deposited = deposited }; } private void Tick() { if (!((Object)(object)_nview == (Object)null) && _nview.IsValid() && ReloadPlan()) { if (_nview.IsOwner()) { AbsorbContainerMaterials(); TouchWhenInventoryChanged(); CheckAutoCleanup(); } UpdatePreview(); } } public void Touch() { ZoneBlueprintChestLifecycle.Touch(_nview); } private void TouchWhenInventoryChanged() { int inventorySignatureHash = GetInventorySignatureHash(); if (!_hasInventorySignature) { _lastInventorySignatureHash = inventorySignatureHash; _hasInventorySignature = true; } else if (inventorySignatureHash != _lastInventorySignatureHash) { _lastInventorySignatureHash = inventorySignatureHash; Touch(); } } private void CheckAutoCleanup() { if (Time.time < _nextCleanupCheck) { return; } _nextCleanupCheck = Time.time + 30f; ZNetView? nview = _nview; if (ZoneBlueprintChestLifecycle.IsExpired((nview != null) ? nview.GetZDO() : null, BlueprintConfig.ChestTimeoutMinutes) && !HasRetainedMaterials()) { ZNetView? nview2 = _nview; if (nview2 != null) { nview2.Destroy(); } } } private bool HasRetainedMaterials() { Container? container = _container; int? obj; if (container == null) { obj = null; } else { Inventory inventory = container.m_inventory; obj = ((inventory != null) ? new int?(inventory.NrOfItems()) : null); } int? num = obj; if (num.GetValueOrDefault() > 0) { return true; } if (GetDepositedTotal() > 0) { return true; } return ReadRefundMaterials().Any((RefundMaterial material) => material.Amount > 0); } private int GetInventorySignatureHash() { Inventory val = _container?.m_inventory; if (val == null) { return 0; } int num = 17; int num2 = 0; foreach (ItemData allItem in val.GetAllItems()) { string obj = allItem.m_shared?.m_name ?? ""; int hashCode = StringComparer.Ordinal.GetHashCode(obj); hashCode = (hashCode * 397) ^ allItem.m_stack; num += hashCode; num ^= (hashCode << 7) | (hashCode >>> 25); num2++; } return (num * 397) ^ num2; } private bool ReloadPlan(bool force = false) { //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010b: 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_0097: Unknown result type (might be due to invalid IL or missing references) string blueprintName = GetBlueprintName(); if (string.IsNullOrWhiteSpace(blueprintName)) { return false; } if (!force && _plan != null && string.Equals(_loadedBlueprintName, blueprintName, StringComparison.OrdinalIgnoreCase)) { return true; } if (ShouldSkipFailedPlanReload(blueprintName, force)) { return false; } if (!TryGetAnchorTransform(out var position, out var rotation)) { _blueprint = null; _plan = null; _requirements = new List(); _stationRequirements = new List(); _loadedBlueprintName = ""; _lastReadySignature = ""; ClearPreview(); return false; } ZoneBlueprintFile blueprint; try { _blueprint = ZoneBlueprintCommands.LoadBlueprintForPlan(blueprintName); _plan = ZoneBlueprintCommands.CreateLoadPlanForBlueprint(blueprintName, position, rotation); _requirements = ZoneBlueprintCommands.CollectRequirements(_plan); _stationRequirements = ZoneBlueprintCommands.CollectCraftingStations(_plan); _loadedBlueprintName = blueprintName; _lastReadySignature = ""; ClearPlanLoadFailure(); return true; } catch (Exception ex2) when (ZoneBlueprintPlanRpc.TryGetCachedPreview(blueprintName, out blueprint)) { try { _blueprint = blueprint; _plan = ZoneBlueprintCommands.CreateLoadPlanForBlueprint(blueprint, position, rotation); _requirements = ZoneBlueprintCommands.CollectRequirements(_plan); _stationRequirements = ZoneBlueprintCommands.CollectCraftingStations(_plan); _loadedBlueprintName = blueprintName; _lastReadySignature = ""; ClearPlanLoadFailure(); return true; } catch (Exception ex) { RecordPlanLoadFailure(blueprintName, "Failed to load Homestead server blueprint preview '" + blueprintName + "': " + ex.Message + " (local: " + ex2.Message + ")", logWarning: true); } _blueprint = null; _plan = null; _requirements = new List(); _stationRequirements = new List(); _loadedBlueprintName = ""; _lastReadySignature = ""; ClearPreview(); return false; } catch (Exception ex3) { ZoneBlueprintPlanRpc.RequestPreview(blueprintName); RecordPlanLoadFailure(blueprintName, "Failed to load Homestead blueprint plan '" + blueprintName + "': " + ex3.Message, !ZoneBlueprintPlanRpc.IsPreviewPending(blueprintName)); _blueprint = null; _plan = null; _requirements = new List(); _stationRequirements = new List(); _loadedBlueprintName = ""; _lastReadySignature = ""; ClearPreview(); return false; } } private bool ShouldSkipFailedPlanReload(string name, bool force) { if (force || _plan != null || !string.Equals(_failedBlueprintName, name, StringComparison.OrdinalIgnoreCase)) { return false; } return Time.realtimeSinceStartup < _nextFailedPlanReloadAt; } private void RecordPlanLoadFailure(string name, string message, bool logWarning) { float realtimeSinceStartup = Time.realtimeSinceStartup; bool flag = !string.Equals(_lastPlanLoadFailure, message, StringComparison.Ordinal); _failedBlueprintName = name; _lastPlanLoadFailure = message; _nextFailedPlanReloadAt = realtimeSinceStartup + 5f; if (logWarning && (flag || !(realtimeSinceStartup < _nextFailedPlanWarningAt))) { HomesteadPlugin.HomesteadLogger.LogWarning((object)message); _nextFailedPlanWarningAt = realtimeSinceStartup + 60f; } } private void ClearPlanLoadFailure() { _failedBlueprintName = ""; _lastPlanLoadFailure = ""; _nextFailedPlanReloadAt = 0f; _nextFailedPlanWarningAt = 0f; } private void AbsorbContainerMaterials() { //IL_005f: Unknown result type (might be due to invalid IL or missing references) if (_container?.m_inventory != null && !_absorbing && _container.m_inventory.GetAllItems().ToList().Count != 0) { string readyBefore = CaptureReadySignature(); _absorbing = true; ZoneMaterialEscrow.AbsorbResult absorbResult; try { absorbResult = CreateMaterialSession().AbsorbUnexpectedInventoryItems(_container.m_inventory, ((Component)this).transform.position, preferInventory: false); } finally { _absorbing = false; } if (absorbResult.Changed) { _container.Save(); _lastReadySignature = ""; Touch(); PlayProgressSfxIfReadyAdvanced(readyBefore, absorbResult.Accepted); } } } public bool TryAcceptMaterialFromInventory(Inventory sourceInventory, ItemData item, int requestedAmount, bool message) { string readyBefore = CaptureReadySignature(); int num = AcceptMaterialFromInventory(sourceInventory, item, requestedAmount); if (num > 0) { Container? container = _container; if (container != null) { container.Save(); } _lastReadySignature = ""; Touch(); PlayProgressSfxIfReadyAdvanced(readyBefore, num); if (message && (Object)(object)Player.m_localPlayer != (Object)null && num < requestedAmount) { ((Character)Player.m_localPlayer).Message((MessageType)2, HomesteadLocalization.Format("hs_blueprint_accepted_excess_inventory", num), 0, (Sprite)null); } return true; } if (message && (Object)(object)Player.m_localPlayer != (Object)null) { ((Character)Player.m_localPlayer).Message((MessageType)2, HomesteadLocalization.Text("hs_blueprint_material_not_needed"), 0, (Sprite)null); } return false; } public bool TryAcceptAllFromPlayer(Player player) { Player player2 = player; if ((Object)(object)player2 == (Object)null) { return false; } Inventory inventory = ((Humanoid)player2).GetInventory(); string readyBefore = CaptureReadySignature(); int num = 0; num += CreateMaterialSession().AcceptAllNeeded(inventory, (ItemData item) => item.m_shared.m_questItem || ((Humanoid)player2).IsItemEquiped(item)); if (num > 0) { Container? container = _container; if (container != null) { container.Save(); } _lastReadySignature = ""; Touch(); PlayProgressSfxIfReadyAdvanced(readyBefore, num); ((Character)player2).Message((MessageType)2, HomesteadLocalization.Format("hs_blueprint_accepted_materials", num), 0, (Sprite)null); return true; } ((Character)player2).Message((MessageType)2, HomesteadLocalization.Text("hs_blueprint_no_matching_materials"), 0, (Sprite)null); return false; } public int TryPullAvailableMaterials(Player player, string trigger, bool message) { if ((Object)(object)player == (Object)null || (Object)(object)_nview == (Object)null || !_nview.IsValid() || !ReloadPlan()) { return 0; } string readyBefore = CaptureReadySignature(); int num = AcceptAllFromPlayerInventory(player); int num2 = 0; if ((trigger == "confirm" && BlueprintConfig.AzuCraftyBoxesPullOnConfirm) || (trigger == "open" && BlueprintConfig.AzuCraftyBoxesPullOnOpen)) { num2 = TryPullFromAzuCraftyBoxes(player, trigger, message: false, playProgressSfx: false); } int num3 = num + num2; if (num3 > 0) { Container? container = _container; if (container != null) { container.Save(); } _lastReadySignature = ""; Touch(); PlayProgressSfxIfReadyAdvanced(readyBefore, num3); if (message) { ((Character)player).Message((MessageType)1, HomesteadLocalization.Format("hs_blueprint_pulled_materials", num3, num, num2), 0, (Sprite)null); } } return num3; } public int TryPullFromAzuCraftyBoxes(Player player, string trigger, bool message, bool playProgressSfx = true) { if ((Object)(object)_nview == (Object)null || !_nview.IsValid() || !ReloadPlan()) { return 0; } ZoneMaterialEscrow.Session session = CreateMaterialSession(); List missingRequirements = session.GetMissingRequirements(); if (missingRequirements.Count == 0) { return 0; } string readyBefore = (playProgressSfx ? CaptureReadySignature() : ""); int num = AzuCraftyBoxesCompat.PullMissingMaterials((Component)(object)this, missingRequirements, delegate(ZoneBlueprintRequirement requirement, int amount) { session.AcceptPulled(requirement, amount); }); if (num <= 0) { return 0; } Container? container = _container; if (container != null) { container.Save(); } _lastReadySignature = ""; Touch(); if (playProgressSfx) { PlayProgressSfxIfReadyAdvanced(readyBefore, num); } if (message) { ((Character)player).Message((MessageType)1, HomesteadLocalization.Format("hs_blueprint_pulled_from_containers", num), 0, (Sprite)null); } return num; } private int AcceptAllFromPlayerInventory(Player player) { Player player2 = player; Inventory inventory = ((Humanoid)player2).GetInventory(); return CreateMaterialSession().AcceptAllNeeded(inventory, (ItemData item) => item.m_shared.m_questItem || ((Humanoid)player2).IsItemEquiped(item)); } private int AcceptMaterialFromInventory(Inventory sourceInventory, ItemData item, int requestedAmount) { if ((Object)(object)_nview == (Object)null || !_nview.IsValid() || sourceInventory == null || item == null || requestedAmount <= 0) { return 0; } return CreateMaterialSession().AcceptNeededOnly(sourceInventory, item, requestedAmount); } private void AcceptMaterialAmount(ZoneBlueprintRequirement requirement, int amount) { if (amount > 0) { SetDeposited(requirement.ItemName, GetDeposited(requirement.ItemName) + amount); AddRefundMaterial(requirement, amount); } } private void PlayConfirmSfx() { PlayLocalEffect("vfx_StaminaUpgrade", "confirm"); } private void PlayProgressSfxIfReadyAdvanced(string readyBefore, int acceptedAmount) { if (acceptedAmount > 0) { string b = CaptureReadySignature(); if (!string.Equals(readyBefore, b, StringComparison.Ordinal)) { PlayLocalEffect("sfx_build_hammer_wood", "progress"); } } } private string CaptureReadySignature() { if (_plan == null && !ReloadPlan()) { return ""; } GetReadyEntryIndices(out string signature); return signature; } private void PlayLocalEffect(string prefabName, string label) { //IL_0025: 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) if (!((Object)(object)Player.m_localPlayer == (Object)null)) { GameObject val = FindPrefab(prefabName); if (Object.op_Implicit((Object)(object)val)) { Object.Instantiate(val, ((Component)this).transform.position, Quaternion.identity); } } } private static void GiveOrDropItem(ItemData prototype, int amount, Vector3 dropPosition, bool preferInventory, GameObject? dropPrefab = null) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) ZoneMaterialEscrow.GiveOrDropItem(prototype, amount, dropPosition, preferInventory, dropPrefab); } private void UpdatePreview() { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: 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_0064: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.m_localPlayer == (Object)null || _blueprint == null || _plan == null) { return; } RefreshPendingMaterialStyle(); if (!TryGetAnchorTransform(out var position, out var rotation)) { ClearPreview(); return; } string signature; HashSet readyEntryIndices = GetReadyEntryIndices(out signature); if (_previewGhost.HasRoot && string.Equals(signature, _lastReadySignature, StringComparison.Ordinal)) { _previewGhost.SetTransform(position, rotation); } else { RebuildPreview(readyEntryIndices, signature, position, rotation); } } private void RebuildPreview(HashSet? readyEntries = null, string? readySignature = null, Vector3? anchorPosition = null, Quaternion? anchorRotation = null) { //IL_0020: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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_0064: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.m_localPlayer == (Object)null || _blueprint == null || _plan == null) { return; } Vector3 position = default(Vector3); Quaternion rotation = default(Quaternion); if ((!anchorPosition.HasValue || !anchorRotation.HasValue) && !TryGetAnchorTransform(out position, out rotation)) { ClearPreview(); return; } Vector3 valueOrDefault = anchorPosition.GetValueOrDefault(position); Quaternion valueOrDefault2 = anchorRotation.GetValueOrDefault(rotation); if (readyEntries == null) { readyEntries = GetReadyEntryIndices(out readySignature); } if (readySignature == null) { readySignature = ""; } ClearPreview(); GameObject val = _previewGhost.CreateBlueprint(_blueprint, "HomesteadPlanPreview_" + GetBlueprintName(), valueOrDefault, valueOrDefault2); for (int i = 0; i < val.transform.childCount; i++) { Transform child = val.transform.GetChild(i); if (!readyEntries.Contains(i)) { ApplyPendingMaterial(((Component)child).gameObject); } } RebuildStationPreview(); _lastReadySignature = readySignature; } private void ClearPreview() { _previewGhost.Destroy(); _stationGhost.Destroy(); } private void RebuildStationPreview() { //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_0033: 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_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: 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) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: 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_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) _stationGhost.Destroy(); if (_blueprint == null || _stationRequirements.Count == 0) { return; } Vector3 position = ((Component)this).transform.position; Quaternion rotation = ((Component)this).transform.rotation; GameObject val = _stationGhost.CreateEmpty("HomesteadPlanStationPreview_" + GetBlueprintName()); float num = 2.75f; float num2 = 360f / (float)Mathf.Max(1, _stationRequirements.Count); for (int i = 0; i < _stationRequirements.Count; i++) { ZoneBlueprintCraftingStationRequirement zoneBlueprintCraftingStationRequirement = _stationRequirements[i]; GameObject val2 = FindPrefab(zoneBlueprintCraftingStationRequirement.PrefabName); if (Object.op_Implicit((Object)(object)val2)) { Vector3 val3 = Quaternion.Euler(0f, num2 * (float)i, 0f) * new Vector3(0f, 0f, 0f - num); Vector3 val4 = position + rotation * val3; val4.y = SampleGroundY(val4.x, val4.z, position.y); GameObject val5 = ZoneBlueprintVisuals.CreatePrefabVisualRoot(val2, "HomesteadStationGhost_" + zoneBlueprintCraftingStationRequirement.PrefabName); val5.transform.SetParent(val.transform, true); val5.transform.position = val4; val5.transform.rotation = rotation * Quaternion.Euler(0f, 180f + num2 * (float)i, 0f); _stationGhost.ApplyMaterial(val5, BlueprintConfig.PreviewGhostColor); } } } private static GameObject? FindPrefab(string prefabName) { if (string.IsNullOrWhiteSpace(prefabName)) { return null; } ZNetScene instance = ZNetScene.instance; object obj = ((instance != null) ? instance.GetPrefab(prefabName) : null); if (obj == null) { obj = PrefabManager.Instance.GetPrefab(prefabName); if (obj == null) { ObjectDB instance2 = ObjectDB.instance; if (instance2 == null) { return null; } obj = instance2.GetItemPrefab(prefabName); } } return (GameObject?)obj; } private static float SampleGroundY(float x, float z, float fallbackY) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZoneSystem.instance == (Object)null) { return fallbackY; } Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(x, fallbackY, z); Vector3 val2 = default(Vector3); Biome val3 = default(Biome); BiomeArea val4 = default(BiomeArea); Heightmap val5 = default(Heightmap); ZoneSystem.instance.GetGroundData(ref val, ref val2, ref val3, ref val4, ref val5); return val.y; } private void ApplyPendingMaterial(GameObject root) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) _previewGhost.ApplyMaterial(root, BlueprintConfig.PreviewGhostColor); } private bool RefreshPendingMaterialStyle() { //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_0006: 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_0036: Unknown result type (might be due to invalid IL or missing references) Color previewGhostColor = BlueprintConfig.PreviewGhostColor; string previewStyleSignature = GetPreviewStyleSignature(previewGhostColor); bool result = !string.Equals(previewStyleSignature, _lastPreviewStyleSignature, StringComparison.Ordinal); _lastPreviewStyleSignature = previewStyleSignature; _previewGhost.UpdateMaterialColor(previewGhostColor); _stationGhost.UpdateMaterialColor(previewGhostColor); return result; } private static string GetPreviewStyleSignature(Color color) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return ColorUtility.ToHtmlStringRGBA(color); } private HashSet GetReadyEntryIndices(out string signature) { HashSet hashSet = new HashSet(); if (_plan == null) { signature = ""; return hashSet; } Dictionary budget = GetDepositedMaterials(); if (!TryGetAnchorTransform(out var anchor, out var _)) { signature = ""; return hashSet; } foreach (var item4 in (from item in _plan.Entries.Select((ZoneBlueprintCommands.BlueprintLoadEntry entry, int index) => (entry, index)) orderby item.entry.Position.y select item).ThenBy<(ZoneBlueprintCommands.BlueprintLoadEntry, int), float>(delegate((ZoneBlueprintCommands.BlueprintLoadEntry entry, int index) item) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: 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_0024: 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) Vector3 val = item.entry.Position - anchor; return val.x * val.x + val.z * val.z; }).ThenBy<(ZoneBlueprintCommands.BlueprintLoadEntry, int), int>(((ZoneBlueprintCommands.BlueprintLoadEntry entry, int index) item) => item.index)) { ZoneBlueprintCommands.BlueprintLoadEntry item2 = item4.Item1; int item3 = item4.Item2; Dictionary entryRequirements = GetEntryRequirements(item2); if (entryRequirements.Any((KeyValuePair pair) => !budget.TryGetValue(pair.Key, out var value) || value < pair.Value)) { continue; } foreach (KeyValuePair item5 in entryRequirements) { budget[item5.Key] -= item5.Value; } hashSet.Add(item3); } signature = string.Join(",", hashSet.OrderBy((int index) => index)); return hashSet; } private static Dictionary GetEntryRequirements(ZoneBlueprintCommands.BlueprintLoadEntry entry) { Dictionary dictionary = new Dictionary(); Piece component = entry.Prefab.GetComponent(); if ((Object)(object)component == (Object)null) { return dictionary; } Requirement[] resources = component.m_resources; foreach (Requirement val in resources) { if (Object.op_Implicit((Object)(object)val.m_resItem) && val.m_amount > 0) { string name = val.m_resItem.m_itemData.m_shared.m_name; dictionary.TryGetValue(name, out var value); dictionary[name] = value + val.GetAmount(0); } } return dictionary; } private IEnumerable GetMissingRequirements() { return CreateMaterialSession().GetMissingRequirements(); } public List GetMissingRequirementList() { return GetMissingRequirements().ToList(); } public bool IsComplete() { return GetDepositedTotal() >= GetRequiredTotal(); } private int GetRequiredTotal() { return _requirements.Sum((ZoneBlueprintRequirement requirement) => requirement.Amount); } private int GetDepositedTotal() { return _requirements.Sum((ZoneBlueprintRequirement requirement) => Mathf.Min(requirement.Amount, GetDeposited(requirement.ItemName))); } private Dictionary GetDepositedMaterials() { Dictionary dictionary = new Dictionary(); foreach (ZoneBlueprintRequirement requirement in _requirements) { dictionary[requirement.ItemName] = GetDeposited(requirement.ItemName); } return dictionary; } private int GetDeposited(string itemName) { ZNetView? nview = _nview; if (((nview != null) ? nview.GetZDO() : null) == null) { return 0; } return _nview.GetZDO().GetInt("hs_plan_material_" + itemName, 0); } private ZoneMaterialEscrow.Session CreateMaterialSession() { return new ZoneMaterialEscrow.Session(_requirements, GetDeposited, AcceptMaterialAmount); } private void SetDeposited(string itemName, int amount) { ZNetView? nview = _nview; if (nview != null) { ZDO zDO = nview.GetZDO(); if (zDO != null) { zDO.Set("hs_plan_material_" + itemName, Mathf.Max(0, amount)); } } } private void ClearDepositedMaterials() { foreach (ZoneBlueprintRequirement requirement in _requirements) { SetDeposited(requirement.ItemName, 0); } ClearRefundMaterials(); } private void AddRefundMaterial(ZoneBlueprintRequirement requirement, int amount) { ZoneBlueprintRequirement requirement2 = requirement; if (amount > 0) { ZNetView? nview = _nview; if (((nview != null) ? nview.GetZDO() : null) != null) { List list = ReadRefundMaterials(); RefundMaterial refundMaterial = list.FirstOrDefault((RefundMaterial item) => item.ItemName == requirement2.ItemName); if (refundMaterial == null) { refundMaterial = new RefundMaterial { ItemName = requirement2.ItemName, PrefabName = requirement2.PrefabName }; list.Add(refundMaterial); } if (string.IsNullOrWhiteSpace(refundMaterial.PrefabName)) { refundMaterial.PrefabName = requirement2.PrefabName; } refundMaterial.Amount += amount; WriteRefundMaterials(list); LogRefundInfo($"Recorded refund material: {requirement2.ItemName} prefab={refundMaterial.PrefabName} added={amount} total={refundMaterial.Amount}."); return; } } string itemName = requirement2.ItemName; object arg = amount; ZNetView? nview2 = _nview; LogRefundDebug($"Skipped refund ledger add for '{itemName}'. amount={arg}, zdo={((nview2 != null) ? nview2.GetZDO() : null) != null}."); } private List ReadRefundMaterials() { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown ZNetView? nview = _nview; ZDO val = ((nview != null) ? nview.GetZDO() : null); if (val == null) { LogRefundDebug("Read refund ledger skipped: no ZDO."); return new List(); } string @string = val.GetString("hs_plan_refund_payload", ""); if (string.IsNullOrWhiteSpace(@string)) { LogRefundDebug("Read refund ledger: empty payload."); return new List(); } try { ZPackage val2 = new ZPackage(@string); int num = val2.ReadInt(); if (num != 1) { LogRefundInfo($"Read refund ledger: unsupported version {num}."); return new List(); } int num2 = val2.ReadInt(); List list = new List(num2); for (int i = 0; i < num2; i++) { list.Add(new RefundMaterial { ItemName = val2.ReadString(), PrefabName = val2.ReadString(), Amount = val2.ReadInt() }); } LogRefundInfo($"Read refund ledger: {list.Count} material entries, total={list.Sum((RefundMaterial item) => item.Amount)}."); return list; } catch (Exception ex) { LogRefundInfo("Failed to read refund payload: " + ex.Message); return new List(); } } private void WriteRefundMaterials(IEnumerable materials) { //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown ZNetView? nview = _nview; ZDO val = ((nview != null) ? nview.GetZDO() : null); if (val == null) { LogRefundDebug("Write refund ledger skipped: no ZDO."); return; } List list = materials.Where((RefundMaterial item) => item.Amount > 0 && !string.IsNullOrWhiteSpace(item.ItemName)).OrderBy((RefundMaterial item) => item.ItemName, StringComparer.Ordinal).ToList(); if (list.Count == 0) { val.Set("hs_plan_refund_payload", ""); LogRefundDebug("Cleared refund ledger payload."); return; } ZPackage val2 = new ZPackage(); val2.Write(1); val2.Write(list.Count); foreach (RefundMaterial item in list) { val2.Write(item.ItemName); val2.Write(item.PrefabName); val2.Write(item.Amount); } val.Set("hs_plan_refund_payload", val2.GetBase64()); LogRefundDebug($"Wrote refund ledger: {list.Count} entries, total={list.Sum((RefundMaterial item) => item.Amount)}."); } private void ClearRefundMaterials() { ZNetView? nview = _nview; if (nview != null) { ZDO zDO = nview.GetZDO(); if (zDO != null) { zDO.Set("hs_plan_refund_payload", ""); } } LogRefundDebug("Refund ledger cleared."); } private string GetBlueprintName() { ZNetView? nview = _nview; if (((nview != null) ? nview.GetZDO() : null) == null) { return ""; } return _nview.GetZDO().GetString("hs_blueprint_name", ""); } private bool TryGetAnchorTransform(out Vector3 position, out Quaternion rotation) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) position = default(Vector3); rotation = default(Quaternion); ZNetView? nview = _nview; if (((nview != null) ? nview.GetZDO() : null) == null) { return false; } ZDO zDO = _nview.GetZDO(); position = new Vector3(ReadRequiredFloat(zDO, "hs_anchor_x"), ReadRequiredFloat(zDO, "hs_anchor_y"), ReadRequiredFloat(zDO, "hs_anchor_z")); rotation = new Quaternion(ReadRequiredFloat(zDO, "hs_anchor_rot_x"), ReadRequiredFloat(zDO, "hs_anchor_rot_y"), ReadRequiredFloat(zDO, "hs_anchor_rot_z"), ReadRequiredFloat(zDO, "hs_anchor_rot_w")); if (IsFinite(position.x) && IsFinite(position.y) && IsFinite(position.z) && IsFinite(rotation.x) && IsFinite(rotation.y) && IsFinite(rotation.z)) { return IsFinite(rotation.w); } return false; } private static float ReadRequiredFloat(ZDO zdo, string key) { return zdo.GetFloat(key, float.NaN); } private static bool IsFinite(float value) { if (!float.IsNaN(value)) { return !float.IsInfinity(value); } return false; } private void OnDestroyed() { ReleaseAzuCraftyBoxesContainer("PlanChest.WearNTear.m_onDestroyed"); TryRefundDepositedMaterials("WearNTear.m_onDestroyed"); } private void ReleaseAzuCraftyBoxesContainer(string source) { AzuCraftyBoxesCompat.RemoveContainer((Container?)(((Object)(object)_container != (Object)null && Object.op_Implicit((Object)(object)_container)) ? ((object)_container) : ((object)((Component)this).GetComponent())), source); } private void TryRefundDepositedMaterials(string source) { //IL_00f7: Unknown result type (might be due to invalid IL or missing references) if (_refundStarted || (Object)(object)_nview == (Object)null) { LogRefundDebug($"{source}: skipped refund. started={_refundStarted}, nview={(Object)(object)_nview != (Object)null}."); return; } ZDO zDO = _nview.GetZDO(); if (zDO == null || zDO.GetBool("hs_plan_confirmed", false)) { LogRefundDebug(string.Format("{0}: skipped refund. zdo={1}, confirmed={2}.", source, zDO != null, (zDO != null) ? new bool?(zDO.GetBool("hs_plan_confirmed", false)) : null)); return; } if (_nview.IsValid() && !_nview.IsOwner()) { LogRefundDebug($"{source}: skipped refund because this peer is not owner. valid={_nview.IsValid()}."); return; } _refundStarted = true; LogRefundInfo(string.Format("{0}: refund starting at {1}. valid={2}, owner={3}, payloadBytes={4}.", source, ((Component)this).transform.position, _nview.IsValid(), _nview.IsOwner(), zDO.GetString("hs_plan_refund_payload", "").Length)); try { RefundDepositedMaterials(source); } catch (Exception arg) { HomesteadPlugin.HomesteadLogger.LogWarning((object)$"Blueprint refund failed during {source}: {arg}"); } } private void RefundDepositedMaterials(string source) { //IL_0045: 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) //IL_0091: Unknown result type (might be due to invalid IL or missing references) List list = ReadRefundMaterials(); if (list.All((RefundMaterial material) => material.Amount <= 0)) { LogRefundInfo("Refund skipped: no deposited materials found."); return; } ClearDepositedMaterials(); Vector3 position = ((Component)this).transform.position; LogRefundInfo($"Queueing refund materials from {source}: entries={list.Count}, total={list.Sum((RefundMaterial material) => material.Amount)}."); ScheduleRefundDrop(list, position, source); } private static void ScheduleRefundDrop(List refundMaterials, Vector3 dropPosition, string source) { //IL_0022: 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) if ((Object)(object)HomesteadPlugin.Instance != (Object)null) { ((MonoBehaviour)HomesteadPlugin.Instance).StartCoroutine(DropRefundMaterialsDeferred(refundMaterials, dropPosition, source)); } else { DropRefundMaterials(refundMaterials, dropPosition, source); } } [IteratorStateMachine(typeof(d__103))] private static IEnumerator DropRefundMaterialsDeferred(List refundMaterials, Vector3 dropPosition, string source) { //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) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__103(0) { refundMaterials = refundMaterials, dropPosition = dropPosition, source = source }; } private static void DropRefundMaterials(IEnumerable refundMaterials, Vector3 dropPosition, string source) { //IL_00cf: Unknown result type (might be due to invalid IL or missing references) LogRefundInfo("Dropping queued refund materials from " + source + "."); foreach (RefundMaterial refundMaterial in refundMaterials) { if (refundMaterial.Amount > 0) { GameObject val = FindPrefab(refundMaterial.PrefabName); ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent() : null); if ((Object)(object)val2 == (Object)null) { HomesteadPlugin.HomesteadLogger.LogWarning((object)("Failed to refund Homestead blueprint material '" + refundMaterial.ItemName + "': prefab '" + refundMaterial.PrefabName + "' was not found.")); } else { LogRefundInfo($"Dropping refund material '{refundMaterial.ItemName}' prefab={refundMaterial.PrefabName} amount={refundMaterial.Amount}."); GiveOrDropItem(val2.m_itemData, refundMaterial.Amount, dropPosition, preferInventory: false, val); } } } } private static void LogRefundInfo(string message) { } private static void LogRefundDebug(string message) { } public void DrawRequirementOverlay(InventoryGrid grid) { //IL_00a5: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)grid == (Object)null || !ReloadPlan()) { return; } List missingRequirementList = GetMissingRequirementList(); int num = 0; foreach (Element element in grid.m_elements) { if (num >= missingRequirementList.Count) { break; } if (!element.m_used) { ZoneBlueprintRequirement zoneBlueprintRequirement = missingRequirementList[num++]; Sprite requirementIcon = GetRequirementIcon(zoneBlueprintRequirement); element.m_used = true; ((Behaviour)element.m_icon).enabled = (Object)(object)requirementIcon != (Object)null; element.m_icon.sprite = requirementIcon; ((Graphic)element.m_icon).color = new Color(1f, 1f, 1f, 0.45f); ((Behaviour)element.m_amount).enabled = true; element.m_amount.text = zoneBlueprintRequirement.Amount.ToString(); ((Behaviour)element.m_quality).enabled = false; ((Behaviour)element.m_equiped).enabled = false; ((Behaviour)element.m_queued).enabled = false; ((Behaviour)element.m_noteleport).enabled = false; ((Behaviour)element.m_food).enabled = false; ((Component)element.m_durability).gameObject.SetActive(false); element.m_tooltip.m_topic = Localization.instance.Localize(zoneBlueprintRequirement.DisplayName); element.m_tooltip.m_text = HomesteadLocalization.Format("hs_blueprint_requirement_tooltip", zoneBlueprintRequirement.Amount); } } } private static Sprite? GetRequirementIcon(ZoneBlueprintRequirement requirement) { GameObject val = FindPrefab(requirement.PrefabName); ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent() : null); if (!((Object)(object)val2 != (Object)null)) { return null; } return val2.m_itemData.GetIcon(); } public static bool TryGetAnchor(Container? container, out ZoneBlueprintPlanAnchor anchor) { anchor = null; if (!Object.op_Implicit((Object)(object)container)) { return false; } anchor = ((Component)container).GetComponent(); if ((Object)(object)anchor != (Object)null) { return anchor.ReloadPlan(); } return false; } private static void Message(Player player, string message, MessageType type) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) HomesteadPlugin.HomesteadLogger.LogInfo((object)message); ((Character)player).Message(type, message, 0, (Sprite)null); } private static string FormatShortcut(KeyboardShortcut shortcut) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) string text = ConfigValueHelpers.FormatShortcut(shortcut); if (!string.Equals(text, "None", StringComparison.OrdinalIgnoreCase)) { return text; } return "Unbound"; } } internal static class ZoneBlueprintPlanChestPrefab { internal const string PrefabName = "piece_chest_wood_blueprint"; private const string BasePrefabName = "piece_chest_wood"; internal static readonly int PrefabHash = StringExtensionMethods.GetStableHashCode("piece_chest_wood_blueprint"); private static ManualLogSource? _logger; private static bool _initialized; private static bool _registered; public static void Initialize(ManualLogSource logger) { _logger = logger; if (!_initialized) { _initialized = true; PrefabManager.OnVanillaPrefabsAvailable += RegisterPrefab; RegisterPrefab(); } } public static HomesteadCommandResult PlacePlanChest(string blueprintName, Player player, Vector3 anchor, Quaternion anchorRotation, Vector3 chestPosition, Quaternion chestRotation) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) long playerID = player.GetPlayerID(); return PlacePlanChest(blueprintName, playerID, HomesteadPlayerIdentity.ResolveLocalPlatformId(playerID), anchor, anchorRotation, chestPosition, chestRotation, 0L); } public static HomesteadCommandResult PlacePlanChest(string blueprintName, long playerId, string ownerPlatformId, Vector3 anchor, Quaternion anchorRotation, Vector3 chestPosition, Quaternion chestRotation, long vfxExcludePeer = 0L) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003a: 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_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) RegisterPrefab(); if (!ZoneBlueprintChestLifecycle.CanPlaceChests(ownerPlatformId, 1, out string reason)) { return HomesteadCommandResult.Fail(reason); } GameObject prefab = GetPrefab(); if (!Object.op_Implicit((Object)(object)prefab)) { return HomesteadCommandResult.Fail(HomesteadLocalization.Text("hs_blueprint_chest_prefab_not_ready")); } GameObject val = null; try { val = Object.Instantiate(prefab, chestPosition, chestRotation); Piece component = val.GetComponent(); if ((Object)(object)component != (Object)null) { component.SetCreator(playerId); } ZNetView component2 = val.GetComponent(); if ((Object)(object)component2 != (Object)null && component2.IsValid()) { ZoneBlueprintChestLifecycle.SetOwnerPlatformId(component2.GetZDO(), ownerPlatformId); } (val.GetComponent() ?? val.AddComponent()).SetPlan(blueprintName, anchor, anchorRotation); ZoneChestPlacement.PlayPlaceEffect(val); ZoneChestPlacement.SafeOnPlaced(val, _logger, "Blueprint chest"); ZoneBlueprintChestVfx.BroadcastPlace("plan", ToTransformPayload(chestPosition, chestRotation), vfxExcludePeer); ZoneLimitCompat.RebuildCounts(); return HomesteadCommandResult.Ok(HomesteadLocalization.Format("hs_blueprint_chest_placed", blueprintName)); } catch (Exception ex) { ZoneChestPlacement.DestroySpawned(val); return HomesteadCommandResult.Fail(HomesteadLocalization.Format("hs_blueprint_chest_place_failed", ex.Message)); } } public static GameObject? CreatePreview() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown RegisterPrefab(); GameObject prefab = GetPrefab(); if (!Object.op_Implicit((Object)(object)prefab)) { return null; } GameObject val = new GameObject("HomesteadBlueprintChestPreview"); if (ZoneBlueprintVisuals.CopyVisuals(prefab.transform, val.transform) == 0) { Object.Destroy((Object)(object)val); return null; } return val; } private static GameObject? GetPrefab() { GameObject prefab = PrefabManager.Instance.GetPrefab("piece_chest_wood_blueprint"); if (prefab == null) { ZNetScene instance = ZNetScene.instance; if (instance == null) { return null; } prefab = instance.GetPrefab("piece_chest_wood_blueprint"); } return prefab; } internal static Sprite? GetIcon() { RegisterPrefab(); GameObject? prefab = GetPrefab(); if (prefab == null) { return null; } return prefab.GetComponent()?.m_icon; } public static bool PlayPlaceEffect(Vector3 position, Quaternion rotation) { //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) RegisterPrefab(); return ZoneChestPlacement.PlayPlaceEffect(GetPrefab(), position, rotation); } private static ZoneBlueprintStoreTransformPayload ToTransformPayload(Vector3 position, Quaternion rotation) { //IL_000f: 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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) ZoneBlueprintStoreTransformPayload zoneBlueprintStoreTransformPayload = new ZoneBlueprintStoreTransformPayload(); zoneBlueprintStoreTransformPayload.Pos = new float[3] { position.x, position.y, position.z }; zoneBlueprintStoreTransformPayload.Rot = new float[4] { rotation.x, rotation.y, rotation.z, rotation.w }; return zoneBlueprintStoreTransformPayload; } private static void RegisterPrefab() { if (_registered) { return; } if (Object.op_Implicit((Object)(object)PrefabManager.Instance.GetPrefab("piece_chest_wood_blueprint"))) { _registered = true; return; } if (!Object.op_Implicit((Object)(object)PrefabManager.Instance.GetPrefab("piece_chest_wood"))) { ZNetScene instance = ZNetScene.instance; if (!Object.op_Implicit((Object)(object)((instance != null) ? instance.GetPrefab("piece_chest_wood") : null))) { return; } } GameObject val = PrefabManager.Instance.CreateClonedPrefab("piece_chest_wood_blueprint", "piece_chest_wood"); if (Object.op_Implicit((Object)(object)val)) { ConfigurePrefab(val); PrefabManager.Instance.AddPrefab(val); PrefabManager.Instance.RegisterToZNetScene(val); _registered = true; ManualLogSource? logger = _logger; if (logger != null) { logger.LogInfo((object)"Registered Homestead blueprint chest prefab."); } } } private static void ConfigurePrefab(GameObject prefab) { //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_004b: Expected O, but got Unknown Container component = prefab.GetComponent(); if ((Object)(object)component != (Object)null) { component.m_name = HomesteadLocalization.Token("hs_blueprint_chest_name"); component.m_width = 8; component.m_height = BlueprintConfig.ChestRows; component.m_autoDestroyEmpty = false; component.m_privacy = (PrivacySetting)2; component.m_defaultItems = new DropTable(); } Piece component2 = prefab.GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.m_name = HomesteadLocalization.Token("hs_blueprint_chest_name"); component2.m_description = HomesteadLocalization.Token("hs_blueprint_chest_desc"); component2.m_resources = Array.Empty(); } if ((Object)(object)prefab.GetComponent() == (Object)null) { prefab.AddComponent(); } } } internal static class ZoneBlueprintPreviewBuilder { private readonly struct VisualDescriptor { public string Name { get; } public Mesh Mesh { get; } public Material[] Materials { get; } public bool Skinned { get; } public Vector3 LocalPosition { get; } public Quaternion LocalRotation { get; } public Vector3 LocalScale { get; } public VisualDescriptor(string name, Mesh mesh, Material[] materials, bool skinned, Vector3 localPosition, Quaternion localRotation, Vector3 localScale) { //IL_001e: 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_0026: 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_002e: 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) Name = name; Mesh = mesh; Materials = materials; Skinned = skinned; LocalPosition = localPosition; LocalRotation = localRotation; LocalScale = localScale; } } private static readonly Dictionary> VisualCache = new Dictionary>(StringComparer.OrdinalIgnoreCase); public static GameObject? CreateVisualPreview(GameObject prefab, Vector3 localPosition, Quaternion localRotation, Vector3 scale, int index, Transform parent) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) List visuals = GetVisuals(prefab); if (visuals.Count == 0) { return null; } GameObject val = new GameObject($"HomesteadBlueprintPreview_{index:D3}"); val.transform.SetParent(parent, false); val.transform.localPosition = localPosition; val.transform.localRotation = localRotation; val.transform.localScale = scale; foreach (VisualDescriptor item in visuals) { GameObject val2 = new GameObject(item.Name); val2.transform.SetParent(val.transform, false); val2.transform.localPosition = item.LocalPosition; val2.transform.localRotation = item.LocalRotation; val2.transform.localScale = item.LocalScale; if (item.Skinned) { SkinnedMeshRenderer obj = val2.AddComponent(); obj.sharedMesh = item.Mesh; ((Renderer)obj).sharedMaterials = item.Materials; ((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)obj).receiveShadows = false; } else { MeshFilter val3 = val2.AddComponent(); MeshRenderer obj2 = val2.AddComponent(); val3.sharedMesh = item.Mesh; ((Renderer)obj2).sharedMaterials = item.Materials; ((Renderer)obj2).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)obj2).receiveShadows = false; } } return val; } public static void ClearCache() { VisualCache.Clear(); } private static List GetVisuals(GameObject prefab) { string prefabName = Utils.GetPrefabName(prefab); if (VisualCache.TryGetValue(prefabName, out List value)) { return value; } List list = new List(); CollectVisuals(prefab.transform, prefab.transform, list); VisualCache[prefabName] = list; return list; } private static void CollectVisuals(Transform root, Transform source, List visuals) { //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Expected O, but got Unknown if (!((Component)source).gameObject.activeSelf) { return; } MeshFilter component = ((Component)source).GetComponent(); MeshRenderer component2 = ((Component)source).GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component.sharedMesh != (Object)null && (Object)(object)component2 != (Object)null && ((Renderer)component2).enabled) { visuals.Add(CreateDescriptor(root, source, component.sharedMesh, ((Renderer)component2).sharedMaterials, skinned: false)); } SkinnedMeshRenderer component3 = ((Component)source).GetComponent(); if ((Object)(object)component3 != (Object)null && (Object)(object)component3.sharedMesh != (Object)null && ((Renderer)component3).enabled) { visuals.Add(CreateDescriptor(root, source, component3.sharedMesh, ((Renderer)component3).sharedMaterials, skinned: true)); } foreach (Transform item in source) { Transform source2 = item; CollectVisuals(root, source2, visuals); } } private static VisualDescriptor CreateDescriptor(Transform root, Transform source, Mesh mesh, Material[] materials, bool skinned) { //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_000c: 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) Decompose(root.worldToLocalMatrix * source.localToWorldMatrix, out var position, out var rotation, out var scale); return new VisualDescriptor(((Object)source).name, mesh, materials, skinned, position, rotation, scale); } private static void Decompose(Matrix4x4 matrix, out Vector3 position, out Quaternion rotation, out Vector3 scale) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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) Vector3 val = Vector4.op_Implicit(((Matrix4x4)(ref matrix)).GetColumn(0)); Vector3 val2 = Vector4.op_Implicit(((Matrix4x4)(ref matrix)).GetColumn(1)); Vector3 val3 = Vector4.op_Implicit(((Matrix4x4)(ref matrix)).GetColumn(2)); position = Vector4.op_Implicit(((Matrix4x4)(ref matrix)).GetColumn(3)); scale = new Vector3(((Vector3)(ref val)).magnitude, ((Vector3)(ref val2)).magnitude, ((Vector3)(ref val3)).magnitude); rotation = ((((Vector3)(ref val3)).sqrMagnitude > 1E-06f && ((Vector3)(ref val2)).sqrMagnitude > 1E-06f) ? Quaternion.LookRotation(val3, val2) : Quaternion.identity); } } internal sealed class ZoneBlueprintSaveTool : MonoBehaviour { private sealed class SaveSelection { public Vector3 Anchor { get; } public Quaternion AnchorRotation { get; } public float Radius { get; } public List Zdos { get; } public SaveSelection(Vector3 anchor, Quaternion anchorRotation, float radius, List zdos) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //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) Anchor = anchor; AnchorRotation = anchorRotation; Radius = radius; Zdos = zdos; } } [CompilerGenerated] private sealed class <>c__DisplayClass73_0 { public Sprite icon; public bool renderFinished; internal void b__0(Sprite? renderedIcon) { icon = renderedIcon; renderFinished = true; } } [CompilerGenerated] private sealed class d__59 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public SaveSelection selection; public IReadOnlyList zdos; public ZoneBlueprintSaveTool <>4__this; public GameObject root; private Quaternion 5__2; private int 5__3; private IEnumerator <>7__wrap3; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__59(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <>7__wrap3 = null; <>1__state = -2; } private bool MoveNext() { //IL_002d: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: 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_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) bool result; try { int num = <>1__state; ZoneBlueprintSaveTool zoneBlueprintSaveTool = <>4__this; switch (num) { default: result = false; goto end_IL_0000; case 0: <>1__state = -1; 5__2 = Quaternion.Inverse(selection.AnchorRotation); 5__3 = 0; <>7__wrap3 = zdos.GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; break; } while (true) { if (<>7__wrap3.MoveNext()) { ZDO current = <>7__wrap3.Current; if (zoneBlueprintSaveTool._selection != selection || (Object)(object)zoneBlueprintSaveTool._selectionPreviewRoot != (Object)(object)root) { zoneBlueprintSaveTool._previewBuildCoroutine = null; result = false; <>m__Finally1(); break; } if (ZoneBlueprintCommands.TryReadSavableWearNTear(current, out GameObject prefab)) { Vector3 vec = current.GetVec3(ZDOVars.s_scaleHash, prefab.transform.localScale); Vector3 localPosition = 5__2 * (current.GetPosition() - selection.Anchor); Quaternion localRotation = 5__2 * current.GetRotation(); GameObject val = zoneBlueprintSaveTool.CreateVisualPreview(prefab, localPosition, localRotation, vec, 5__3, zoneBlueprintSaveTool._selectionPreviewRoot.transform); if ((Object)(object)val != (Object)null) { zoneBlueprintSaveTool._previewVisuals.Add(val); } 5__3++; if (5__3 % 64 == 0) { <>2__current = null; <>1__state = 1; result = true; break; } } continue; } <>m__Finally1(); <>7__wrap3 = null; zoneBlueprintSaveTool._previewBuildCoroutine = null; result = false; break; } end_IL_0000:; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>7__wrap3 != null) { <>7__wrap3.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__73 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public ZoneBlueprintSaveTool <>4__this; private <>c__DisplayClass73_0 <>8__1; private Stopwatch 5__2; private string 5__3; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__73(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>8__1 = null; 5__2 = null; 5__3 = null; <>1__state = -2; } private bool MoveNext() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Expected O, but got Unknown int num = <>1__state; ZoneBlueprintSaveTool zoneBlueprintSaveTool = <>4__this; ManualLogSource? logger2; switch (num) { default: return false; case 0: <>1__state = -1; goto IL_0234; case 1: <>1__state = -1; goto IL_0234; case 2: <>1__state = -1; goto IL_0234; case 3: <>1__state = -1; goto IL_0188; case 4: { <>1__state = -1; <>8__1 = null; 5__2 = null; 5__3 = null; goto IL_0234; } IL_0234: if (zoneBlueprintSaveTool._iconRenderQueue.Count > 0) { <>8__1 = new <>c__DisplayClass73_0(); if (ShouldDelayIconRenderForPlacement()) { <>2__current = (object)new WaitForSecondsRealtime(1f); <>1__state = 1; return true; } 5__2 = Stopwatch.StartNew(); 5__3 = zoneBlueprintSaveTool._iconRenderQueue.Dequeue(); zoneBlueprintSaveTool._queuedIconRenders.Remove(5__3); if (!zoneBlueprintSaveTool._queuedIconBlueprints.TryGetValue(5__3, out ZoneBlueprintFile value) && !ZoneBlueprintCommands.TryLoadBlueprint(5__3, out value)) { zoneBlueprintSaveTool._queuedIconBlueprints.Remove(5__3); <>2__current = null; <>1__state = 2; return true; } zoneBlueprintSaveTool._queuedIconBlueprints.Remove(5__3); <>8__1.icon = null; <>8__1.renderFinished = false; try { ZoneBlueprintVisuals.EnqueueRenderAndCacheIcon(5__3, value, delegate(Sprite? renderedIcon) { <>8__1.icon = renderedIcon; <>8__1.renderFinished = true; }); } catch (Exception ex) { ManualLogSource? logger = _logger; if (logger != null) { logger.LogWarning((object)("Failed to render Homestead blueprint icon '" + 5__3 + "': " + ex.Message)); } <>8__1.renderFinished = true; } goto IL_0188; } zoneBlueprintSaveTool._iconRenderCoroutine = null; return false; IL_0188: if (!<>8__1.renderFinished) { <>2__current = null; <>1__state = 3; return true; } ZoneBlueprintSaveToolMenu.ApplyBlueprintIcon(5__3, <>8__1.icon); 5__2.Stop(); logger2 = _logger; if (logger2 != null) { logger2.LogDebug((object)$"Homestead blueprint icon render completed for '{5__3}' in {5__2.Elapsed.TotalMilliseconds:0.0} ms; queued={zoneBlueprintSaveTool._iconRenderQueue.Count}."); } <>2__current = (object)new WaitForSecondsRealtime(1.25f); <>1__state = 4; return true; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private const float MinSideLength = 2f; private const float SizeStep = 2f; private const float PreviewLift = 4f; private const int PreviewBuildBatchSize = 64; private const int SaveNameMaxLength = 64; private const float TargetOverlayRefreshInterval = 0.3f; private const float IconRenderIntervalSeconds = 1.25f; private const float IconRenderPlacementDelaySeconds = 1f; private static ManualLogSource? _logger; private static ZoneBlueprintSaveTool? _instance; private static float? _lastAreaYaw; private readonly List _previewVisuals = new List(); private readonly List _nearbyTargetZdos = new List(); private readonly List _targetCandidateZdos = new List(); private readonly Queue _iconRenderQueue = new Queue(); private readonly HashSet _queuedIconRenders = new HashSet(StringComparer.OrdinalIgnoreCase); private readonly Dictionary _queuedIconBlueprints = new Dictionary(StringComparer.OrdinalIgnoreCase); private ZoneAreaToolController? _areaTool; private GameObject? _selectionPreviewRoot; private SaveSelection? _selection; private Coroutine? _iconRenderCoroutine; private Coroutine? _previewBuildCoroutine; private bool _active; private GameObject? _savePanel; private InputField? _saveNameInput; private Text? _saveCountText; private Text? _saveStatusText; private string _saveName = ""; private string _saveStatus = ""; private bool _focusSaveName; private bool _saveInputBlocked; private float _selectionPreviewYawOffset; public static bool HasSelection => _instance?._selection != null; public static bool IsActive { get { ZoneBlueprintSaveTool? instance = _instance; if (instance == null) { return false; } return (instance._areaTool?.Active).GetValueOrDefault(); } } private static float MaxSelectableSide => Mathf.Max(2f, AreaToolConfig.BlueprintSaveMaxSide); private ZoneAreaToolController AreaTool => _areaTool ?? (_areaTool = new ZoneAreaToolController((MonoBehaviour)(object)this, new ZoneAreaToolController.Options { MinSide = 2f, SizeStep = 2f, MaxSide = () => MaxSelectableSide, DefaultWidth = () => AreaToolConfig.BlueprintSaveDefaultWidth, DefaultDepth = () => AreaToolConfig.BlueprintSaveDefaultDepth, Color = () => AreaToolConfig.BlueprintSaveColor, RangeLineName = "HomesteadBlueprintRadius", TargetOverlayName = "HomesteadAreaSaveTarget", TargetOverlayRefreshInterval = 0.3f, GetSavedYaw = () => _lastAreaYaw, SetSavedYaw = delegate(float yaw) { _lastAreaYaw = yaw; }, IsLocked = () => _selection != null, GetEffectiveYaw = (float yaw) => (_selection != null) ? ZoneAreaSelection.NormalizeYaw(yaw + _selectionPreviewYawOffset) : yaw, OnLockedScroll = delegate(float scroll) { float num = ((scroll > 0f) ? PlacementControlConfig.RotationStep : (0f - PlacementControlConfig.RotationStep)); _selectionPreviewYawOffset = ZoneAreaSelection.NormalizeYaw(_selectionPreviewYawOffset + num); }, OnFrame = delegate { UpdateSelectionPreview(); UpdateSavePanel(); }, ShouldBlockToolInput = () => _selection != null && IsSaveNameInputFocused(), StatusTitle = () => (_selection != null) ? HomesteadLocalization.Text("hs_area_save_preview_name") : HomesteadLocalization.Text("hs_area_save_name"), FindCandidates = FindSaveBoundaryPreviewCandidates, OnClick = PickSelection })); public static void Initialize(ManualLogSource logger) { _logger = logger; ZoneBlueprintSaveToolMenu.Initialize(); EnsureInstance(); } public static void Activate(Player player) { EnsureInstance(); _instance?.ActivateInternal(player); } public static void Deactivate() { _instance?.DeactivateInternal(); } public static void ClearSelection() { _instance?.ClearSelectionInternal(); } public static void QueueMenuRefresh(string blueprintName) { EnsureInstance(); ZoneBlueprintSaveToolMenu.RequestHammerTableRefresh(blueprintName); } public static void QueueIconRender(string blueprintName, ZoneBlueprintFile? blueprint = null) { EnsureInstance(); _instance?.QueueIconRenderInternal(blueprintName, blueprint); } public static bool TryGetSelectedBlueprint(string name, Player player, out ZoneBlueprintFile blueprint, out string reason) { //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: 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_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) blueprint = null; reason = ""; if (_instance?._selection == null) { reason = HomesteadLocalization.Format("hs_blueprint_no_preview_selected", "Wheel", ZoneAreaToolShared.FormatScaleInput(), ZoneAreaToolShared.FormatDepthInput(), ZoneAreaToolShared.FormatWidthInput()); return false; } if (ZDOMan.instance == null) { reason = HomesteadLocalization.Text("hs_common_world_not_ready"); return false; } SaveSelection selection = _instance._selection; List list = new List(); foreach (ZDOID zdo in selection.Zdos) { ZDO zDO = ZDOMan.instance.GetZDO(zdo); if (zDO != null && zDO.IsValid()) { list.Add(zDO); } } if (list.Count == 0) { reason = HomesteadLocalization.Text("hs_blueprint_preview_invalid"); return false; } blueprint = ZoneBlueprintCommands.CaptureBlueprintFromZdos(name, player, selection.Anchor, selection.AnchorRotation, list, selection.Radius); return true; } private static void EnsureInstance() { //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_002a: Expected O, but got Unknown if (!((Object)(object)_instance != (Object)null) || !Object.op_Implicit((Object)(object)_instance)) { GameObject val = new GameObject("HomesteadBlueprintSaveTool"); Object.DontDestroyOnLoad((Object)val); _instance = val.AddComponent(); } } private void ActivateInternal(Player player) { _active = true; AreaTool.Activate(player); } private void DeactivateInternal() { _active = false; _areaTool?.Deactivate(); _saveStatus = ""; _focusSaveName = false; _selectionPreviewYawOffset = 0f; SetSaveUiInputBlocked(blocked: false); SetSavePanelVisible(visible: false); _selection = null; ClearPreviewLines(); } private void ClearSelectionInternal() { _selection = null; _saveStatus = ""; _focusSaveName = false; _selectionPreviewYawOffset = 0f; _areaTool?.ResetOffsets(); SetSaveUiInputBlocked(blocked: false); SetSavePanelVisible(visible: false); ClearPreviewLines(); ZoneAreaToolStatusHud.Hide(); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)1, HomesteadLocalization.Text("hs_blueprint_preview_cleared"), 0, (Sprite)null); } } private void Update() { if (!_active) { ZoneAreaToolController? areaTool = _areaTool; if (areaTool == null || !areaTool.Active) { return; } } if (!AreaTool.Tick()) { DeactivateInternal(); } } private void OnDestroy() { SetSaveUiInputBlocked(blocked: false); DestroySavePanel(); _areaTool?.Destroy(); _areaTool = null; ClearPreviewLines(); if ((Object)(object)_instance == (Object)(object)this) { _instance = null; } } private void PickSelection(Player player) { PickSelection(player, AreaTool.CurrentArea); } private void PickSelection(Player player, ZoneAreaSelection area) { //IL_0061: 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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) if (!AreaTool.HasAimPoint) { return; } BlueprintAreaSaveCreatorMode areaSaveCreatorMode = BlueprintConfig.AreaSaveCreatorMode; List list = ZoneBlueprintCommands.FindBlueprintWearNTearZdos(player, area, areaSaveCreatorMode); if (list.Count == 0) { _selection = null; ClearPreviewLines(); Message(player, HomesteadLocalization.Format("hs_blueprint_no_targets_in_area", BlueprintConfig.AreaSaveEligibleTargetLabel, AreaTool.FormattedSize)); return; } Quaternion rotation = area.Rotation; _selection = new SaveSelection(area.Center, rotation, area.HalfDiagonal, list.Select((ZDO zdo) => zdo.m_uid).ToList()); _selectionPreviewYawOffset = 0f; _saveName = GenerateDefaultBlueprintName(); _saveStatus = ""; _focusSaveName = false; EnsureSavePanel(); RefreshSavePanel(); SetSavePanelVisible(visible: true); ReleaseSaveNameFocus(); DrawSelectionPreview(list); } private void SaveSelectionFromUi() { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { HomesteadCommandResult homesteadCommandResult = ZoneBlueprintCommands.SaveSelectedBlueprint(_saveName, localPlayer); _saveStatus = (homesteadCommandResult.Success ? "Saved." : homesteadCommandResult.Message); Message(localPlayer, homesteadCommandResult.Message, (MessageType)(homesteadCommandResult.Success ? 1 : 2)); if (homesteadCommandResult.Success) { _selection = null; _selectionPreviewYawOffset = 0f; _focusSaveName = false; SetSaveUiInputBlocked(blocked: false); SetSavePanelVisible(visible: false); ClearPreviewLines(); } } } private IReadOnlyList FindSaveBoundaryPreviewCandidates(Player player, ZoneAreaSelection area) { _targetCandidateZdos.Clear(); if (ZDOMan.instance == null || (Object)(object)ZNetScene.instance == (Object)null || (Object)(object)player == (Object)null) { return _targetCandidateZdos; } long playerID = player.GetPlayerID(); if (playerID == 0L) { return _targetCandidateZdos; } ZoneAreaTargetOverlay.CollectNearbyZdos(area, _nearbyTargetZdos); foreach (ZDO nearbyTargetZdo in _nearbyTargetZdos) { if (!ZoneBlueprintCommands.IsHomesteadBlueprintChest(nearbyTargetZdo) && ZoneBlueprintCommands.TryReadSavableWearNTear(nearbyTargetZdo, out GameObject _) && IsLoadedWearNTear(nearbyTargetZdo)) { long @long = nearbyTargetZdo.GetLong(ZDOVars.s_creator, 0L); if (BlueprintConfig.AreaSaveAllowsCreator(playerID, @long)) { _targetCandidateZdos.Add(nearbyTargetZdo); } } } return _targetCandidateZdos; } private static bool IsLoadedWearNTear(ZDO zdo) { if ((Object)(object)ZNetScene.instance == (Object)null) { return false; } ZNetView val = ZNetScene.instance.FindInstance(zdo); if ((Object)(object)val != (Object)null) { return (Object)(object)((Component)val).GetComponent() != (Object)null; } return false; } private void DrawSelectionPreview(IReadOnlyList zdos) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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) ClearPreviewLines(); if (_selection != null) { _selectionPreviewRoot = new GameObject("HomesteadBlueprintHeldPreview"); _selectionPreviewRoot.transform.SetParent(((Component)this).transform, false); _selectionPreviewRoot.transform.position = AreaTool.AimPoint + Vector3.up * 4f; _selectionPreviewRoot.transform.rotation = _selection.AnchorRotation; _previewBuildCoroutine = ((MonoBehaviour)this).StartCoroutine(BuildSelectionPreview(zdos.ToList(), _selection, _selectionPreviewRoot)); } } [IteratorStateMachine(typeof(d__59))] private IEnumerator BuildSelectionPreview(IReadOnlyList zdos, SaveSelection selection, GameObject root) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__59(0) { <>4__this = this, zdos = zdos, selection = selection, root = root }; } private void UpdateSelectionPreview() { //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) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0057: 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_0071: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_selectionPreviewRoot == (Object)null) && _selection != null) { _selectionPreviewRoot.transform.position = AreaTool.AimPoint + Vector3.up * 4f; _selectionPreviewRoot.transform.rotation = _selection.AnchorRotation * Quaternion.Euler(0f, _selectionPreviewYawOffset, 0f); } } private void EnsureSavePanel() { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Expected O, but got Unknown //IL_02a9: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_02c7: Unknown result type (might be due to invalid IL or missing references) //IL_02ec: Unknown result type (might be due to invalid IL or missing references) //IL_02f6: Expected O, but got Unknown //IL_0308: Unknown result type (might be due to invalid IL or missing references) //IL_0317: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Unknown result type (might be due to invalid IL or missing references) //IL_0334: Unknown result type (might be due to invalid IL or missing references) //IL_033a: Unknown result type (might be due to invalid IL or missing references) if ((!((Object)(object)_savePanel != (Object)null) || !Object.op_Implicit((Object)(object)_savePanel)) && !((Object)(object)GUIManager.CustomGUIFront == (Object)null)) { GUIManager instance = GUIManager.Instance; _savePanel = instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, 382f, 214f, true); ((Object)_savePanel).name = "HomesteadBlueprintSavePanel"; Transform transform = _savePanel.transform; instance.CreateText(HomesteadLocalization.Text("hs_blueprint_save_title"), transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -28f), instance.AveriaSerifBold, 20, instance.ValheimOrange, true, Color.black, 320f, 28f, false); _saveCountText = instance.CreateText("", transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -62f), instance.AveriaSerif, 15, instance.ValheimBeige, true, Color.black, 320f, 24f, false).GetComponent(); instance.CreateText(HomesteadLocalization.Text("hs_blueprint_name_label"), transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -88f), instance.AveriaSerifBold, 15, instance.ValheimOrange, true, Color.black, 320f, 22f, false); GameObject val = instance.CreateInputField(transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -122f), (ContentType)0, HomesteadLocalization.Text("hs_blueprint_name_placeholder"), 16, 292f, 34f); _saveNameInput = val.GetComponent(); _saveNameInput.characterLimit = 64; ((UnityEvent)(object)_saveNameInput.onValueChanged).AddListener((UnityAction)delegate(string value) { _saveName = value; }); ((UnityEvent)instance.CreateButton(HomesteadLocalization.Text("hs_common_save"), transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(-76f, -166f), 132f, 34f).GetComponent