Decompiled source of SurtlingFuelItemHopperFix v1.0.0

SurtlingFuelItemHopperFix.dll

Decompiled 2 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;
using ValheimHopper.Logic;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("SurtlingFuelItemHopperFix")]
[assembly: AssemblyDescription("Compatibility bridge for SurtlingFuel and ItemHopper")]
[assembly: AssemblyProduct("SurtlingFuelItemHopperFix")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[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 SurtlingFuelItemHopperFix
{
	[BepInPlugin("local.valheim.surtlingfuelitemhopperfix", "SurtlingFuel ItemHopper Fix", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency("com.jotunn.jotunn", "2.29.2")]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "local.valheim.surtlingfuelitemhopperfix";

		public const string PluginName = "SurtlingFuel ItemHopper Fix";

		public const string PluginVersion = "1.0.0";

		public const string SurtlingFuelGuid = "com.dejan.surtlingfuel";

		public const string ItemHopperGuid = "com.maxsch.valheim.ItemHopper";

		internal const string SurtlingCorePrefab = "SurtlingCore";

		internal const string CoalPrefab = "Coal";

		internal const string CoreFuelRpc = "RPC_SurtlingFuel_AddCoreFuel";

		internal const string CoreFuelZdoKeyName = "SurtlingFuel_CoreFuel";

		internal static readonly int CoreFuelZdoKey = StringExtensionMethods.GetStableHashCode("SurtlingFuel_CoreFuel");

		internal static ConfigEntry<string> AdditionalFuelPrefabs;

		internal static ManualLogSource Log;

		private static HashSet<string> _alternativeFuelPrefabs = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "SurtlingCore" };

		private static MethodInfo _getFuelPerCore;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			ConfigurationManagerAttributes val = new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			};
			AdditionalFuelPrefabs = ((BaseUnityPlugin)this).Config.Bind<string>("Fuel", "Additional Fuel Prefabs", "BlackCore", new ConfigDescription("Comma-, semicolon-, or line-separated prefab names that ItemHopper may feed as SurtlingFuel core fuel. SurtlingCore is always enabled. Coal is always ignored. Every listed item receives SurtlingFuel's configured fuel value and speed boost. [Synced with Server]", (AcceptableValueBase)null, new object[1] { val }));
			RebuildAlternativeFuelSet();
			AdditionalFuelPrefabs.SettingChanged += OnFuelListChanged;
			Type type = AccessTools.TypeByName("SurtlingFuel.SurtlingFuelPlugin");
			_getFuelPerCore = ((type == null) ? null : AccessTools.Method(type, "GetFuelPerCore", new Type[1] { typeof(Smelter) }, (Type[])null));
			if (_getFuelPerCore == null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"SurtlingFuel.GetFuelPerCore was not found. The compatibility patch was not installed, so no hopper items will be consumed incorrectly.");
				return;
			}
			_harmony = new Harmony("local.valheim.surtlingfuelitemhopperfix");
			_harmony.PatchAll(typeof(Plugin).Assembly);
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Loaded SurtlingFuel ItemHopper Fix 1.0.0. Alternative hopper fuels: " + string.Join(", ", _alternativeFuelPrefabs) + "."));
		}

		private void OnDestroy()
		{
			if (AdditionalFuelPrefabs != null)
			{
				AdditionalFuelPrefabs.SettingChanged -= OnFuelListChanged;
			}
			if (_harmony != null)
			{
				_harmony.UnpatchSelf();
			}
		}

		private static void OnFuelListChanged(object sender, EventArgs eventArgs)
		{
			RebuildAlternativeFuelSet();
			Log.LogInfo((object)("Updated alternative hopper fuels: " + string.Join(", ", _alternativeFuelPrefabs) + "."));
		}

		private static void RebuildAlternativeFuelSet()
		{
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "SurtlingCore" };
			string[] array = ((AdditionalFuelPrefabs == null) ? string.Empty : AdditionalFuelPrefabs.Value).Split(new char[4] { ',', ';', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (text.Length != 0)
				{
					if (string.Equals(text, "Coal", StringComparison.OrdinalIgnoreCase))
					{
						Log.LogWarning((object)"Ignored Coal in Additional Fuel Prefabs; vanilla coal must use ItemHopper's normal fuel RPC.");
					}
					else
					{
						hashSet.Add(text);
					}
				}
			}
			_alternativeFuelPrefabs = hashSet;
		}

		internal static bool IsAlternativeFuel(ItemData item)
		{
			if (item == null)
			{
				return false;
			}
			if ((Object)(object)item.m_dropPrefab != (Object)null && _alternativeFuelPrefabs.Contains(((Object)item.m_dropPrefab).name))
			{
				return true;
			}
			string a = ((item.m_shared == null) ? null : item.m_shared.m_name);
			if (string.Equals(a, "$item_surtlingcore", StringComparison.Ordinal))
			{
				return true;
			}
			if (_alternativeFuelPrefabs.Contains("BlackCore"))
			{
				return string.Equals(a, "$item_blackcore", StringComparison.Ordinal);
			}
			return false;
		}

		internal static bool IsCoalPowered(Smelter smelter)
		{
			if ((Object)(object)smelter == (Object)null || (Object)(object)smelter.m_fuelItem == (Object)null || smelter.m_fuelItem.m_itemData == null)
			{
				return false;
			}
			ItemData itemData = smelter.m_fuelItem.m_itemData;
			if ((Object)(object)itemData.m_dropPrefab != (Object)null && string.Equals(((Object)itemData.m_dropPrefab).name, "Coal", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			if (itemData.m_shared != null)
			{
				return string.Equals(itemData.m_shared.m_name, "$item_coal", StringComparison.Ordinal);
			}
			return false;
		}

		internal static bool IsCoreFuelActive(Smelter smelter)
		{
			if (TryReadFuelState(smelter, out var _, out var _, out var coreFuel))
			{
				return coreFuel > 0;
			}
			return false;
		}

		internal static bool CanAcceptAlternativeFuel(Smelter smelter)
		{
			if (!IsCoalPowered(smelter))
			{
				return false;
			}
			if (!TryReadFuelState(smelter, out var _, out var fuel, out var coreFuel))
			{
				return false;
			}
			bool num = fuel > 0.01f && coreFuel <= 0;
			bool flag = fuel <= (float)smelter.m_maxFuel - 1f;
			return !num && flag;
		}

		internal static bool TryAddAlternativeFuel(Smelter smelter, ItemData item, Inventory source)
		{
			if (source == null || !CanAcceptAlternativeFuel(smelter))
			{
				return false;
			}
			if (!TryReadFuelState(smelter, out var _, out var fuel, out var _))
			{
				return false;
			}
			int val;
			try
			{
				val = (int)_getFuelPerCore.Invoke(null, new object[1] { smelter });
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Could not read SurtlingFuel's configured fuel value: " + ex));
				return false;
			}
			int val2 = smelter.m_maxFuel - (int)Math.Ceiling(fuel);
			int num = Math.Min(val, val2);
			if (num <= 0)
			{
				return false;
			}
			ZNetView nview = smelter.m_nview;
			if ((Object)(object)nview == (Object)null || !nview.IsValid())
			{
				return false;
			}
			if (!source.RemoveItem(item, 1))
			{
				return false;
			}
			nview.InvokeRPC("RPC_SurtlingFuel_AddCoreFuel", new object[1] { num });
			return true;
		}

		private static bool TryReadFuelState(Smelter smelter, out ZDO zdo, out float fuel, out int coreFuel)
		{
			zdo = null;
			fuel = 0f;
			coreFuel = 0;
			if ((Object)(object)smelter == (Object)null || (Object)(object)smelter.m_nview == (Object)null || !smelter.m_nview.IsValid())
			{
				return false;
			}
			zdo = smelter.m_nview.GetZDO();
			if (zdo == null)
			{
				return false;
			}
			fuel = zdo.GetFloat(ZDOVars.s_fuel, 0f);
			coreFuel = zdo.GetInt(CoreFuelZdoKey, 0);
			return true;
		}
	}
	[HarmonyPatch(typeof(SmelterFuelTarget), "CanAddItem")]
	internal static class SmelterFuelTargetCanAddItemPatch
	{
		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static bool Prefix(SmelterFuelTarget __instance, ItemData item, ref bool __result)
		{
			Smelter component = ((Component)__instance).GetComponent<Smelter>();
			if (Plugin.IsAlternativeFuel(item))
			{
				__result = Plugin.CanAcceptAlternativeFuel(component);
				return false;
			}
			if (Plugin.IsCoreFuelActive(component))
			{
				__result = false;
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(SmelterFuelTarget), "AddItem")]
	internal static class SmelterFuelTargetAddItemPatch
	{
		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static bool Prefix(SmelterFuelTarget __instance, ItemData item, Inventory source)
		{
			Smelter component = ((Component)__instance).GetComponent<Smelter>();
			if (Plugin.IsAlternativeFuel(item))
			{
				Plugin.TryAddAlternativeFuel(component, item, source);
				return false;
			}
			return !Plugin.IsCoreFuelActive(component);
		}
	}
}