Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Lamplighter v1.0.0
BepInEx\plugins\Lamplighter\Lamplighter.dll
Decompiled 15 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Lamplighter.Config; using Lamplighter.Creatures; using Lamplighter.Pieces; using Lamplighter.Systems; using Lamplighter.Visuals; using UnityEngine; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("Greguru")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright © Greguru 2026")] [assembly: AssemblyDescription("\r\n A Valheim mod that summons a fire spirit to tend nearby fires and lights.\r\n ")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("Lamplighter")] [assembly: AssemblyTitle("Lamplighter")] [assembly: AssemblyVersion("1.0.0.0")] namespace Lamplighter { [BepInPlugin("com.g.lamplighter", "Lamplighter", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] [SynchronizationMode(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "com.g.lamplighter"; public const string PluginName = "Lamplighter"; public const string PluginVersion = "1.0.0"; private void Awake() { ModConfig.Bind(((BaseUnityPlugin)this).Config); LamplighterPiece.Register(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Lamplighter 1.0.0 loaded. The fires of Valheim can be tended."); } } } namespace Lamplighter.Visuals { internal sealed class RangeIndicator : MonoBehaviour { private const int Segments = 96; private const float Width = 0.12f; private const float HeightOffset = 0.08f; private static readonly FieldInfo PlacementGhostField = AccessTools.Field(typeof(Player), "m_placementGhost"); private LineRenderer _line; private float _lastRadius = -1f; private void Awake() { //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Expected O, but got Unknown _line = ((Component)this).GetComponent<LineRenderer>(); if ((Object)(object)_line == (Object)null) { _line = ((Component)this).gameObject.AddComponent<LineRenderer>(); } _line.useWorldSpace = false; _line.loop = true; _line.positionCount = 96; _line.startWidth = 0.12f; _line.endWidth = 0.12f; ((Renderer)_line).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)_line).receiveShadows = false; Shader val = Shader.Find("Sprites/Default"); if ((Object)(object)val != (Object)null) { ((Renderer)_line).material = new Material(val); } ((Renderer)_line).enabled = false; RebuildCircle(); } private void Update() { //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) if (!ModConfig.ShowRangeWhilePlacing.Value) { ((Renderer)_line).enabled = false; return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || PlacementGhostField == null) { ((Renderer)_line).enabled = false; return; } object? value = PlacementGhostField.GetValue(localPlayer); if (!((Object)((value is GameObject) ? value : null) == (Object)(object)((Component)this).gameObject)) { ((Renderer)_line).enabled = false; return; } ((Renderer)_line).enabled = true; if (!Mathf.Approximately(ModConfig.WorkRadius.Value, _lastRadius)) { RebuildCircle(); } Color value2 = ModConfig.WispColor.Value; value2.a = 0.85f; _line.startColor = value2; _line.endColor = value2; if ((Object)(object)((Renderer)_line).material != (Object)null) { ((Renderer)_line).material.color = value2; } } private void RebuildCircle() { //IL_0047: Unknown result type (might be due to invalid IL or missing references) float num = (_lastRadius = ModConfig.WorkRadius.Value); for (int i = 0; i < 96; i++) { float num2 = (float)i * (float)Math.PI * 2f / 96f; _line.SetPosition(i, new Vector3(Mathf.Cos(num2) * num, 0.08f, Mathf.Sin(num2) * num)); } } private void OnDestroy() { if ((Object)(object)_line != (Object)null && (Object)(object)((Renderer)_line).material != (Object)null) { Object.Destroy((Object)(object)((Renderer)_line).material); } } } internal sealed class ShrineVisuals : MonoBehaviour { private readonly List<Material> _shrineMaterials = new List<Material>(); private readonly List<Material> _oozeMaterials = new List<Material>(); private bool _initialized; private bool _subscribed; private void Awake() { Initialize(); } private void OnEnable() { Initialize(); ApplyColors(); } private void Initialize() { if (!_initialized) { CacheMaterials(); _initialized = true; } Subscribe(); ApplyColors(); } private void CacheMaterials() { _shrineMaterials.Clear(); _oozeMaterials.Clear(); Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<Renderer>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Material[] materials = componentsInChildren[i].materials; foreach (Material val in materials) { if (!((Object)(object)val == (Object)null)) { if (((Object)val).name.StartsWith("WispLure_mat")) { _shrineMaterials.Add(val); } else if (((Object)val).name.StartsWith("Ooze_mat")) { _oozeMaterials.Add(val); } } } } } private void Subscribe() { if (!_subscribed) { if (ModConfig.ShrineColor != null) { ModConfig.ShrineColor.SettingChanged += OnAppearanceChanged; } if (ModConfig.OozeColor != null) { ModConfig.OozeColor.SettingChanged += OnAppearanceChanged; } _subscribed = true; } } private void OnAppearanceChanged(object sender, EventArgs e) { ApplyColors(); } private void ApplyColors() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: 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_006d: Unknown result type (might be due to invalid IL or missing references) if (ModConfig.ShrineColor != null) { Color value = ModConfig.ShrineColor.Value; foreach (Material shrineMaterial in _shrineMaterials) { ApplyMaterialColor(shrineMaterial, value); } } if (ModConfig.OozeColor == null) { return; } Color value2 = ModConfig.OozeColor.Value; foreach (Material oozeMaterial in _oozeMaterials) { ApplyMaterialColor(oozeMaterial, value2); } } private static void ApplyMaterialColor(Material material, Color color) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)material == (Object)null)) { if (material.HasProperty("_Color")) { material.SetColor("_Color", color); } if (material.HasProperty("_EmissionColor")) { material.SetColor("_EmissionColor", color); } } } private void OnDestroy() { if (_subscribed) { if (ModConfig.ShrineColor != null) { ModConfig.ShrineColor.SettingChanged -= OnAppearanceChanged; } if (ModConfig.OozeColor != null) { ModConfig.OozeColor.SettingChanged -= OnAppearanceChanged; } _subscribed = false; } } } internal sealed class WispVisuals : MonoBehaviour { private Color _lastColor; private void Start() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) _lastColor = new Color(-1f, -1f, -1f, -1f); ApplyColor(); } private void Update() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) if (ModConfig.WispColor.Value != _lastColor) { ApplyColor(); } } private void ApplyColor() { //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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) Color val = (_lastColor = ModConfig.WispColor.Value); Light[] componentsInChildren = ((Component)this).GetComponentsInChildren<Light>(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].color = val; } ParticleSystem[] componentsInChildren2 = ((Component)this).GetComponentsInChildren<ParticleSystem>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { MainModule main = componentsInChildren2[i].main; ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(val); } Renderer[] componentsInChildren3 = ((Component)this).GetComponentsInChildren<Renderer>(true); for (int i = 0; i < componentsInChildren3.Length; i++) { Material[] materials = componentsInChildren3[i].materials; foreach (Material val2 in materials) { if (val2.HasProperty("_Color")) { val2.color = val; } if (val2.HasProperty("_EmissionColor")) { val2.SetColor("_EmissionColor", new Color(val.r * 2f, val.g * 2f, val.b * 2f, 1f)); } } } } } internal static class WispVisualsFactory { public static GameObject Prefab { get; private set; } public static void Create() { if ((Object)(object)Prefab != (Object)null) { return; } Prefab = PrefabManager.Instance.CreateClonedPrefab("lamplighter_wisp_visual", "LuredWisp"); if ((Object)(object)Prefab == (Object)null) { Logger.LogError((object)"Could not clone LuredWisp prefab."); return; } RemoveComponent<ZNetView>(); RemoveComponent<ZSyncTransform>(); RemoveComponent<LuredWisp>(); RemoveComponent<Pickable>(); RemoveComponent<Rigidbody>(); Collider[] componentsInChildren = Prefab.GetComponentsInChildren<Collider>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } if ((Object)(object)Prefab.GetComponent<WispVisuals>() == (Object)null) { Prefab.AddComponent<WispVisuals>(); } Prefab.SetActive(false); ModConfig.DebugLog("Created Lamplighter wisp visual."); } private static void RemoveComponent<T>() where T : Component { T component = Prefab.GetComponent<T>(); if ((Object)(object)component != (Object)null) { Object.DestroyImmediate((Object)(object)component); } } } } namespace Lamplighter.Systems { internal static class ContainerScanner { public static Container FindNearestContaining(Vector3 origin, string itemName) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(itemName)) { return null; } float value = ModConfig.WorkRadius.Value; float num = value * value; Container result = null; float num2 = float.MaxValue; Container[] array = Object.FindObjectsOfType<Container>(); foreach (Container val in array) { if ((Object)(object)val == (Object)null || !((Behaviour)val).isActiveAndEnabled) { continue; } Vector3 val2 = ((Component)val).transform.position - origin; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (!(sqrMagnitude > num) && (!(itemName == "$item_wood") || !IsWoodStack(val) || ModConfig.TakeWoodFromWoodStacks.Value)) { Inventory inventory = val.GetInventory(); if (inventory != null && inventory.CountItems(itemName, -1, true) > 0 && sqrMagnitude < num2) { result = val; num2 = sqrMagnitude; } } } return result; } public static bool IsWoodStack(Container container) { if ((Object)(object)container == (Object)null) { return false; } Piece componentInParent = ((Component)container).GetComponentInParent<Piece>(); if ((Object)(object)componentInParent == (Object)null) { return false; } string name = ((Object)((Component)componentInParent).gameObject).name; if (!(name == "wood_stack")) { return name.StartsWith("wood_stack("); } return true; } } internal static class FireScanner { private static readonly FieldInfo NViewField = AccessTools.Field(typeof(Fireplace), "m_nview"); private static readonly FieldInfo MaxFuelField = AccessTools.Field(typeof(Fireplace), "m_maxFuel"); private static readonly FieldInfo StartFuelField = AccessTools.Field(typeof(Fireplace), "m_startFuel"); private static readonly FieldInfo InfiniteFuelField = AccessTools.Field(typeof(Fireplace), "m_infiniteFuel"); private static readonly FieldInfo FuelItemField = AccessTools.Field(typeof(Fireplace), "m_fuelItem"); public static Fireplace FindNearestNeedingFuel(Vector3 origin) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) float value = ModConfig.WorkRadius.Value; float num = value * value; Fireplace result = null; float num2 = float.MaxValue; Fireplace[] array = Object.FindObjectsOfType<Fireplace>(); foreach (Fireplace val in array) { if (IsValidPlacedFireplace(val)) { Vector3 val2 = ((Component)val).transform.position - origin; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (!(sqrMagnitude > num) && NeedsFuel(val) && sqrMagnitude < num2) { result = val; num2 = sqrMagnitude; } } } return result; } public static Fireplace FindNearestServiceable(Vector3 origin, IDictionary<string, int> carriedFuel) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) if (carriedFuel == null || carriedFuel.Count == 0) { return null; } float value = ModConfig.WorkRadius.Value; float num = value * value; Fireplace result = null; float num2 = float.MaxValue; Fireplace[] array = Object.FindObjectsOfType<Fireplace>(); foreach (Fireplace val in array) { if (!IsValidPlacedFireplace(val)) { continue; } Vector3 val2 = ((Component)val).transform.position - origin; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (!(sqrMagnitude > num) && NeedsFuel(val) && CanAcceptFuel(val)) { string fuelItemName = GetFuelItemName(val); if (!string.IsNullOrEmpty(fuelItemName) && carriedFuel.TryGetValue(fuelItemName, out var value2) && value2 > 0 && sqrMagnitude < num2) { result = val; num2 = sqrMagnitude; } } } return result; } public static Dictionary<string, int> GetFuelTypesInRadius(Vector3 origin) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) Dictionary<string, int> dictionary = new Dictionary<string, int>(); float value = ModConfig.WorkRadius.Value; float num = value * value; Fireplace[] array = Object.FindObjectsOfType<Fireplace>(); foreach (Fireplace val in array) { if (!IsValidPlacedFireplace(val)) { continue; } Vector3 val2 = ((Component)val).transform.position - origin; if (((Vector3)(ref val2)).sqrMagnitude > num) { continue; } string fuelItemName = GetFuelItemName(val); if (!string.IsNullOrEmpty(fuelItemName)) { int fuelStackLimit = GetFuelStackLimit(val); if (!dictionary.TryGetValue(fuelItemName, out var value2) || fuelStackLimit > value2) { dictionary[fuelItemName] = fuelStackLimit; } } } return dictionary; } public static bool NeedsFuel(Fireplace fireplace) { if (!IsValidPlacedFireplace(fireplace)) { return false; } if (InfiniteFuelField != null && (bool)InfiniteFuelField.GetValue(fireplace)) { return false; } float maxFuel = GetMaxFuel(fireplace); if (maxFuel <= 0f) { return false; } if (GetFuelNeededToMax(fireplace) <= 0) { return false; } return GetFuel(fireplace) / maxFuel < ModConfig.RefillThreshold; } public static bool CanAcceptFuel(Fireplace fireplace) { if (!IsValidPlacedFireplace(fireplace)) { return false; } return GetFuelNeededToMax(fireplace) > 0; } public static int GetFuelNeededToMax(Fireplace fireplace) { if (!IsValidPlacedFireplace(fireplace)) { return 0; } float maxFuel = GetMaxFuel(fireplace); if (maxFuel <= 0f) { return 0; } float fuel = GetFuel(fireplace); float num = maxFuel - fuel; if (num < 1f) { return 0; } return Mathf.Max(0, Mathf.FloorToInt(num + 0.0001f)); } public static float GetMaxFuel(Fireplace fireplace) { if ((Object)(object)fireplace == (Object)null || MaxFuelField == null) { return 0f; } return (float)MaxFuelField.GetValue(fireplace); } public static float GetFuel(Fireplace fireplace) { if (!IsValidPlacedFireplace(fireplace)) { return 0f; } ZNetView networkView = GetNetworkView(fireplace); if ((Object)(object)networkView == (Object)null) { return 0f; } ZDO zDO = networkView.GetZDO(); if (zDO == null) { return 0f; } float num = zDO.GetFloat("fuel", -1f); if (num < 0f) { num = ((StartFuelField != null) ? ((float)StartFuelField.GetValue(fireplace)) : 0f); } return num; } public static string GetFuelItemName(Fireplace fireplace) { return GetFuelItem(fireplace)?.m_itemData?.m_shared?.m_name; } public static int GetFuelStackLimit(Fireplace fireplace) { ItemDrop fuelItem = GetFuelItem(fireplace); if (fuelItem?.m_itemData?.m_shared == null) { return 1; } return Mathf.Max(1, fuelItem.m_itemData.m_shared.m_maxStackSize); } public static bool IsValidPlacedFireplace(Fireplace fireplace) { if ((Object)(object)fireplace == (Object)null || !((Behaviour)fireplace).isActiveAndEnabled || !((Component)fireplace).gameObject.activeInHierarchy) { return false; } ZNetView networkView = GetNetworkView(fireplace); if ((Object)(object)networkView == (Object)null || !networkView.IsValid()) { return false; } if (networkView.GetZDO() == null) { return false; } return true; } private static ZNetView GetNetworkView(Fireplace fireplace) { if ((Object)(object)fireplace == (Object)null || NViewField == null) { return null; } object? value = NViewField.GetValue(fireplace); return (ZNetView)((value is ZNetView) ? value : null); } private static ItemDrop GetFuelItem(Fireplace fireplace) { if ((Object)(object)fireplace == (Object)null || FuelItemField == null) { return null; } object? value = FuelItemField.GetValue(fireplace); return (ItemDrop)((value is ItemDrop) ? value : null); } } internal static class FuelService { private static readonly FieldInfo ContainerNViewField = AccessTools.Field(typeof(Container), "m_nview"); private static readonly FieldInfo FireplaceNViewField = AccessTools.Field(typeof(Fireplace), "m_nview"); private static readonly MethodInfo InventoryChangedMethod = AccessTools.Method(typeof(Inventory), "Changed", (Type[])null, (Type[])null); private static readonly MethodInfo ContainerSaveMethod = AccessTools.Method(typeof(Container), "Save", (Type[])null, (Type[])null); private static readonly MethodInfo RemoveItemMethod = AccessTools.Method(typeof(Inventory), "RemoveItem", new Type[1] { typeof(ItemData) }, (Type[])null); public static int TakeFuel(Container container, string fuelName, int maximumAmount) { if ((Object)(object)container == (Object)null || string.IsNullOrEmpty(fuelName) || maximumAmount <= 0) { return 0; } Inventory inventory = container.GetInventory(); if (inventory == null) { return 0; } object? obj = ContainerNViewField?.GetValue(container); ZNetView val = (ZNetView)((obj is ZNetView) ? obj : null); if ((Object)(object)val != (Object)null && val.IsValid() && !val.IsOwner()) { val.ClaimOwnership(); } int num = maximumAmount; int num2 = 0; foreach (ItemData item in new List<ItemData>(inventory.GetAllItems())) { if (num <= 0) { break; } if (item == null || item.m_shared == null || item.m_shared.m_name != fuelName || item.m_stack <= 0) { continue; } int num3 = Mathf.Min(item.m_stack, num); if (num3 == item.m_stack) { if (RemoveItemMethod == null) { continue; } RemoveItemMethod.Invoke(inventory, new object[1] { item }); } else { item.m_stack -= num3; } num2 += num3; num -= num3; } if (num2 <= 0) { return 0; } InventoryChangedMethod?.Invoke(inventory, null); ContainerSaveMethod?.Invoke(container, null); HandleEmptyWoodStack(container, fuelName); ModConfig.DebugLog($"Lamplighter: picked up {num2} x {fuelName}"); return num2; } public static int AddFuelToMax(Fireplace fireplace, int availableAmount) { if ((Object)(object)fireplace == (Object)null || availableAmount <= 0) { return 0; } int fuelNeededToMax = FireScanner.GetFuelNeededToMax(fireplace); if (fuelNeededToMax <= 0) { return 0; } int num = Mathf.Min(fuelNeededToMax, availableAmount); object? obj = FireplaceNViewField?.GetValue(fireplace); ZNetView val = (ZNetView)((obj is ZNetView) ? obj : null); if ((Object)(object)val == (Object)null || !val.IsValid()) { return 0; } if (!val.IsOwner()) { val.ClaimOwnership(); } for (int i = 0; i < num; i++) { val.InvokeRPC("RPC_AddFuel", Array.Empty<object>()); } ModConfig.DebugLog($"Lamplighter: delivered {num} fuel to {((Object)fireplace).name}"); return num; } private static void HandleEmptyWoodStack(Container container, string fuelName) { if (!ModConfig.TakeWoodFromWoodStacks.Value || fuelName != "$item_wood" || !ContainerScanner.IsWoodStack(container)) { return; } Inventory inventory = container.GetInventory(); if (inventory != null && inventory.CountItems("$item_wood", -1, true) > 0) { return; } Piece componentInParent = ((Component)container).GetComponentInParent<Piece>(); if (!((Object)(object)componentInParent == (Object)null)) { ZNetView component = ((Component)componentInParent).GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null && component.IsValid() && !component.IsOwner()) { component.ClaimOwnership(); } if ((Object)(object)ZNetScene.instance != (Object)null) { ZNetScene.instance.Destroy(((Component)componentInParent).gameObject); } } } } } namespace Lamplighter.Pieces { internal static class LamplighterPiece { public const string PrefabName = "piece_lamplighter"; private const string SourcePrefab = "piece_wisplure"; private static CustomPiece _customPiece; public static void Register() { PrefabManager.OnVanillaPrefabsAvailable += CreatePiece; } private static void CreatePiece() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown PrefabManager.OnVanillaPrefabsAvailable -= CreatePiece; WispVisualsFactory.Create(); PieceConfig val = new PieceConfig { Name = "Lamplighter", Description = "Summons a fire spirit that tends nearby fires and lights.", PieceTable = PieceTables.Hammer, Category = PieceCategories.Misc, CraftingStation = CraftingStations.Workbench }; val.AddRequirement("Stone", 10, true); val.AddRequirement("Resin", 5, true); val.AddRequirement("SurtlingCore", 1, true); _customPiece = new CustomPiece("piece_lamplighter", "piece_wisplure", val); GameObject piecePrefab = _customPiece.PiecePrefab; if ((Object)(object)piecePrefab.GetComponent<ShrineVisuals>() == (Object)null) { piecePrefab.AddComponent<ShrineVisuals>(); } if ((Object)(object)piecePrefab.GetComponent<RangeIndicator>() == (Object)null) { piecePrefab.AddComponent<RangeIndicator>(); } if ((Object)(object)piecePrefab.GetComponent<LamplighterWisp>() == (Object)null) { piecePrefab.AddComponent<LamplighterWisp>(); } WispSpawner component = piecePrefab.GetComponent<WispSpawner>(); if ((Object)(object)component != (Object)null) { Object.DestroyImmediate((Object)(object)component); } PieceManager.Instance.AddPiece(_customPiece); ModConfig.DebugLog("Registered Lamplighter build piece."); } } } namespace Lamplighter.Creatures { internal sealed class LamplighterWisp : MonoBehaviour, Hoverable { private enum WispState { Idle, ToChest, AtChest, ToFire, AtFire } private const float HoverHeight = 1.8f; private const float BobAmount = 0.15f; private const float BobSpeed = 1.5f; private const float DriftAmount = 0.18f; private const float DriftSpeed = 0.65f; private const float MoveSpeed = 3.5f; private const float ChestHoverHeight = 1.1f; private const float ChestArrivalDistance = 0.35f; private const float FireHoverDistance = 0.8f; private const float FireHoverHeight = 0.7f; private const float FireArrivalDistance = 0.3f; private const float ChestPauseTime = 0.6f; private const float FirePauseTime = 0.4f; private const float RestingScanInterval = 3f; private const float RemoteSyncInterval = 0.5f; private const string InventoryZdoKey = "com.g.lamplighter.carried_inventory"; private const string VisualStateZdoKey = "com.g.lamplighter.visual_state"; private static readonly FieldInfo ObjectDbItemsField = AccessTools.Field(typeof(ObjectDB), "m_items"); private GameObject _wisp; private ZNetView _nview; private WearNTear _wearNTear; private Fireplace _targetFire; private Container _targetContainer; private readonly Dictionary<string, int> _inventory = new Dictionary<string, int>(); private readonly Dictionary<string, int> _stackLimits = new Dictionary<string, int>(); private readonly List<string> _restockQueue = new List<string>(); private int _restockIndex; private string _restockFuelName; private WispState _state; private float _timeOffset; private float _nextScanTime; private float _stateTimer; private bool _isResting; private bool _restockDidWork; private bool _inventoryReturned; private bool _wasOwner; private char _remoteVisualMode = 'H'; private Vector3 _remoteVisualTarget; private float _nextRemoteSyncTime; private void Start() { _timeOffset = Random.Range(0f, 100f); _nview = ((Component)this).GetComponent<ZNetView>(); _wearNTear = ((Component)this).GetComponent<WearNTear>(); if ((Object)(object)_wearNTear != (Object)null) { WearNTear wearNTear = _wearNTear; wearNTear.m_onDestroyed = (Action)Delegate.Combine(wearNTear.m_onDestroyed, new Action(OnShrineDestroyed)); } CreateWisp(); if ((Object)(object)_nview != (Object)null && _nview.IsValid()) { LoadInventoryFromZdo(); _wasOwner = _nview.IsOwner(); if (_wasOwner) { SaveVisualHome(); } else { LoadVisualStateFromZdo(); } } } private void CreateWisp() { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_wisp != (Object)null) && !((Object)(object)WispVisualsFactory.Prefab == (Object)null)) { _wisp = Object.Instantiate<GameObject>(WispVisualsFactory.Prefab, ((Component)this).transform); ((Object)_wisp).name = "LamplighterWisp"; _wisp.transform.localScale = Vector3.one * 0.65f; _wisp.transform.localPosition = new Vector3(0f, 1.8f, 0f); _wisp.SetActive(true); } } private void Update() { if ((Object)(object)_wisp == (Object)null) { CreateWisp(); return; } if ((Object)(object)_nview == (Object)null || !_nview.IsValid()) { MoveHome(); return; } bool flag = _nview.IsOwner(); if (flag != _wasOwner) { _wasOwner = flag; LoadInventoryFromZdo(); ResetWorkState(); if (flag) { SaveVisualHome(); ModConfig.DebugLog("Lamplighter: acquired network ownership."); } } if (!flag) { UpdateRemoteVisual(); return; } switch (_state) { case WispState.Idle: UpdateIdle(); break; case WispState.ToChest: UpdateToChest(); break; case WispState.AtChest: UpdateAtChest(); break; case WispState.ToFire: UpdateToFire(); break; case WispState.AtFire: UpdateAtFire(); break; } } private void UpdateIdle() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) MoveHome(); if (!(Time.time < _nextScanTime)) { Fireplace val = FireScanner.FindNearestServiceable(((Component)this).transform.position, _inventory); if ((Object)(object)val != (Object)null) { LeaveResting(); BeginFireJob(val); } else if (StartRestockRun()) { LeaveResting(); } else { EnterResting(); } } } private void BeginFireJob(Fireplace fireplace) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) if (FireScanner.IsValidPlacedFireplace(fireplace)) { string fuelItemName = FireScanner.GetFuelItemName(fireplace); int carried = GetCarried(fuelItemName); if (carried > 0) { _targetFire = fireplace; _state = WispState.ToFire; Vector3 fireHoverPosition = GetFireHoverPosition(fireplace); SaveVisualTarget('F', fireHoverPosition); ModConfig.DebugLog($"Lamplighter: servicing {((Object)fireplace).name} with {fuelItemName} ({carried} carried)"); } } } private bool StartRestockRun() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) Dictionary<string, int> fuelTypesInRadius = FireScanner.GetFuelTypesInRadius(((Component)this).transform.position); if (fuelTypesInRadius.Count == 0) { return false; } foreach (KeyValuePair<string, int> item in fuelTypesInRadius) { _stackLimits[item.Key] = item.Value; } _restockQueue.Clear(); _restockIndex = 0; _restockDidWork = false; foreach (KeyValuePair<string, int> item2 in fuelTypesInRadius) { string key = item2.Key; int value = item2.Value; if (GetCarried(key) < value) { _restockQueue.Add(key); } } if (_restockQueue.Count == 0) { return false; } if (!BeginNextRestockFuel()) { return false; } ModConfig.DebugLog($"Lamplighter: beginning restock run for {_restockQueue.Count} fuel type(s)"); return true; } private bool BeginNextRestockFuel() { _targetContainer = null; _restockFuelName = null; while (_restockIndex < _restockQueue.Count) { string text = _restockQueue[_restockIndex]; _restockIndex++; int stackLimit = GetStackLimit(text); if (GetCarried(text) < stackLimit) { _restockFuelName = text; if (FindContainerForCurrentFuel()) { return true; } _restockFuelName = null; } } FinishRestockRun(); return false; } private bool FindContainerForCurrentFuel() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(_restockFuelName)) { return false; } int stackLimit = GetStackLimit(_restockFuelName); if (GetCarried(_restockFuelName) >= stackLimit) { return false; } Container val = ContainerScanner.FindNearestContaining(((Component)this).transform.position, _restockFuelName); if ((Object)(object)val == (Object)null) { return false; } _targetContainer = val; _state = WispState.ToChest; LeaveResting(); Vector3 chestHoverPosition = GetChestHoverPosition(val); SaveVisualTarget('C', chestHoverPosition); ModConfig.DebugLog("Lamplighter: fetching " + _restockFuelName + " from " + ((Object)val).name); return true; } private void UpdateToChest() { //IL_0021: 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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_targetContainer == (Object)null) { HandleFailedChest(); return; } if (!IsInsideWorkRadius(((Component)_targetContainer).transform.position)) { HandleFailedChest(); return; } Vector3 chestHoverPosition = GetChestHoverPosition(_targetContainer); MoveWisp(chestHoverPosition); if (Vector3.Distance(_wisp.transform.position, chestHoverPosition) <= 0.35f) { _stateTimer = 0.6f; _state = WispState.AtChest; } } private void UpdateAtChest() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_targetContainer == (Object)null || string.IsNullOrEmpty(_restockFuelName)) { HandleFailedChest(); return; } Vector3 chestHoverPosition = GetChestHoverPosition(_targetContainer); BobAround(chestHoverPosition, 0.08f); _stateTimer -= Time.deltaTime; if (!(_stateTimer > 0f)) { string restockFuelName = _restockFuelName; int stackLimit = GetStackLimit(restockFuelName); int carried = GetCarried(restockFuelName); int num = Mathf.Max(0, stackLimit - carried); int num2 = 0; if (num > 0) { num2 = FuelService.TakeFuel(_targetContainer, restockFuelName, num); } if (num2 > 0) { _restockDidWork = true; SetCarried(restockFuelName, carried + num2); ModConfig.DebugLog($"Lamplighter: carrying {GetCarried(restockFuelName)}/{stackLimit} x {restockFuelName}"); } _targetContainer = null; if (GetCarried(restockFuelName) >= stackLimit || !FindContainerForCurrentFuel()) { _restockFuelName = null; BeginNextRestockFuel(); } } } private void HandleFailedChest() { _targetContainer = null; if (!FindContainerForCurrentFuel()) { _restockFuelName = null; BeginNextRestockFuel(); } } private void FinishRestockRun() { _targetContainer = null; _restockFuelName = null; _restockQueue.Clear(); _restockIndex = 0; _state = WispState.Idle; SaveVisualHome(); if (_restockDidWork) { ModConfig.DebugLog("Lamplighter: restock complete."); _nextScanTime = Time.time + 0.25f; } else { EnterResting(); } } private void UpdateToFire() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_targetFire == (Object)null) { FinishFireJob(); return; } if (!FireScanner.IsValidPlacedFireplace(_targetFire)) { FinishFireJob(); return; } if (!IsInsideWorkRadius(((Component)_targetFire).transform.position)) { FinishFireJob(); return; } string fuelItemName = FireScanner.GetFuelItemName(_targetFire); if (GetCarried(fuelItemName) <= 0) { FinishFireJob(); return; } if (!FireScanner.CanAcceptFuel(_targetFire)) { FinishFireJob(); return; } Vector3 fireHoverPosition = GetFireHoverPosition(_targetFire); MoveWisp(fireHoverPosition); if (Vector3.Distance(_wisp.transform.position, fireHoverPosition) <= 0.3f) { _stateTimer = 0.4f; _state = WispState.AtFire; } } private void UpdateAtFire() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_targetFire == (Object)null || !FireScanner.IsValidPlacedFireplace(_targetFire)) { FinishFireJob(); return; } Vector3 fireHoverPosition = GetFireHoverPosition(_targetFire); BobAround(fireHoverPosition, 0.08f); _stateTimer -= Time.deltaTime; if (_stateTimer > 0f) { return; } string fuelItemName = FireScanner.GetFuelItemName(_targetFire); int carried = GetCarried(fuelItemName); if (carried <= 0) { FinishFireJob(); return; } int num = FuelService.AddFuelToMax(_targetFire, carried); if (num > 0) { SetCarried(fuelItemName, carried - num); ModConfig.DebugLog($"Lamplighter: {GetCarried(fuelItemName)} x {fuelItemName} remaining"); } FinishFireJob(); } private void FinishFireJob() { _targetFire = null; _state = WispState.Idle; SaveVisualHome(); _nextScanTime = Time.time + 0.15f; } private void EnterResting() { _state = WispState.Idle; _nextScanTime = Time.time + 3f; SaveVisualHome(); if (!_isResting) { _isResting = true; ModConfig.DebugLog("Lamplighter: resting."); } } private void LeaveResting() { _isResting = false; } private void ResetWorkState() { _targetFire = null; _targetContainer = null; _restockFuelName = null; _restockQueue.Clear(); _restockIndex = 0; _restockDidWork = false; _state = WispState.Idle; _isResting = false; _nextScanTime = Time.time + 0.15f; } private int GetCarried(string fuelName) { if (string.IsNullOrEmpty(fuelName)) { return 0; } if (_inventory.TryGetValue(fuelName, out var value)) { return value; } return 0; } private void SetCarried(string fuelName, int amount) { if (string.IsNullOrEmpty(fuelName)) { return; } if (amount <= 0) { if (_inventory.Remove(fuelName)) { SaveInventoryToZdo(); } return; } int stackLimit = GetStackLimit(fuelName); int num = Mathf.Clamp(amount, 0, stackLimit); if (!_inventory.TryGetValue(fuelName, out var value) || value != num) { _inventory[fuelName] = num; SaveInventoryToZdo(); } } private int GetStackLimit(string fuelName) { if (_stackLimits.TryGetValue(fuelName, out var value)) { return Mathf.Max(1, value); } return 1; } private void SaveInventoryToZdo() { if ((Object)(object)_nview == (Object)null || !_nview.IsValid() || !_nview.IsOwner()) { return; } ZDO zDO = _nview.GetZDO(); if (zDO == null) { return; } StringBuilder stringBuilder = new StringBuilder(); List<string> list = new List<string>(_inventory.Keys); list.Sort(StringComparer.Ordinal); foreach (string item in list) { int carried = GetCarried(item); if (carried > 0) { int stackLimit = GetStackLimit(item); string value = Convert.ToBase64String(Encoding.UTF8.GetBytes(item)); if (stringBuilder.Length > 0) { stringBuilder.Append(';'); } stringBuilder.Append(value); stringBuilder.Append(','); stringBuilder.Append(carried); stringBuilder.Append(','); stringBuilder.Append(stackLimit); } } zDO.Set("com.g.lamplighter.carried_inventory", stringBuilder.ToString()); ModConfig.DebugLog($"Lamplighter: saved {_inventory.Count} carried fuel type(s)."); } private void LoadInventoryFromZdo() { if ((Object)(object)_nview == (Object)null || !_nview.IsValid()) { return; } ZDO zDO = _nview.GetZDO(); if (zDO == null) { return; } string text = zDO.GetString("com.g.lamplighter.carried_inventory", string.Empty); _inventory.Clear(); _stackLimits.Clear(); if (string.IsNullOrEmpty(text)) { return; } string[] array = text.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(new char[1] { ',' }); if (array2.Length != 3) { Logger.LogWarning((object)"Lamplighter: invalid saved inventory entry."); continue; } try { string text2 = Encoding.UTF8.GetString(Convert.FromBase64String(array2[0])); if (!int.TryParse(array2[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) || !int.TryParse(array2[2], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2)) { Logger.LogWarning((object)"Lamplighter: invalid saved inventory amount."); } else if (!string.IsNullOrEmpty(text2) && result > 0) { result2 = Mathf.Max(1, result2); result = Mathf.Clamp(result, 1, result2); _stackLimits[text2] = result2; _inventory[text2] = result; } } catch (FormatException) { Logger.LogWarning((object)"Lamplighter: invalid saved fuel name."); } } ModConfig.DebugLog($"Lamplighter: restored {_inventory.Count} carried fuel type(s)."); } private void SaveVisualHome() { if (!((Object)(object)_nview == (Object)null) && _nview.IsValid() && _nview.IsOwner()) { ZDO zDO = _nview.GetZDO(); if (zDO != null) { zDO.Set("com.g.lamplighter.visual_state", "H"); } } } private void SaveVisualTarget(char mode, Vector3 position) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_nview == (Object)null) && _nview.IsValid() && _nview.IsOwner()) { ZDO zDO = _nview.GetZDO(); if (zDO != null) { string text = string.Format(CultureInfo.InvariantCulture, "{0}|{1:R}|{2:R}|{3:R}", mode, position.x, position.y, position.z); zDO.Set("com.g.lamplighter.visual_state", text); } } } private void UpdateRemoteVisual() { //IL_003d: Unknown result type (might be due to invalid IL or missing references) if (Time.time >= _nextRemoteSyncTime) { _nextRemoteSyncTime = Time.time + 0.5f; LoadInventoryFromZdo(); LoadVisualStateFromZdo(); } if (_remoteVisualMode == 'H') { MoveHome(); } else { MoveWisp(_remoteVisualTarget); } } private void LoadVisualStateFromZdo() { //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_nview == (Object)null || !_nview.IsValid()) { return; } ZDO zDO = _nview.GetZDO(); if (zDO == null) { return; } string text = zDO.GetString("com.g.lamplighter.visual_state", "H"); if (string.IsNullOrEmpty(text) || text == "H") { _remoteVisualMode = 'H'; return; } string[] array = text.Split(new char[1] { '|' }); if (array.Length != 4 || string.IsNullOrEmpty(array[0])) { _remoteVisualMode = 'H'; return; } if (!float.TryParse(array[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || !float.TryParse(array[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2) || !float.TryParse(array[3], NumberStyles.Float, CultureInfo.InvariantCulture, out var result3)) { _remoteVisualMode = 'H'; return; } char c = array[0][0]; if (c != 'C' && c != 'F') { _remoteVisualMode = 'H'; return; } _remoteVisualMode = c; _remoteVisualTarget = new Vector3(result, result2, result3); } private bool IsInsideWorkRadius(Vector3 position) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) float value = ModConfig.WorkRadius.Value; Vector3 val = position - ((Component)this).transform.position; return ((Vector3)(ref val)).sqrMagnitude <= value * value; } private Vector3 GetChestHoverPosition(Container container) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) return ((Component)container).transform.position + Vector3.up * 1.1f; } private Vector3 GetFireHoverPosition(Fireplace fireplace) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)fireplace).transform.position; Vector3 val = ((Component)this).transform.position - position; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { val = Vector3.right; } ((Vector3)(ref val)).Normalize(); return position + val * 0.8f + Vector3.up * 0.7f; } private void MoveWisp(Vector3 destination) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) _wisp.transform.position = Vector3.MoveTowards(_wisp.transform.position, destination, 3.5f * Time.deltaTime); } private void BobAround(Vector3 center, float amount) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) float num = Time.time + _timeOffset; Vector3 destination = center + new Vector3(Mathf.Cos(num * 2f) * amount, Mathf.Sin(num * 2.5f) * amount, Mathf.Sin(num * 2f) * amount); MoveWisp(destination); } private void MoveHome() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) float num = Time.time + _timeOffset; Vector3 destination = ((Component)this).transform.position + new Vector3(Mathf.Cos(num * 0.65f) * 0.18f, 1.8f + Mathf.Sin(num * 1.5f) * 0.15f, Mathf.Sin(num * 0.65f) * 0.18f); MoveWisp(destination); } private void OnShrineDestroyed() { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) if (_inventoryReturned || (Object)(object)_nview == (Object)null || !_nview.IsValid() || !_nview.IsOwner()) { return; } _inventoryReturned = true; if (_inventory.Count == 0) { return; } Vector3 position = ((Component)this).transform.position + Vector3.up * 0.75f; foreach (KeyValuePair<string, int> item in new List<KeyValuePair<string, int>>(_inventory)) { if (item.Value > 0) { DropCarriedItem(item.Key, item.Value, position); } } _inventory.Clear(); SaveInventoryToZdo(); ModConfig.DebugLog("Lamplighter: returned carried inventory."); } private void DropCarriedItem(string sharedName, int amount, Vector3 position) { //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ObjectDB.instance == (Object)null || amount <= 0) { return; } if (!(ObjectDbItemsField?.GetValue(ObjectDB.instance) is List<GameObject> list)) { Logger.LogWarning((object)$"Lamplighter: couldn't return {amount} x {sharedName}; ObjectDB item list unavailable."); return; } GameObject val = null; ItemDrop val2 = null; foreach (GameObject item in list) { if (!((Object)(object)item == (Object)null)) { ItemDrop component = item.GetComponent<ItemDrop>(); if (!((Object)(object)component == (Object)null) && component.m_itemData != null && component.m_itemData.m_shared != null && !(component.m_itemData.m_shared.m_name != sharedName)) { val = item; val2 = component; break; } } } if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { Logger.LogWarning((object)$"Lamplighter: couldn't return {amount} x {sharedName}; item prefab not found."); return; } int num = Mathf.Max(1, val2.m_itemData.m_shared.m_maxStackSize); int num2 = amount; Vector3 val3 = default(Vector3); while (num2 > 0) { int num3 = Mathf.Min(num2, num); ItemData obj = val2.m_itemData.Clone(); obj.m_dropPrefab = val; ((Vector3)(ref val3))..ctor(Random.Range(-0.35f, 0.35f), 0f, Random.Range(-0.35f, 0.35f)); ItemDrop.DropItem(obj, num3, position + val3, Quaternion.Euler(0f, Random.Range(0f, 360f), 0f)); num2 -= num3; } } public string GetHoverName() { return "Lamplighter"; } public string GetHoverText() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("<color=orange>Lamplighter</color>"); stringBuilder.Append("\n"); stringBuilder.Append("Status: "); stringBuilder.Append(GetStatusText()); stringBuilder.Append("\n"); if (_inventory.Count == 0) { stringBuilder.Append("Carrying: Nothing"); return stringBuilder.ToString(); } stringBuilder.Append("Carrying:"); List<string> list = new List<string>(_inventory.Keys); list.Sort(); foreach (string item in list) { int carried = GetCarried(item); if (carried > 0) { int stackLimit = GetStackLimit(item); string value = item; if (Localization.instance != null) { value = Localization.instance.Localize(item); } stringBuilder.Append("\n"); stringBuilder.Append(value); stringBuilder.Append(": "); stringBuilder.Append(carried); stringBuilder.Append("/"); stringBuilder.Append(stackLimit); } } return stringBuilder.ToString(); } private string GetStatusText() { if ((Object)(object)_nview != (Object)null && _nview.IsValid() && !_nview.IsOwner()) { return _remoteVisualMode switch { 'C' => "Restocking", 'F' => "Working", _ => "Resting", }; } switch (_state) { case WispState.ToChest: case WispState.AtChest: return "Restocking"; case WispState.ToFire: case WispState.AtFire: return "Working"; default: if (!_isResting) { return "Looking for work"; } return "Resting"; } } private void OnDestroy() { if ((Object)(object)_wearNTear != (Object)null) { WearNTear wearNTear = _wearNTear; wearNTear.m_onDestroyed = (Action)Delegate.Remove(wearNTear.m_onDestroyed, new Action(OnShrineDestroyed)); } } } } namespace Lamplighter.Config { internal static class ModConfig { public static ConfigEntry<float> WorkRadius { get; private set; } public static ConfigEntry<int> RefillBelowPercent { get; private set; } public static ConfigEntry<Color> WispColor { get; private set; } public static ConfigEntry<Color> OozeColor { get; private set; } public static ConfigEntry<Color> ShrineColor { get; private set; } public static ConfigEntry<bool> TakeWoodFromWoodStacks { get; private set; } public static ConfigEntry<bool> DetailedLogging { get; private set; } public static ConfigEntry<bool> ShowRangeWhilePlacing { get; private set; } public static ConfigEntry<bool> ShowRangeOnHover { get; private set; } public static float RefillThreshold => (float)RefillBelowPercent.Value / 100f; public static void Bind(ConfigFile config) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Expected O, but got Unknown //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Expected O, but got Unknown WorkRadius = config.Bind<float>("Lamplighter", "Work Radius", 40f, new ConfigDescription("Maximum distance in meters for servicing fires and searching fuel containers.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 100f), new object[1] { AdminOnly() })); RefillBelowPercent = config.Bind<int>("Lamplighter", "Refill Below", 25, new ConfigDescription("Refill a fire when its fuel falls below this percentage.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), new object[1] { AdminOnly() })); TakeWoodFromWoodStacks = config.Bind<bool>("Lamplighter", "Take Wood From Wood Stacks", true, "Allow the Lamplighter to use placed Wood Stacks as a fuel source."); WispColor = config.Bind<Color>("Appearance", "Wisp Color", new Color(1f, 0.25f, 0.03f, 1f), "Color of the Lamplighter fire spirit."); OozeColor = config.Bind<Color>("Appearance", "Ooze Color", new Color(1f, 0.25f, 0.03f, 1f), "Color of the glowing flowing material on the Lamplighter shrine."); ShrineColor = config.Bind<Color>("Appearance", "Shrine Color", new Color(0.85f, 0.72f, 0.4f, 1f), "Color of the Lamplighter shrine structure."); DetailedLogging = config.Bind<bool>("Advanced", "Detailed Logging", false, "Log Lamplighter jobs, fuel transfers, restocking, and other diagnostic activity."); ShowRangeWhilePlacing = config.Bind<bool>("Advanced", "Show Range While Placing", true, new ConfigDescription("Show the Lamplighter work radius while placing it.", (AcceptableValueBase)null, new object[1] { Hidden() })); ShowRangeOnHover = config.Bind<bool>("Advanced", "Show Range On Hover", false, new ConfigDescription("Show the work radius while hovering over an existing Lamplighter.", (AcceptableValueBase)null, new object[1] { Hidden() })); } public static void DebugLog(string message) { if (DetailedLogging != null && DetailedLogging.Value) { Logger.LogInfo((object)message); } } private static ConfigurationManagerAttributes AdminOnly() { //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_000d: Expected O, but got Unknown return new ConfigurationManagerAttributes { IsAdminOnly = true }; } private static ConfigurationManagerAttributes Hidden() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown return new ConfigurationManagerAttributes { Browsable = false }; } } }