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 <Name>k__BackingField;
public string Name => <Name>k__BackingField;
public ExtensionMarkerAttribute(string name)
{
<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<string> ProtectedContainerPrefabs = new HashSet<string>(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<ZoneBlueprintRequirement> missingRequirements, Action<ZoneBlueprintRequirement, int> 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<object>()) 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<object>()) 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<ItemData?, bool> 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<GameObject> 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<ZoneBlueprintTerrainContact> CaptureContacts(Vector3 anchor, Quaternion inverseAnchorRotation, IEnumerable<TerrainContactSource> 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<TerrainWorldContact> contacts = BlueprintTerrainContactSampler.CaptureWorldContacts(sources, BlueprintConfig.TerrainSupportContactTolerance);
return BlueprintTerrainContactSampler.ToBlueprintContacts(anchor, inverseAnchorRotation, contacts);
}
public static bool ApplySupportContacts(IEnumerable<Vector3> supportContacts)
{
return HomesteadTerrainSupport.ApplyWorldSupportContacts(supportContacts);
}
public static IEnumerator ApplySupportContactsAsync(IEnumerable<Vector3> supportContacts, Action<bool> onComplete)
{
return HomesteadTerrainSupport.ApplyWorldSupportContactsAsync(supportContacts, onComplete);
}
}
internal static class BlueprintTerrainContactSampler
{
public static List<TerrainWorldContact> CaptureWorldContacts(IEnumerable<TerrainContactSource> 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<long, TerrainWorldContact> dictionary = new Dictionary<long, TerrainWorldContact>();
foreach (TerrainContactSource source in sources)
{
if (Object.op_Implicit((Object)(object)source.Prefab) && !((Object)(object)source.Prefab.GetComponent<WearNTear>() == (Object)null) && HomesteadTerrainSupport.TryGetWearNTearBounds(source.Prefab, source.Position, source.Rotation, source.Scale, out var bounds))
{
AddLowestBoundsFootprintContacts(bounds, dictionary);
}
}
List<TerrainWorldContact> list = new List<TerrainWorldContact>();
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<ZoneBlueprintTerrainContact> ToBlueprintContacts(Vector3 anchor, Quaternion inverseAnchorRotation, IEnumerable<TerrainWorldContact> 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<long, TerrainWorldContact> 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<T> config<T>(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<T> val2 = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, val);
ConfigSync.AddConfigEntry<T>(val2).SynchronizedConfig = synchronizedSetting;
return val2;
}
internal ConfigEntry<T> config<T>(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<object>()), 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<HomesteadPlugin.Toggle> _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<HomesteadPlugin.Toggle>(_serverConfigLocked);
}
}
internal static class ClientConfig
{
private static ConfigEntry<float> _counterVisibleSeconds;
private static ConfigEntry<float> _statusHudX;
private static ConfigEntry<float> _statusHudY;
private static ConfigEntry<int> _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<float>(0.1f, 10f), Array.Empty<object>()), 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<float>(0f, 3000f), Array.Empty<object>()), 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<float>(0f, 3000f), Array.Empty<object>()), 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<int>(10, 64), Array.Empty<object>()), 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<BlueprintTerrainSupportMode> _terrainSupport = null;
private static ConfigEntry<int> _chestRows = null;
private static ConfigEntry<KeyboardShortcut> _chestConfirmHotkey = null;
private static ConfigEntry<BlueprintAzuCraftyBoxesPullMode> _azuCraftyBoxesPullMode = null;
private static ConfigEntry<float> _terrainSupportContactTolerance = null;
private static ConfigEntry<float> _terrainSupportFeatherWidth = null;
private static ConfigEntry<int> _maxUploadKb = null;
private static ConfigEntry<int> _maxEntries = null;
private static ConfigEntry<int> _maxPreviewEntries = null;
private static ConfigEntry<int> _maxIconKb = null;
private static ConfigEntry<int> _storeListingDays = null;
private static ConfigEntry<int> _storeAutoDelistMaxPurchases = null;
private static ConfigEntry<int> _storeMaxListingsPerSteamId = null;
private static ConfigEntry<BlueprintStoreIdentityMode> _storeIdentityMode = null;
private static ConfigEntry<int> _chestTimeoutMinutes = null;
private static ConfigEntry<int> _chestMapIconSize = null;
private static ConfigEntry<int> _maxActiveChestsPerPlayer = null;
private static ConfigEntry<float> _storeLargePanelScale = null;
private static ConfigEntry<float> _storeLargePanelX = null;
private static ConfigEntry<float> _storeLargePanelY = null;
private static ConfigEntry<float> _storeFormPanelScale = null;
private static ConfigEntry<float> _storeFormPanelX = null;
private static ConfigEntry<float> _storeFormPanelY = null;
private static ConfigEntry<HomesteadPlugin.Toggle> _storeAnonymousNotifications = null;
private static ConfigEntry<BlueprintStoreNotificationMode> _storeNotificationMode = null;
private static ConfigEntry<HomesteadPlugin.Toggle> _storeDebugLogging = null;
private static ConfigEntry<float> _storeNotificationButtonX = null;
private static ConfigEntry<float> _storeNotificationButtonY = null;
private static ConfigEntry<KeyboardShortcut> _storeListModifierKey = null;
private static ConfigEntry<KeyboardShortcut> _storeBackHotkey = null;
private static ConfigEntry<Color> _storeListingPreviewColor = null;
private static ConfigEntry<Color> _storePurchasePreviewColor = null;
private static ConfigEntry<float> _areaSaveMaxSide = null;
private static ConfigEntry<float> _areaSaveDefaultWidth = null;
private static ConfigEntry<float> _areaSaveDefaultDepth = null;
private static ConfigEntry<BlueprintAreaSaveCreatorMode> _areaSaveCreatorMode = null;
private static ConfigEntry<Color> _areaSaveBoundaryColor = null;
private static ConfigEntry<float> _areaDismantleMaxSide = null;
private static ConfigEntry<float> _areaDismantleDefaultWidth = null;
private static ConfigEntry<float> _areaDismantleDefaultDepth = null;
private static ConfigEntry<Color> _areaDismantleBoundaryColor = null;
private static ConfigEntry<string> _areaDismantlePrefabBlacklist = null;
private static ConfigEntry<KeyboardShortcut> _areaToolDepthModifierKey = null;
private static ConfigEntry<KeyboardShortcut> _areaToolWidthModifierKey = null;
private static ConfigEntry<Color> _previewGhostColor = null;
private static ConfigEntry<float> _previewGhostBrightness = null;
private static readonly HashSet<string> BuiltInAreaDismantleProtectedPrefabs = new HashSet<string>(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<string> 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<int>(10, 40), Array.Empty<object>()));
_chestConfirmHotkey = plugin.config<KeyboardShortcut>("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<float>(0.01f, 2f), Array.Empty<object>()));
_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<float>(0f, 64f), Array.Empty<object>()));
_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<int>(64, 16384), Array.Empty<object>()));
_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<int>(1, 20000), Array.Empty<object>()));
_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<int>(1, 20000), Array.Empty<object>()));
_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<int>(0, 2048), Array.Empty<object>()));
_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<int>(0, 365), Array.Empty<object>()));
_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<int>(0, 100000), Array.Empty<object>()));
_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<int>(1, 200), Array.Empty<object>()));
_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<int>(0, 60), Array.Empty<object>()));
_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<int>(0, 10), Array.Empty<object>()), 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<int>(0, 50), Array.Empty<object>()));
_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<float>(0.75f, 2f), Array.Empty<object>()), 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<float>(-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<float>(-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<float>(0.75f, 2f), Array.Empty<object>()), 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<float>(-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<float>(-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<float>(-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<float>(-3000f, 3000f), new object[1]
{
new ConfigurationManagerAttributes
{
Browsable = false
}
}), synchronizedSetting: false);
_storeListModifierKey = plugin.config<KeyboardShortcut>("04 - Blueprint Store", "Blueprint Store List Modifier Key", new KeyboardShortcut((KeyCode)308, Array.Empty<KeyCode>()), "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<KeyboardShortcut>("04 - Blueprint Store", "Blueprint Store Back Hotkey", new KeyboardShortcut((KeyCode)326, Array.Empty<KeyCode>()), "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<Color>("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<Color>("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<float>(2f, 256f), Array.Empty<object>()));
_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<float>(2f, 256f), Array.Empty<object>()), 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<float>(2f, 256f), Array.Empty<object>()), 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<Color>("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<float>(1f, 128f), Array.Empty<object>()));
_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<float>(1f, 128f), Array.Empty<object>()), 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<float>(1f, 128f), Array.Empty<object>()), synchronizedSetting: false);
_areaDismantleBoundaryColor = plugin.config<Color>("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<KeyboardShortcut>("03 - Blueprint", "Area Tool Depth Modifier Key", new KeyboardShortcut((KeyCode)326, Array.Empty<KeyCode>()), "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<KeyboardShortcut>("03 - Blueprint", "Area Tool Width Modifier Key", new KeyboardShortcut((KeyCode)327, Array.Empty<KeyCode>()), "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<Color>("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<float>(0.1f, 2f), Array.Empty<object>()), 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<string> 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<string> list2 = list.Where((string entry) => !BuiltInAreaDismantleProtectedPrefabs.Contains(entry)).Distinct<string>(StringComparer.OrdinalIgnoreCase).ToList();
if (list2.Count != list.Count || !list2.SequenceEqual<string>(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<HomesteadPlugin.Toggle> _enabled;
private static ConfigEntry<float> _resourcePickupRange;
private static ConfigEntry<BuildCameraDistanceMode> _distanceMode;
private static ConfigEntry<float> _maxDistanceFromAvatar;
private static ConfigEntry<float> _baseDistanceFromAvatar;
private static ConfigEntry<float> _distancePerComfortLevel;
private static ConfigEntry<float> _moveSpeedMultiplier;
private static ConfigEntry<KeyboardShortcut> _toggleHotkey;
private static ConfigEntry<HomesteadPlugin.Toggle> _demisterFollowCamera;
private static ConfigEntry<KeyboardShortcut> _lookAtLockHotkey;
private static ConfigEntry<BuildCameraRestrictionMode> _restrictionMode;
private static ConfigEntry<int> _minimumComfortLevel;
private static ConfigEntry<HomesteadPlugin.Toggle> _followDvergrCircletLight;
private static ConfigEntry<float> _helmetLightOffsetForward;
private static ConfigEntry<float> _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<float>(0f, 100f), Array.Empty<object>()));
_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<float>(1f, 500f), Array.Empty<object>()));
_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<float>(1f, 500f), Array.Empty<object>()));
_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<float>(0f, 50f), Array.Empty<object>()));
_moveSpeedMultiplier = plugin.config("05 - Build Camera", "Camera Move Speed Multiplier", 3f, new ConfigDescription("Multiplies build camera panning speed.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 20f), Array.Empty<object>()));
_toggleHotkey = plugin.config<KeyboardShortcut>("05 - Build Camera", "Toggle Build Camera Hotkey", new KeyboardShortcut((KeyCode)98, Array.Empty<KeyCode>()), "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<KeyboardShortcut>("05 - Build Camera", "Look At Lock Hotkey", new KeyboardShortcut((KeyCode)113, Array.Empty<KeyCode>()), "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<int>(1, 30), Array.Empty<object>()));
_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<float>(-5f, 5f), Array.Empty<object>()), 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<float>(-5f, 5f), Array.Empty<object>()), synchronizedSetting: false);
}
}
internal static class PlacementControlConfig
{
private static ConfigEntry<KeyboardShortcut> _gridSnapToggleHotkey;
private static ConfigEntry<float> _gridSnapSize;
private static ConfigEntry<HomesteadPlugin.Toggle> _placementAdjustEnabled;
private static ConfigEntry<float> _placementAdjustHeightStep;
private static ConfigEntry<float> _placementAdjustHorizontalStep;
private static ConfigEntry<float> _placementRotationStep;
private static ConfigEntry<float> _placementXAxisRotation;
private static ConfigEntry<float> _placementZAxisRotation;
private static ConfigEntry<KeyboardShortcut> _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<KeyboardShortcut>("06 - Placement Controls", "Grid Snap Toggle Hotkey", new KeyboardShortcut((KeyCode)103, Array.Empty<KeyCode>()), "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<float>(0.05f, 1f), Array.Empty<object>()), 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<float>(0.01f, 10f), Array.Empty<object>()), 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<float>(0.01f, 10f), Array.Empty<object>()), 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<float>(1f, 90f), Array.Empty<object>()), 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<float>(-180f, 180f), Array.Empty<object>()), 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<float>(-180f, 180f), Array.Empty<object>()), synchronizedSetting: false);
_placementAdjustModifierKey = plugin.config<KeyboardShortcut>("06 - Placement Controls", "Position Adjust Modifier Key", new KeyboardShortcut((KeyCode)308, Array.Empty<KeyCode>()), "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<HomesteadPlugin.Toggle> _extensionEnabled;
private static ConfigEntry<float> _fuelMinutes;
private static ConfigEntry<string> _repairStation;
private static ConfigEntry<float> _perItemMaxIntensityMultiplier;
private static ConfigEntry<float> _perItemMaxRangeMultiplier;
private static ConfigEntry<float> _perItemAdjustmentStep;
private static ConfigEntry<KeyboardShortcut> _toggleLightHotkey;
private static ConfigEntry<KeyboardShortcut> _adjustmentModifierKey;
private static ConfigEntry<HomesteadPlugin.Toggle> _remoteVisualSync;
private static ConfigEntry<float> _remoteLightMaxDistance;
private static ConfigEntry<HomesteadPlugin.Toggle> _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<float>(1f, 10000f), Array.Empty<object>()));
_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<float>(1f, 3f), Array.Empty<object>()));
_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<float>(1f, 3f), Array.Empty<object>()));
_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<float>(0.05f, 1f), Array.Empty<object>()));
_toggleLightHotkey = plugin.config<KeyboardShortcut>("08 - Dvergr Circlet", "Toggle Light Hotkey", new KeyboardShortcut((KeyCode)108, Array.Empty<KeyCode>()), "Client-only hotkey that toggles the equipped Dvergr circlet light on or off.", synchronizedSetting: false);
_adjustmentModifierKey = plugin.config<KeyboardShortcut>("08 - Dvergr Circlet", "Adjustment Modifier Key", new KeyboardShortcut((KeyCode)304, Array.Empty<KeyCode>()), "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<float>(0f, 200f), Array.Empty<object>()), 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