using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Digitalroot.Valheim.Common;
using Digitalroot.Valheim.Common.Json;
using HarmonyLib;
using JetBrains.Annotations;
using Jotunn.Utils;
using SimpleJson;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Digitalroot.ValheimEternalFire")]
[assembly: AssemblyDescription("Eternal Fire")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Digitalroot Technologies")]
[assembly: AssemblyProduct("Digitalroot Valheim Mods")]
[assembly: AssemblyCopyright("Copyright © Digitalroot Technologies 2021 - 2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("3ccc4dc1-5b17-47c1-b996-ca03b8639a61")]
[assembly: AssemblyFileVersion("1.0.14")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.14.0")]
[module: UnverifiableCode]
namespace Digitalroot.Valheim.EternalFire
{
[BepInPlugin("digitalroot.mods.eternalfire", "Eternal Fire", "1.0.14")]
[BepInDependency("com.jotunn.jotunn", "2.11.5")]
[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
public class Main : BaseUnityPlugin, ITraceableLogging
{
internal static class PluginConfigSection
{
internal static string General = "General";
internal static string Fireplaces = "Fireplaces";
internal static string CookingStations = "CookingStations";
internal static string Smelters = "Smelters";
internal static string Custom = "Custom";
}
private Harmony _harmony;
public static Main Instance;
private static ConfigEntry<bool> config_fire_pit;
private static ConfigEntry<bool> config_iron_fire_pit;
private static ConfigEntry<bool> config_bonfire;
private static ConfigEntry<bool> config_hearth;
private static ConfigEntry<bool> config_piece_walltorch;
private static ConfigEntry<bool> config_piece_groundtorch;
private static ConfigEntry<bool> config_piece_groundtorch_wood;
private static ConfigEntry<bool> config_piece_groundtorch_green;
private static ConfigEntry<bool> config_piece_groundtorch_blue;
private static ConfigEntry<bool> config_piece_brazierfloor01;
private static ConfigEntry<bool> config_piece_brazierfloor02;
private static ConfigEntry<bool> config_piece_brazierceiling01;
private static ConfigEntry<bool> config_piece_jackoturnip;
private static ConfigEntry<bool> config_piece_oven;
private static ConfigEntry<bool> config_smelter;
private static ConfigEntry<bool> config_blastfurnace;
private static ConfigEntry<bool> config_eitrrefinery;
private static ConfigEntry<bool> config_piece_bathtub;
private static ConfigEntry<string> config_custom_instance;
public const string Version = "1.0.14";
public const string Name = "Eternal Fire";
public const string Guid = "digitalroot.mods.eternalfire";
public const string Namespace = "Digitalroot.ValheimEternalFire";
public static ConfigEntry<int> NexusId { get; private set; }
public string Source => "Digitalroot.ValheimEternalFire";
public bool EnableTrace { get; }
public Main()
{
Instance = this;
EnableTrace = false;
Log.Trace(Instance, "Digitalroot.ValheimEternalFire." + MethodBase.GetCurrentMethod()?.DeclaringType?.Name + "." + MethodBase.GetCurrentMethod()?.Name);
}
[UsedImplicitly]
private void Awake()
{
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Expected O, but got Unknown
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Expected O, but got Unknown
try
{
Log.Trace(Instance, "Digitalroot.ValheimEternalFire." + MethodBase.GetCurrentMethod()?.DeclaringType?.Name + "." + MethodBase.GetCurrentMethod()?.Name);
NexusId = ((BaseUnityPlugin)this).Config.Bind<int>(PluginConfigSection.General, "NexusID", 2754, new ConfigDescription("Nexus mod ID for updates", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
{
Browsable = false,
ReadOnly = true
} }));
config_fire_pit = ((BaseUnityPlugin)this).Config.Bind<bool>(PluginConfigSection.Fireplaces, "CampFire", true, "Enable Campfire");
config_iron_fire_pit = ((BaseUnityPlugin)this).Config.Bind<bool>(PluginConfigSection.Fireplaces, "IronFirePit", true, "Enable Iron Fire Pit");
config_bonfire = ((BaseUnityPlugin)this).Config.Bind<bool>(PluginConfigSection.Fireplaces, "Bonfire", true, "Enable Bonfire");
config_piece_walltorch = ((BaseUnityPlugin)this).Config.Bind<bool>(PluginConfigSection.Fireplaces, "Sconce", true, "Enable Sconce");
config_piece_groundtorch = ((BaseUnityPlugin)this).Config.Bind<bool>(PluginConfigSection.Fireplaces, "StandingIronTorch", true, "Enable Standing Iron Torch");
config_piece_groundtorch_wood = ((BaseUnityPlugin)this).Config.Bind<bool>(PluginConfigSection.Fireplaces, "StandingWoodTorch", true, "Enable Standing Wood Torch");
config_piece_groundtorch_green = ((BaseUnityPlugin)this).Config.Bind<bool>(PluginConfigSection.Fireplaces, "StandingGreenBurningIronTorch", true, "Enable Standing Green Burning Iron Torch");
config_piece_groundtorch_blue = ((BaseUnityPlugin)this).Config.Bind<bool>(PluginConfigSection.Fireplaces, "StandingBlueBurningIronTorch", true, "Enable Standing Blue Burning Iron Torch");
config_piece_brazierfloor01 = ((BaseUnityPlugin)this).Config.Bind<bool>(PluginConfigSection.Fireplaces, "StandingBrazier", true, "Enable Standing Brazier");
config_piece_brazierfloor02 = ((BaseUnityPlugin)this).Config.Bind<bool>(PluginConfigSection.Fireplaces, "StandingBlueBrazier", true, "Enable Standing Blue Brazier");
config_piece_brazierceiling01 = ((BaseUnityPlugin)this).Config.Bind<bool>(PluginConfigSection.Fireplaces, "HangingBrazier", true, "Enable Hanging Brazier");
config_piece_jackoturnip = ((BaseUnityPlugin)this).Config.Bind<bool>(PluginConfigSection.Fireplaces, "JackOTurnip", true, "Enable Jack-o-Turnip");
config_hearth = ((BaseUnityPlugin)this).Config.Bind<bool>(PluginConfigSection.Fireplaces, "Hearth", true, "Enable Hearth");
config_piece_bathtub = ((BaseUnityPlugin)this).Config.Bind<bool>(PluginConfigSection.Fireplaces, "HotTub", true, "Enable Hot Tub");
config_piece_oven = ((BaseUnityPlugin)this).Config.Bind<bool>(PluginConfigSection.CookingStations, "StoneOven", true, "Enable Stone Oven");
config_smelter = ((BaseUnityPlugin)this).Config.Bind<bool>(PluginConfigSection.Smelters, "Smelter", false, "Enable Smelter");
config_blastfurnace = ((BaseUnityPlugin)this).Config.Bind<bool>(PluginConfigSection.Smelters, "BlastFurnace", false, "Enable Blast Furnace");
config_eitrrefinery = ((BaseUnityPlugin)this).Config.Bind<bool>(PluginConfigSection.Smelters, "EitrRefinery", false, "Enable Eitr Refinery");
config_custom_instance = ((BaseUnityPlugin)this).Config.Bind<string>(PluginConfigSection.Custom, "CustomPrefabs", "", "A comma-separated list of prefab names");
_harmony = Harmony.CreateAndPatchAll(typeof(Main).Assembly, "digitalroot.mods.eternalfire");
}
catch (Exception e)
{
Log.Error(Instance, e);
}
}
[UsedImplicitly]
private void OnDestroy()
{
try
{
Log.Trace(Instance, "Digitalroot.ValheimEternalFire." + MethodBase.GetCurrentMethod()?.DeclaringType?.Name + "." + MethodBase.GetCurrentMethod()?.Name);
Harmony harmony = _harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
}
catch (Exception e)
{
Log.Error(Instance, e);
}
}
public static async void Refuel(ZNetView znview)
{
await Task.Delay(33);
znview.InvokeRPC("AddFuel", Array.Empty<object>());
}
public static bool ConfigCheck(string instanceName)
{
bool result = false;
switch (instanceName.Replace("(Clone)", string.Empty))
{
case "fire_pit":
result = config_fire_pit.Value;
break;
case "fire_pit_iron":
result = config_iron_fire_pit.Value;
break;
case "bonfire":
result = config_bonfire.Value;
break;
case "hearth":
result = config_hearth.Value;
break;
case "piece_walltorch":
result = config_piece_walltorch.Value;
break;
case "piece_groundtorch":
result = config_piece_groundtorch.Value;
break;
case "piece_groundtorch_wood":
result = config_piece_groundtorch_wood.Value;
break;
case "piece_groundtorch_green":
result = config_piece_groundtorch_green.Value;
break;
case "piece_groundtorch_blue":
result = config_piece_groundtorch_blue.Value;
break;
case "piece_brazierfloor01":
result = config_piece_brazierfloor01.Value;
break;
case "piece_brazierfloor02":
result = config_piece_brazierfloor02.Value;
break;
case "piece_brazierceiling01":
result = config_piece_brazierceiling01.Value;
break;
case "piece_jackoturnip":
result = config_piece_jackoturnip.Value;
break;
case "piece_oven":
result = config_piece_oven.Value;
break;
case "smelter":
result = config_smelter.Value;
break;
case "blastfurnace":
result = config_blastfurnace.Value;
break;
case "eitrrefinery":
result = config_eitrrefinery.Value;
break;
case "piece_bathtub":
result = config_piece_bathtub.Value;
break;
}
if (config_custom_instance.Value.Split(new char[1] { ',' }).Contains(instanceName.Remove(instanceName.Length - 7)))
{
result = true;
}
return result;
}
}
[UsedImplicitly]
public class Patch
{
[HarmonyPatch]
public class PatchFireplaceUpdateFireplace
{
[HarmonyPrefix]
[HarmonyPatch(typeof(Fireplace), "UpdateFireplace")]
private static void Prefix(ref Fireplace __instance, ref ZNetView ___m_nview)
{
if (Main.ConfigCheck(((Object)__instance).name))
{
___m_nview.GetZDO().Set("fuel", __instance.m_maxFuel);
}
}
}
[HarmonyPatch]
public class PatchCookingStationSetFuel
{
[HarmonyPrefix]
[HarmonyPatch(typeof(CookingStation), "SetFuel")]
private static void Prefix(ref CookingStation __instance, ref float fuel)
{
if (Main.ConfigCheck(((Object)__instance).name))
{
fuel = __instance.m_maxFuel;
}
}
}
[HarmonyPatch]
public class PatchCookingStationAwake
{
[HarmonyPostfix]
[HarmonyPatch(typeof(CookingStation), "Awake")]
private static void Postfix(ref CookingStation __instance, ref ZNetView ___m_nview)
{
if (((Behaviour)___m_nview).isActiveAndEnabled && !((Object)(object)Player.m_localPlayer == (Object)null) && !((Character)Player.m_localPlayer).IsTeleporting() && Main.ConfigCheck(((Object)__instance).name))
{
Main.Refuel(___m_nview);
}
}
}
[HarmonyPatch]
public class PatchSmelterSetFuel
{
[HarmonyPrefix]
[HarmonyPatch(typeof(Smelter), "SetFuel")]
private static void Prefix(ref Smelter __instance, ref float fuel)
{
if (Main.ConfigCheck(((Object)__instance).name))
{
fuel = __instance.m_maxFuel;
}
}
}
[HarmonyPatch]
public class PatchSmelterAwake
{
[HarmonyPostfix]
[HarmonyPatch(typeof(Smelter), "Awake")]
private static void Postfix(ref Smelter __instance, ref ZNetView ___m_nview)
{
if (((Behaviour)___m_nview).isActiveAndEnabled && !((Object)(object)Player.m_localPlayer == (Object)null) && !((Character)Player.m_localPlayer).IsTeleporting() && Main.ConfigCheck(((Object)__instance).name))
{
Main.Refuel(___m_nview);
}
}
}
}
}
namespace Digitalroot.Valheim.Common
{
internal interface ITraceableLogging
{
string Source { get; }
bool EnableTrace { get; }
}
internal sealed class Log
{
private static readonly Dictionary<string, TraceLogger> TraceLoggers;
[UsedImplicitly]
private static Log Instance { get; }
static Log()
{
TraceLoggers = new Dictionary<string, TraceLogger>();
Instance = new Log();
}
private Log()
{
TraceLoggers.Add("Digitalroot", new TraceLogger("Digitalroot", enableTrace: false));
}
public static void RegisterSource(ITraceableLogging sender)
{
if ((!TraceLoggers.ContainsKey(sender.Source) || TraceLoggers[sender.Source].IsTraceEnabled != sender.EnableTrace) && (!TraceLoggers.ContainsKey(sender.Source) || sender.EnableTrace))
{
if (TraceLoggers.ContainsKey(sender.Source) && sender.EnableTrace)
{
TraceLoggers[sender.Source].EnableTrace();
}
else
{
TraceLoggers.Add(sender.Source, new TraceLogger(sender.Source, sender.EnableTrace));
}
}
}
private static TraceLogger GetTraceLogger(ITraceableLogging sender)
{
if (!TraceLoggers.ContainsKey(sender.Source))
{
return TraceLoggers["Digitalroot"];
}
return TraceLoggers[sender.Source];
}
[UsedImplicitly]
public static void SetEnableTrace(ITraceableLogging sender, bool value)
{
if (value)
{
GetTraceLogger(sender).EnableTrace();
}
else
{
GetTraceLogger(sender).DisableTrace();
}
}
[UsedImplicitly]
public static void SetEnableTraceForAllLoggers(bool value)
{
foreach (TraceLogger value2 in TraceLoggers.Values)
{
if (value)
{
value2.EnableTrace();
}
else
{
value2.DisableTrace();
}
}
}
[UsedImplicitly]
public static void Debug(ITraceableLogging sender, object value)
{
GetTraceLogger(sender).LoggerRef.LogDebug(value);
}
[UsedImplicitly]
public static void Error(ITraceableLogging sender, Exception e, int i = 1)
{
Error(sender, "Message: " + e.Message);
Error(sender, $"TargetSite: {e.TargetSite}");
Error(sender, "StackTrace: " + e.StackTrace);
Error(sender, "Source: " + e.Source);
if (e.Data.Count > 0)
{
foreach (object key in e.Data.Keys)
{
Error(sender, $"key: {key}, value: {e.Data[key]}");
}
}
if (e.InnerException != null)
{
Error(sender, $"--- InnerException [{i}][Start] ---");
Error(sender, e.InnerException, ++i);
}
}
[UsedImplicitly]
public static void Error(ITraceableLogging sender, object value)
{
GetTraceLogger(sender).LoggerRef.LogError(value);
}
[UsedImplicitly]
public static void Info(ITraceableLogging sender, object value)
{
GetTraceLogger(sender).LoggerRef.LogInfo(value);
}
[UsedImplicitly]
public static void Fatal(ITraceableLogging sender, Exception e, int i = 1)
{
Fatal(sender, "Message: " + e.Message);
Fatal(sender, $"TargetSite: {e.TargetSite}");
Fatal(sender, "StackTrace: " + e.StackTrace);
Fatal(sender, "Source: " + e.Source);
if (e.Data.Count > 0)
{
foreach (object key in e.Data.Keys)
{
Fatal(sender, $"key: {key}, value: {e.Data[key]}");
}
}
if (e.InnerException != null)
{
Fatal(sender, $"--- InnerException [{i}][Start] ---");
Fatal(sender, e.InnerException, ++i);
}
}
[UsedImplicitly]
public static void Fatal(ITraceableLogging sender, object value)
{
GetTraceLogger(sender).LoggerRef.LogFatal(value);
}
[UsedImplicitly]
public static void Message(ITraceableLogging sender, object value)
{
GetTraceLogger(sender).LoggerRef.LogMessage(value);
}
[UsedImplicitly]
public static void Trace(ITraceableLogging sender, object value)
{
if (GetTraceLogger(sender).IsTraceEnabled || sender.EnableTrace)
{
GetTraceLogger(sender).LoggerRef.Log((LogLevel)63, value);
}
}
[UsedImplicitly]
public static void Warning(ITraceableLogging sender, object value)
{
GetTraceLogger(sender).LoggerRef.LogWarning(value);
}
}
internal class TraceLogger
{
internal readonly ManualLogSource LoggerRef;
private readonly string _source;
private readonly FileInfo _traceFileInfo;
public bool IsTraceEnabled { get; private set; }
private DirectoryInfo AssemblyDirectory => new FileInfo(Uri.UnescapeDataString(new UriBuilder(Assembly.GetExecutingAssembly().CodeBase).Path)).Directory;
public TraceLogger(string source, bool enableTrace)
{
_source = source;
IsTraceEnabled = enableTrace;
LoggerRef = Logger.CreateLogSource(_source);
_traceFileInfo = new FileInfo(Path.Combine(Paths.BepInExRootPath ?? AssemblyDirectory.FullName, "logs", _source + ".Trace.log"));
if (_traceFileInfo.DirectoryName != null)
{
Directory.CreateDirectory(_traceFileInfo.DirectoryName);
}
if (_traceFileInfo.Exists)
{
_traceFileInfo.Delete();
_traceFileInfo.Refresh();
}
LoggerRef.LogEvent += OnLogEvent;
}
public void EnableTrace()
{
IsTraceEnabled = true;
}
public void DisableTrace()
{
IsTraceEnabled = false;
}
[UsedImplicitly]
public void StopTrace()
{
LoggerRef.LogEvent -= OnLogEvent;
}
private void OnLogEvent(object sender, LogEventArgs e)
{
//IL_00b0: 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)
if (e.Source.SourceName != _source || !IsTraceEnabled)
{
return;
}
using Mutex mutex = new Mutex(initiallyOwned: false, "Digitalroot.Valheim.Common.TraceLogger." + _source);
mutex.WaitOne();
try
{
if (e.Data is string)
{
string contents = $"[{e.Level,-7}:{e.Source.SourceName,10}] {e.Data}{Environment.NewLine}";
File.AppendAllText(_traceFileInfo.FullName, contents, Encoding.UTF8);
}
else
{
string contents2 = $"[{e.Level,-7}:{e.Source.SourceName,10}] {JsonSerializationProvider.Serialize(e.Data)}{Environment.NewLine}";
File.AppendAllText(_traceFileInfo.FullName, contents2, Encoding.UTF8);
}
}
finally
{
mutex.ReleaseMutex();
}
}
}
}
namespace Digitalroot.Valheim.Common.Json
{
[UsedImplicitly]
internal static class JsonSerializationProvider
{
[Obsolete("Use Deserialize<T>()")]
public static T FromJson<T>(string json)
{
return Deserialize<T>(json);
}
public static T Deserialize<T>(string json)
{
return SimpleJson.DeserializeObject<T>(json, (IJsonSerializerStrategy)(object)new DigitalrootJsonSerializerStrategy());
}
[Obsolete("Use Serialize()")]
public static string ToJson(object obj, bool pretty = false)
{
return Serialize(obj);
}
public static string Serialize(object obj)
{
return SimpleJson.SerializeObject(obj, (IJsonSerializerStrategy)(object)new DigitalrootJsonSerializerStrategy());
}
}
internal class DigitalrootJsonSerializerStrategy : PocoJsonSerializerStrategy
{
public override bool TrySerializeNonPrimitiveObject(object input, out object output)
{
//IL_0009: 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_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: 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_0059: 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_006b: Unknown result type (might be due to invalid IL or missing references)
if (!(input is Vector3 val))
{
if (input is Quaternion val2)
{
output = new float[4] { val2.x, val2.y, val2.z, val2.w };
return true;
}
return ((PocoJsonSerializerStrategy)this).TrySerializeNonPrimitiveObject(input, ref output);
}
output = new float[3] { val.x, val.y, val.z };
return true;
}
public override object DeserializeObject(object value, Type type)
{
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
//IL_0102: Unknown result type (might be due to invalid IL or missing references)
if (type == null)
{
throw new ArgumentNullException("type");
}
if (value == null)
{
throw new ArgumentNullException("value");
}
if (value is string value2)
{
if (string.IsNullOrWhiteSpace(value2))
{
throw new ArgumentNullException("value");
}
if (type == typeof(Vector3))
{
if (!(((PocoJsonSerializerStrategy)this).DeserializeObject(value, typeof(float[])) is float[] array) || (array != null && array.Length != 3))
{
throw new ArgumentException(string.Format("The value '{0}' can be converted to a {1}.", value, "Vector3"), "value");
}
return (object)new Vector3(array[0], array[1], array[2]);
}
if (type == typeof(Quaternion))
{
if (!(((PocoJsonSerializerStrategy)this).DeserializeObject(value, typeof(float[])) is float[] array2) || (array2 != null && array2.Length != 4))
{
throw new ArgumentException(string.Format("The value '{0}' can be converted to a {1}.", value, "Quaternion"), "value");
}
return (object)new Quaternion(array2[0], array2[1], array2[2], array2[3]);
}
return ((PocoJsonSerializerStrategy)this).DeserializeObject(value, type);
}
throw new ArgumentException($"The value '{value}' can be converted to a {type.Name}.", "value");
}
}
}
internal class DigitalrootValheimEternalFire_ProcessedByFody
{
internal const string FodyVersion = "6.6.0.0";
internal const string ILMerge = "1.22.0.0";
}