Decompiled source of FreeFuelSource v1.0.0

FreeFuelSource.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("FreeFuelSource")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0")]
[assembly: AssemblyProduct("FreeFuelSource")]
[assembly: AssemblyTitle("FreeFuelSource")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace FreeFuelSource
{
	[BepInPlugin("Moopfam.FreeFuelSource", "FreeFuelSource", "1.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "Moopfam.FreeFuelSource";

		public const string PluginName = "FreeFuelSource";

		public const string PluginVersion = "1.0";

		private const string SectionGeneral = "01 - General";

		private const string SectionFireSources = "02 - Fire Sources";

		private const string SectionLighting = "03 - Lighting";

		private const string SectionProductionFuel = "04 - Production Fuel";

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<bool> Campfires;

		internal static ConfigEntry<bool> Bonfires;

		internal static ConfigEntry<bool> Hearths;

		internal static ConfigEntry<bool> Fireplaces;

		internal static ConfigEntry<bool> OtherFireSources;

		internal static ConfigEntry<bool> Torches;

		internal static ConfigEntry<bool> Sconces;

		internal static ConfigEntry<bool> Braziers;

		internal static ConfigEntry<bool> Candles;

		internal static ConfigEntry<bool> JackOTurnip;

		internal static ConfigEntry<bool> Smelters;

		internal static ConfigEntry<bool> BlastFurnaces;

		internal static ConfigEntry<bool> CharcoalKilns;

		internal static ConfigEntry<bool> StoneOvens;

		internal static ConfigEntry<bool> EitrRefineries;

		internal static ConfigEntry<bool> OtherProductionFuelSources;

		internal static ManualLogSource Log;

		private Harmony _harmony;

		internal static FuelConfigSnapshot EffectiveSettings
		{
			get
			{
				if ((Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsServer() && VersionHandshake.ServerSettings != null)
				{
					return VersionHandshake.ServerSettings;
				}
				return LocalSnapshot();
			}
		}

		private void Awake()
		{
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Enabled = Bind("01 - General", "Enabled", defaultValue: true, "Master switch for FreeFuelSource. On multiplayer servers the server value is authoritative.");
			Campfires = Bind("02 - Fire Sources", "Campfires", defaultValue: true, "Basic Campfire / Fire Pit (fire_pit) and other campfire-named Fireplace sources.");
			Bonfires = Bind("02 - Fire Sources", "Bonfires", defaultValue: false, "Bonfire fuel is free.");
			Hearths = Bind("02 - Fire Sources", "Hearths", defaultValue: false, "Hearth fuel is free.");
			Fireplaces = Bind("02 - Fire Sources", "Fireplaces", defaultValue: false, "Other fireplace-named fire sources.");
			OtherFireSources = Bind("02 - Fire Sources", "OtherFireSources", defaultValue: false, "Make any other Fireplace component source fuel-free. Enable this for modded/unknown fire sources.");
			Torches = Bind("03 - Lighting", "Torches", defaultValue: true, "Torch fuel is free.");
			Sconces = Bind("03 - Lighting", "Sconces", defaultValue: true, "Sconce fuel is free.");
			Braziers = Bind("03 - Lighting", "Braziers", defaultValue: true, "Brazier fuel is free.");
			Candles = Bind("03 - Lighting", "Candles", defaultValue: true, "Candle-style Fireplace sources use free fuel.");
			JackOTurnip = Bind("03 - Lighting", "JackOTurnip", defaultValue: true, "Jack-o-Turnip-style lights use free fuel.");
			Smelters = Bind("04 - Production Fuel", "Smelters", defaultValue: false, "Standard Smelter coal is treated as unlimited.");
			BlastFurnaces = Bind("04 - Production Fuel", "BlastFurnaces", defaultValue: false, "Blast Furnace coal is treated as unlimited.");
			CharcoalKilns = Bind("04 - Production Fuel", "CharcoalKilns", defaultValue: false, "Charcoal Kiln fuel is treated as unlimited.");
			StoneOvens = Bind("04 - Production Fuel", "StoneOvens", defaultValue: false, "Stone Oven fuel is treated as unlimited.");
			EitrRefineries = Bind("04 - Production Fuel", "EitrRefineries", defaultValue: false, "Eitr Refinery fuel source is treated as unlimited where it uses Valheim's Smelter fuel system.");
			OtherProductionFuelSources = Bind("04 - Production Fuel", "OtherProductionFuelSources", defaultValue: false, "Treat other/modded Smelter-component fuel sources as unlimited.");
			_harmony = new Harmony("Moopfam.FreeFuelSource");
			_harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"FreeFuelSource 1.0 loaded. Multiplayer requires the same mod version on the server and every client.");
		}

		private ConfigEntry<bool> Bind(string section, string key, bool defaultValue, string description)
		{
			ConfigEntry<bool> val = ((BaseUnityPlugin)this).Config.Bind<bool>(section, key, defaultValue, description);
			val.SettingChanged += delegate
			{
				VersionHandshake.BroadcastServerState();
			};
			return val;
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		internal static FuelConfigSnapshot LocalSnapshot()
		{
			return new FuelConfigSnapshot
			{
				Enabled = Value(Enabled),
				Campfires = Value(Campfires),
				Bonfires = Value(Bonfires),
				Hearths = Value(Hearths),
				Fireplaces = Value(Fireplaces),
				OtherFireSources = Value(OtherFireSources),
				Torches = Value(Torches),
				Sconces = Value(Sconces),
				Braziers = Value(Braziers),
				Candles = Value(Candles),
				JackOTurnip = Value(JackOTurnip),
				Smelters = Value(Smelters),
				BlastFurnaces = Value(BlastFurnaces),
				CharcoalKilns = Value(CharcoalKilns),
				StoneOvens = Value(StoneOvens),
				EitrRefineries = Value(EitrRefineries),
				OtherProductionFuelSources = Value(OtherProductionFuelSources)
			};
		}

		private static bool Value(ConfigEntry<bool> entry)
		{
			return entry?.Value ?? false;
		}
	}
	internal sealed class FuelConfigSnapshot
	{
		internal bool Enabled;

		internal bool Campfires;

		internal bool Bonfires;

		internal bool Hearths;

		internal bool Fireplaces;

		internal bool OtherFireSources;

		internal bool Torches;

		internal bool Sconces;

		internal bool Braziers;

		internal bool Candles;

		internal bool JackOTurnip;

		internal bool Smelters;

		internal bool BlastFurnaces;

		internal bool CharcoalKilns;

		internal bool StoneOvens;

		internal bool EitrRefineries;

		internal bool OtherProductionFuelSources;

		internal void Write(ZPackage package)
		{
			package.Write(Enabled);
			package.Write(Campfires);
			package.Write(Bonfires);
			package.Write(Hearths);
			package.Write(Fireplaces);
			package.Write(OtherFireSources);
			package.Write(Torches);
			package.Write(Sconces);
			package.Write(Braziers);
			package.Write(Candles);
			package.Write(JackOTurnip);
			package.Write(Smelters);
			package.Write(BlastFurnaces);
			package.Write(CharcoalKilns);
			package.Write(StoneOvens);
			package.Write(EitrRefineries);
			package.Write(OtherProductionFuelSources);
		}

		internal static FuelConfigSnapshot Read(ZPackage package)
		{
			return new FuelConfigSnapshot
			{
				Enabled = package.ReadBool(),
				Campfires = package.ReadBool(),
				Bonfires = package.ReadBool(),
				Hearths = package.ReadBool(),
				Fireplaces = package.ReadBool(),
				OtherFireSources = package.ReadBool(),
				Torches = package.ReadBool(),
				Sconces = package.ReadBool(),
				Braziers = package.ReadBool(),
				Candles = package.ReadBool(),
				JackOTurnip = package.ReadBool(),
				Smelters = package.ReadBool(),
				BlastFurnaces = package.ReadBool(),
				CharcoalKilns = package.ReadBool(),
				StoneOvens = package.ReadBool(),
				EitrRefineries = package.ReadBool(),
				OtherProductionFuelSources = package.ReadBool()
			};
		}
	}
	internal static class VersionHandshake
	{
		internal const string RpcName = "Moopfam.FreeFuelSource.VersionCheck";

		private static readonly HashSet<ZRpc> ValidatedPeers = new HashSet<ZRpc>();

		private static readonly MethodInfo GetPeersMethod = AccessTools.Method(typeof(ZNet), "GetPeers", Type.EmptyTypes, (Type[])null);

		internal static FuelConfigSnapshot ServerSettings { get; private set; }

		internal static void RegisterAndSend(ZNetPeer peer)
		{
			if (peer != null && peer.m_rpc != null)
			{
				peer.m_rpc.Register<ZPackage>("Moopfam.FreeFuelSource.VersionCheck", (Action<ZRpc, ZPackage>)ReceiveVersion);
				SendState(peer);
			}
		}

		internal static bool IsValidated(ZRpc rpc)
		{
			return rpc != null && ValidatedPeers.Contains(rpc);
		}

		internal static void Reset()
		{
			ValidatedPeers.Clear();
			ServerSettings = null;
		}

		private static void ReceiveVersion(ZRpc rpc, ZPackage package)
		{
			if (rpc == null || package == null)
			{
				return;
			}
			string text = package.ReadString();
			FuelConfigSnapshot serverSettings = FuelConfigSnapshot.Read(package);
			if (!string.Equals(text, "1.0", StringComparison.OrdinalIgnoreCase))
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("FreeFuelSource: rejected peer with version " + text + ". Required version is 1.0."));
				}
				return;
			}
			ValidatedPeers.Add(rpc);
			if ((Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsServer())
			{
				ServerSettings = serverSettings;
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogInfo((object)("FreeFuelSource: server version/config validated (" + text + ")."));
				}
			}
			else
			{
				ManualLogSource log3 = Plugin.Log;
				if (log3 != null)
				{
					log3.LogInfo((object)("FreeFuelSource: client version validated (" + text + ")."));
				}
			}
		}

		private static void SendState(ZNetPeer peer)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			if (peer != null && peer.m_rpc != null)
			{
				ZPackage val = new ZPackage();
				val.Write("1.0");
				Plugin.LocalSnapshot().Write(val);
				peer.m_rpc.Invoke("Moopfam.FreeFuelSource.VersionCheck", new object[1] { val });
			}
		}

		internal static void BroadcastServerState()
		{
			try
			{
				ZNet instance = ZNet.instance;
				if ((Object)(object)instance == (Object)null || !instance.IsServer() || GetPeersMethod == null)
				{
					return;
				}
				object obj = GetPeersMethod.Invoke(instance, null);
				if (!(obj is IEnumerable enumerable))
				{
					return;
				}
				foreach (object item in enumerable)
				{
					ZNetPeer val = (ZNetPeer)((item is ZNetPeer) ? item : null);
					if (val != null)
					{
						SendState(val);
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("FreeFuelSource: could not broadcast server config: " + ex.Message));
				}
			}
		}

		internal static void RejectUnvalidatedPeer(ZNet znet, ZRpc rpc)
		{
			if ((Object)(object)znet == (Object)null || rpc == null)
			{
				return;
			}
			string text = (znet.IsServer() ? "client" : "server");
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogWarning((object)("FreeFuelSource: the " + text + " did not provide the required FreeFuelSource 1.0 handshake."));
			}
			if (znet.IsServer())
			{
				rpc.Invoke("Error", new object[1] { 3 });
				return;
			}
			FieldInfo fieldInfo = AccessTools.Field(typeof(ZNet), "m_connectionStatus");
			if (fieldInfo != null)
			{
				fieldInfo.SetValue(null, (object)(ConnectionStatus)3);
			}
			try
			{
				ISocket socket = rpc.GetSocket();
				if (socket != null)
				{
					socket.Close();
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("FreeFuelSource: failed to close incompatible connection: " + ex.Message));
				}
			}
		}
	}
	[HarmonyPatch(typeof(ZNet), "Awake")]
	internal static class ZNetAwakePatch
	{
		private static void Prefix()
		{
			VersionHandshake.Reset();
		}
	}
	[HarmonyPatch(typeof(ZNet), "OnNewConnection")]
	internal static class ZNetOnNewConnectionPatch
	{
		private static void Prefix(ZNetPeer peer)
		{
			VersionHandshake.RegisterAndSend(peer);
		}
	}
	[HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")]
	internal static class ZNetPeerInfoPatch
	{
		private static bool Prefix(ZNet __instance, ZRpc rpc)
		{
			if (VersionHandshake.IsValidated(rpc))
			{
				return true;
			}
			VersionHandshake.RejectUnvalidatedPeer(__instance, rpc);
			return false;
		}
	}
	internal static class FuelSourceClassifier
	{
		internal static string PrefabName(Component component)
		{
			if ((Object)(object)component == (Object)null || (Object)(object)component.gameObject == (Object)null)
			{
				return string.Empty;
			}
			return (((Object)component.gameObject).name ?? string.Empty).Replace("(Clone)", string.Empty).Trim();
		}

		internal static bool IsFireplaceEnabled(Fireplace fireplace)
		{
			FuelConfigSnapshot effectiveSettings = Plugin.EffectiveSettings;
			if (!effectiveSettings.Enabled || (Object)(object)fireplace == (Object)null)
			{
				return false;
			}
			string value = PrefabName((Component)(object)fireplace);
			if (EqualsName(value, "fire_pit"))
			{
				return effectiveSettings.Campfires;
			}
			if (Contains(value, "jackoturnip"))
			{
				return effectiveSettings.JackOTurnip;
			}
			if (Contains(value, "torch"))
			{
				return effectiveSettings.Torches;
			}
			if (Contains(value, "sconce"))
			{
				return effectiveSettings.Sconces;
			}
			if (Contains(value, "brazier"))
			{
				return effectiveSettings.Braziers;
			}
			if (Contains(value, "candle"))
			{
				return effectiveSettings.Candles;
			}
			if (Contains(value, "bonfire"))
			{
				return effectiveSettings.Bonfires;
			}
			if (Contains(value, "hearth"))
			{
				return effectiveSettings.Hearths;
			}
			if (Contains(value, "campfire"))
			{
				return effectiveSettings.Campfires;
			}
			if (Contains(value, "fireplace"))
			{
				return effectiveSettings.Fireplaces;
			}
			return effectiveSettings.OtherFireSources;
		}

		internal static bool IsSmelterEnabled(Smelter smelter)
		{
			FuelConfigSnapshot effectiveSettings = Plugin.EffectiveSettings;
			if (!effectiveSettings.Enabled || (Object)(object)smelter == (Object)null)
			{
				return false;
			}
			string value = PrefabName((Component)(object)smelter);
			if (Contains(value, "blast") && Contains(value, "furnace"))
			{
				return effectiveSettings.BlastFurnaces;
			}
			if (Contains(value, "charcoal") || Contains(value, "kiln"))
			{
				return effectiveSettings.CharcoalKilns;
			}
			if (Contains(value, "oven"))
			{
				return effectiveSettings.StoneOvens;
			}
			if (Contains(value, "eitr") || Contains(value, "refinery"))
			{
				return effectiveSettings.EitrRefineries;
			}
			if (Contains(value, "smelter"))
			{
				return effectiveSettings.Smelters;
			}
			return effectiveSettings.OtherProductionFuelSources;
		}

		private static bool EqualsName(string value, string text)
		{
			return string.Equals(value, text, StringComparison.OrdinalIgnoreCase);
		}

		private static bool Contains(string value, string text)
		{
			return value.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0;
		}
	}
	[HarmonyPatch(typeof(Fireplace), "Awake")]
	internal static class FireplaceAwakePatch
	{
		private static void Postfix(Fireplace __instance)
		{
			FireplaceFuelController.Apply(__instance);
		}
	}
	[HarmonyPatch(typeof(Fireplace), "UpdateFireplace")]
	internal static class FireplaceUpdatePatch
	{
		private static void Prefix(Fireplace __instance)
		{
			FireplaceFuelController.Apply(__instance);
		}
	}
	internal static class FireplaceFuelController
	{
		private static readonly FieldInfo InfiniteFuelField = AccessTools.Field(typeof(Fireplace), "m_infiniteFuel");

		internal static void Apply(Fireplace fireplace)
		{
			if (!((Object)(object)fireplace == (Object)null) && !(InfiniteFuelField == null))
			{
				InfiniteFuelField.SetValue(fireplace, FuelSourceClassifier.IsFireplaceEnabled(fireplace));
			}
		}
	}
	[HarmonyPatch]
	internal static class SmelterGetFuelPatch
	{
		private static readonly FieldInfo MaxFuelField = AccessTools.Field(typeof(Smelter), "m_maxFuel");

		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(Smelter), "GetFuel", Type.EmptyTypes, (Type[])null);
		}

		private static void Postfix(Smelter __instance, ref float __result)
		{
			if (!FuelSourceClassifier.IsSmelterEnabled(__instance) || MaxFuelField == null)
			{
				return;
			}
			try
			{
				object value = MaxFuelField.GetValue(__instance);
				if (value != null)
				{
					float num = Convert.ToSingle(value);
					if (num > __result)
					{
						__result = num;
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("FreeFuelSource: failed to override production fuel: " + ex.Message));
				}
			}
		}
	}
}