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 AdditionalFuelPrefabs; internal static ManualLogSource Log; private static HashSet _alternativeFuelPrefabs = new HashSet(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("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 hashSet = new HashSet(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(); 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(); if (Plugin.IsAlternativeFuel(item)) { Plugin.TryAddAlternativeFuel(component, item, source); return false; } return !Plugin.IsCoreFuelActive(component); } } }