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 StationItemReturn v1.0.0
StationItemReturn.dll
Decompiled a week agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using ConditionalConfigSync; 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: AssemblyTitle("Station Item Return")] [assembly: AssemblyDescription("Returns stored items and fuel from supported Valheim stations.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("shudnal")] [assembly: AssemblyProduct("Station Item Return")] [assembly: AssemblyCopyright("Copyright © 2026 shudnal")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("a2ef7f0f-9669-41c7-b98a-269eef06fc2e")] [assembly: AssemblyFileVersion("1.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [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 StationItemReturn { internal static class HoverHints { [HarmonyPatch(typeof(CookingStation), "GetHoverText")] private static class CookingStation_GetHoverText_AddReturnHint { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { return InjectRawReturnHint(instructions); } [HarmonyAfter(new string[] { "shudnal.MyLittleUI" })] [HarmonyPriority(0)] private static void Postfix(CookingStation __instance, ref string __result) { __result = AddLocalizedReturnHint(__result, __instance); } } [HarmonyPatch(typeof(Fireplace), "GetHoverText")] private static class Fireplace_GetHoverText_AddReturnHint { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { return InjectRawReturnHint(instructions); } [HarmonyAfter(new string[] { "shudnal.MyLittleUI" })] [HarmonyPriority(0)] private static void Postfix(Fireplace __instance, ref string __result) { __result = AddLocalizedReturnHint(__result, __instance); } } [HarmonyPatch(typeof(Smelter), "OnHoverAddOre")] private static class Smelter_OnHoverAddOre_AddReturnHint { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { return InjectRawReturnHint(instructions); } [HarmonyAfter(new string[] { "shudnal.MyLittleUI" })] [HarmonyPriority(0)] private static void Postfix(Smelter __instance, ref string __result) { __result = AddLocalizedReturnHint(__result, __instance); } } [HarmonyPatch(typeof(Fermenter), "GetHoverText")] private static class Fermenter_GetHoverText_AddReturnHint { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { return InjectRawReturnHint(instructions); } [HarmonyBefore(new string[] { "shudnal.MyLittleUI" })] [HarmonyPriority(0)] private static void Postfix(Fermenter __instance, ref string __result) { __result = AddLocalizedReturnHint(__result, __instance); } } [HarmonyPatch(typeof(Turret), "GetHoverText")] private static class Turret_GetHoverText_AddReturnHint { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { return InjectRawReturnHint(instructions); } [HarmonyAfter(new string[] { "shudnal.MyLittleUI" })] [HarmonyPriority(0)] private static void Postfix(Turret __instance, ref string __result) { __result = AddLocalizedReturnHint(__result, __instance); } } [HarmonyPatch(typeof(Switch), "GetHoverText")] private static class Switch_GetHoverText_AddReturnHint { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { return InjectRawReturnHint(instructions); } [HarmonyAfter(new string[] { "shudnal.MyLittleUI" })] [HarmonyPriority(0)] private static void Postfix(Switch __instance, ref string __result) { __result = AddLocalizedReturnHint(__result, __instance); } } private const string UseKey = "$KEY_Use"; private const string ReturnKeyCombination = "$KEY_AltPlace + $KEY_Use"; private static readonly MethodInfo LocalizeMethod = AccessTools.Method(typeof(Localization), "Localize", new Type[1] { typeof(string) }, (Type[])null); private static readonly MethodInfo LocalizeWithReturnHintMethod = AccessTools.Method(typeof(HoverHints), "LocalizeWithReturnHint", new Type[3] { typeof(Localization), typeof(string), typeof(object) }, (Type[])null); private static string BuildReturnHint(string sharedName) { return "[<color=yellow><b>$KEY_AltPlace + $KEY_Use</b></color>] $hud_remove (<color=#add8e6ff>" + sharedName + "</color>)"; } private static string InsertAfterFirstUseLine(string text, string hint, bool appendWhenUseIsMissing) { if (string.IsNullOrWhiteSpace(text) || string.IsNullOrEmpty(hint)) { return text; } int num = text.IndexOf("$KEY_Use", StringComparison.Ordinal); if (num < 0) { return appendWhenUseIsMissing ? (text + "\n" + hint) : text; } int num2 = text.IndexOf('\n', num); if (num2 < 0) { return text + "\n" + hint; } return text.Insert(num2 + 1, hint + "\n"); } private static string AddRawReturnHint(string text, object source) { if (!StationReturn.TryGetReturnableItem(source, out var sharedName) || string.IsNullOrEmpty(sharedName) || text.IndexOf("$KEY_AltPlace + $KEY_Use", StringComparison.Ordinal) >= 0) { return text; } return InsertAfterFirstUseLine(text, BuildReturnHint(sharedName), source is Fermenter); } private static string LocalizeWithReturnHint(Localization localization, string text, object source) { return localization.Localize(AddRawReturnHint(text, source)); } private static string AddLocalizedReturnHint(string text, object source) { if (string.IsNullOrWhiteSpace(text) || !StationReturn.TryGetReturnableItem(source, out var sharedName) || string.IsNullOrEmpty(sharedName)) { return text; } string value = Localization.instance.Localize("$KEY_AltPlace + $KEY_Use"); if (!string.IsNullOrEmpty(value) && text.IndexOf(value, StringComparison.Ordinal) >= 0) { return text; } string text2 = Localization.instance.Localize("$KEY_Use"); string value2 = "[<color=yellow><b>" + text2 + "</b></color>]"; string text3 = Localization.instance.Localize(BuildReturnHint(sharedName)); int num = text.IndexOf(value2, StringComparison.Ordinal); if (num < 0) { return (source is Fermenter) ? (text + "\n" + text3) : text; } int num2 = text.IndexOf('\n', num); if (num2 < 0) { return text + "\n" + text3; } return text.Insert(num2 + 1, text3 + "\n"); } private static IEnumerable<CodeInstruction> InjectRawReturnHint(IEnumerable<CodeInstruction> instructions) { foreach (CodeInstruction instruction in instructions) { if (LocalizeMethod != null && LocalizeWithReturnHintMethod != null && CodeInstructionExtensions.Calls(instruction, LocalizeMethod)) { CodeInstruction loadSource = new CodeInstruction(OpCodes.Ldarg_0, (object)null); loadSource.labels.AddRange(instruction.labels); instruction.labels.Clear(); yield return loadSource; instruction.opcode = OpCodes.Call; instruction.operand = LocalizeWithReturnHintMethod; } yield return instruction; } } } [BepInPlugin("shudnal.StationItemReturn", "Station Item Return", "1.0.0")] [BepInDependency("_shudnal.ConditionalConfigSync", "1.0.6")] public sealed class StationItemReturn : BaseUnityPlugin { private sealed class ConfigurationManagerAttributes { public bool? ShowRangeAsPercent = false; } public const string PluginId = "shudnal.StationItemReturn"; public const string PluginName = "Station Item Return"; public const string PluginVersion = "1.0.0"; public const string ConditionalConfigSyncGuid = "_shudnal.ConditionalConfigSync"; internal static readonly ConfigSync ConfigSync = new ConfigSync("shudnal.StationItemReturn") { DisplayName = "Station Item Return", CurrentVersion = "1.0.0", MinimumRequiredVersion = "1.0.0", ModRequired = false, ModRequirementMode = (ModRequirementMode)0 }; internal static StationItemReturn Instance; internal static ConfigEntry<bool> ModEnabled; internal static ConfigEntry<bool> ConfigLocked; internal static ConfigEntry<bool> LoggingEnabled; internal static ConfigEntry<bool> CookingStationItemReturnEnabled; internal static ConfigEntry<float> CookingStationItemReturnProgressLimit; internal static ConfigEntry<bool> CookingStationFuelReturnEnabled; internal static ConfigEntry<bool> FireplaceFuelReturnEnabled; internal static ConfigEntry<string> FireplaceExcludedPrefabs; internal static ConfigEntry<bool> SmelterInputReturnEnabled; internal static ConfigEntry<bool> SmelterFuelReturnEnabled; internal static ConfigEntry<string> SmelterFuelExcludedPrefabs; internal static ConfigEntry<bool> FermenterIngredientReturnEnabled; internal static ConfigEntry<float> FermenterIngredientReturnProgressLimit; internal static ConfigEntry<bool> TurretAmmoReturnEnabled; private static readonly HashSet<string> ExcludedFireplacePrefabNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private static readonly HashSet<string> ExcludedSmelterFuelPrefabNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private Harmony harmony; internal static bool IsAvailableForCurrentSession { get { if ((Object)(object)ZNet.instance == (Object)null) { return true; } if (ZNet.m_isServer) { return true; } return ((ConditionalConfigSync)ConfigSync).InitialSyncDone; } } private void Awake() { Instance = this; BindConfiguration(); harmony = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "shudnal.StationItemReturn"); Game.isModded = true; } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } private void BindConfiguration() { //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Expected O, but got Unknown //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Expected O, but got Unknown ModEnabled = BindServerConfig("General", "Enabled", defaultValue: true, "Enable the mod. [Synced with Server]"); LoggingEnabled = BindClientConfig("General", "Enable logging", defaultValue: false, "Enable diagnostic logging on this client."); ConfigLocked = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Lock Configuration", true, "Configuration is locked and can be changed by server administrators only. [Synced with Server]"); ((ConditionalConfigSync)ConfigSync).AddLockingConfigEntry<bool>(ConfigLocked); CookingStationItemReturnEnabled = BindServerConfig("Cooking stations", "Return uncooked items", defaultValue: true, "Allow returning the last uncooked item from cooking stations and ovens. [Synced with Server]"); CookingStationItemReturnProgressLimit = BindServerConfig("Cooking stations", "Maximum return progress", 0f, new ConfigDescription("Maximum cooking progress at which an uncooked item can still be returned. 0 disables this restriction; values above 0 limit returns to that fraction of the cooking time. [Synced with Server]", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), new object[1] { new ConfigurationManagerAttributes { ShowRangeAsPercent = true } })); CookingStationFuelReturnEnabled = BindServerConfig("Cooking stations", "Return fuel", defaultValue: false, "Allow returning one remaining fuel item from cooking stations and ovens that use a fixed fuel item. [Synced with Server]"); FireplaceFuelReturnEnabled = BindServerConfig("Fireplaces", "Return fuel", defaultValue: false, "Allow returning one remaining fuel item from refillable fireplaces that use a fixed fuel item. Fireplaces do not normally refund fuel when destroyed, so this feature is disabled by default. [Synced with Server]"); FireplaceExcludedPrefabs = BindServerConfig("Fireplaces", "Excluded prefabs", string.Empty, "Comma-, semicolon-, or line-separated exact prefab names that must not return fuel. Use this for fireplaces modified to accept multiple fuel item types because Valheim stores only a single fuel amount and does not preserve which fuel items were added. [Synced with Server]"); FireplaceExcludedPrefabs.SettingChanged += delegate { RefreshExcludedFireplacePrefabs(); }; RefreshExcludedFireplacePrefabs(); SmelterInputReturnEnabled = BindServerConfig("Smelters", "Return input items", defaultValue: true, "Allow returning the newest raw item from a smelter input queue. [Synced with Server]"); SmelterFuelReturnEnabled = BindServerConfig("Smelters", "Return fuel", defaultValue: true, "Allow returning one remaining fuel item from smelters that use a fixed fuel item. [Synced with Server]"); SmelterFuelExcludedPrefabs = BindServerConfig("Smelters", "Fuel return excluded prefabs", string.Empty, "Comma-, semicolon-, or line-separated exact prefab names that must not return fuel. Use this for smelters modified to accept multiple fuel item types because Valheim stores only a single fuel amount and does not preserve which fuel items were added. [Synced with Server]"); SmelterFuelExcludedPrefabs.SettingChanged += delegate { RefreshExcludedSmelterFuelPrefabs(); }; RefreshExcludedSmelterFuelPrefabs(); FermenterIngredientReturnEnabled = BindServerConfig("Fermenters", "Return ingredient", defaultValue: true, "Allow returning the original ingredient while a fermenter is still fermenting. [Synced with Server]"); FermenterIngredientReturnProgressLimit = BindServerConfig("Fermenters", "Maximum return progress", 0f, new ConfigDescription("Maximum fermentation progress at which the original ingredient can still be returned. 0 disables this restriction; values above 0 limit returns to that fraction of the fermentation time. For example 25% means mead can only be returned in first 15 minutes of fermenting. [Synced with Server]", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), new object[1] { new ConfigurationManagerAttributes { ShowRangeAsPercent = true } })); TurretAmmoReturnEnabled = BindServerConfig("Turrets", "Return ammunition", defaultValue: false, "Allow returning one loaded ammunition item from turrets configured to refund ammunition when destroyed. Turrets do not preserve cheated provenance, so returned ammunition is always cleared of the cheated marker. [Synced with Server]"); } private static void RefreshExcludedPrefabNames(ConfigEntry<string> entry, HashSet<string> names) { names.Clear(); string text = entry?.Value ?? string.Empty; string[] array = text.Split(new char[4] { ',', ';', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); foreach (string text2 in array) { string text3 = text2.Trim(); if (!string.IsNullOrEmpty(text3)) { names.Add(text3); } } } private static void RefreshExcludedFireplacePrefabs() { RefreshExcludedPrefabNames(FireplaceExcludedPrefabs, ExcludedFireplacePrefabNames); } private static void RefreshExcludedSmelterFuelPrefabs() { RefreshExcludedPrefabNames(SmelterFuelExcludedPrefabs, ExcludedSmelterFuelPrefabNames); } internal static bool IsFireplaceExcluded(Fireplace fireplace) { if (!Object.op_Implicit((Object)(object)fireplace)) { return false; } string text = ((Object.op_Implicit((Object)(object)fireplace.m_nview) && fireplace.m_nview.IsValid()) ? fireplace.m_nview.GetPrefabName() : Utils.GetPrefabName(((Component)fireplace).gameObject)); return !string.IsNullOrEmpty(text) && ExcludedFireplacePrefabNames.Contains(text); } internal static bool IsSmelterFuelExcluded(Smelter smelter) { if (!Object.op_Implicit((Object)(object)smelter)) { return false; } string text = ((Object.op_Implicit((Object)(object)smelter.m_nview) && smelter.m_nview.IsValid()) ? smelter.m_nview.GetPrefabName() : Utils.GetPrefabName(((Component)smelter).gameObject)); return !string.IsNullOrEmpty(text) && ExcludedSmelterFuelPrefabNames.Contains(text); } private ConfigEntry<T> BindServerConfig<T>(string section, string key, T defaultValue, ConfigDescription description) { ConfigEntry<T> val = ((BaseUnityPlugin)this).Config.Bind<T>(section, key, defaultValue, description); ((ConditionalConfigSync)ConfigSync).AddConfigEntry<T>(val, (ConfigSyncMode)0); return val; } private ConfigEntry<T> BindServerConfig<T>(string section, string key, T defaultValue, string description) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown return BindServerConfig(section, key, defaultValue, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>())); } private ConfigEntry<T> BindClientConfig<T>(string section, string key, T defaultValue, string description) { ConfigEntry<T> val = ((BaseUnityPlugin)this).Config.Bind<T>(section, key, defaultValue, description); ((ConditionalConfigSync)ConfigSync).AddConfigEntry<T>(val, (ConfigSyncMode)2); return val; } internal static void LogInfo(object value) { ConfigEntry<bool> loggingEnabled = LoggingEnabled; if (loggingEnabled != null && loggingEnabled.Value) { ((BaseUnityPlugin)Instance).Logger.LogInfo(value); } } internal static void LogWarning(object value) { ((BaseUnityPlugin)Instance).Logger.LogWarning(value); } } internal static class StationReturn { private struct CookingInteractionState { internal bool HadDoneItem; internal int FreeSlot; internal string ExpectedPrefabName; } [HarmonyPatch(typeof(CookingStation), "Awake")] private static class CookingStation_Awake_RegisterRpcs { private static void Postfix(CookingStation __instance) { if (IsValidView(__instance.m_nview)) { __instance.m_nview.Register<Vector3>("RPC_SIR_ReturnCookingItem", (Action<long, Vector3>)delegate(long sender, Vector3 userPoint) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) ReturnCookingItemOnOwner(__instance, userPoint); }); __instance.m_nview.Register<Vector3>("RPC_SIR_ReturnCookingFuel", (Action<long, Vector3>)delegate(long sender, Vector3 userPoint) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) ReturnCookingFuelOnOwner(__instance, userPoint); }); __instance.m_nview.Register<bool, bool>("RPC_SIR_RefreshCookingStation", (Action<long, bool, bool>)delegate(long sender, bool active, bool hasFuel) { RefreshCookingStation(__instance, active, hasFuel); }); __instance.m_nview.Register<int, string>("RPC_SIR_RecordCookingSkill", (Action<long, int, string>)delegate(long sender, int slot, string expectedPrefabName) { MarkCookingSkillCreditOnOwner(__instance, sender, slot, expectedPrefabName); }); } } } [HarmonyPatch(typeof(Fireplace), "Awake")] private static class Fireplace_Awake_RegisterRpcs { private static void Postfix(Fireplace __instance) { if (IsValidView(__instance.m_nview)) { __instance.m_nview.Register<Vector3>("RPC_SIR_ReturnFireplaceFuel", (Action<long, Vector3>)delegate(long sender, Vector3 userPoint) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) ReturnFireplaceFuelOnOwner(__instance, userPoint); }); __instance.m_nview.Register("RPC_SIR_RefreshFireplace", (Action<long>)delegate { RefreshFireplace(__instance); }); } } } [HarmonyPatch(typeof(Smelter), "Awake")] private static class Smelter_Awake_RegisterRpcs { private static void Postfix(Smelter __instance) { if (IsValidView(__instance.m_nview)) { __instance.m_nview.Register<Vector3>("RPC_SIR_ReturnSmelterInput", (Action<long, Vector3>)delegate(long sender, Vector3 userPoint) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) ReturnSmelterInputOnOwner(__instance, userPoint); }); __instance.m_nview.Register<Vector3>("RPC_SIR_ReturnSmelterFuel", (Action<long, Vector3>)delegate(long sender, Vector3 userPoint) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) ReturnSmelterFuelOnOwner(__instance, userPoint); }); __instance.m_nview.Register<bool, bool, bool>("RPC_SIR_RefreshSmelter", (Action<long, bool, bool, bool>)delegate(long sender, bool active, bool hasFuel, bool hasInput) { RefreshSmelter(__instance, active, hasFuel, hasInput); }); } } } [HarmonyPatch(typeof(Fermenter), "Awake")] private static class Fermenter_Awake_RegisterRpcs { private static void Postfix(Fermenter __instance) { if (IsValidView(__instance.m_nview)) { __instance.m_nview.Register<Vector3>("RPC_SIR_ReturnFermenterIngredient", (Action<long, Vector3>)delegate(long sender, Vector3 userPoint) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) ReturnFermenterIngredientOnOwner(__instance, userPoint); }); __instance.m_nview.Register("RPC_SIR_RefreshFermenter", (Action<long>)delegate { RefreshFermenter(__instance); }); } } } [HarmonyPatch(typeof(Turret), "Awake")] private static class Turret_Awake_RegisterRpcs { private static void Postfix(Turret __instance) { if (IsValidView(__instance.m_nview)) { __instance.m_nview.Register<Vector3>("RPC_SIR_ReturnTurretAmmo", (Action<long, Vector3>)delegate(long sender, Vector3 userPoint) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) ReturnTurretAmmoOnOwner(__instance, userPoint); }); __instance.m_nview.Register<int, string>("RPC_SIR_RefreshTurret", (Action<long, int, string>)delegate(long sender, int remainingAmmo, string ammoType) { RefreshTurret(__instance, remainingAmmo, ammoType); }); } } } [HarmonyPatch(typeof(CookingStation), "RPC_AddItem")] private static class CookingStation_RPC_AddItem_CaptureAuthor { private static void Prefix(long sender, out long __state) { __state = activeCookingAuthor; activeCookingAuthor = sender; } private static void Finalizer(long __state) { activeCookingAuthor = __state; } } [HarmonyPatch(typeof(CookingStation), "SetSlot")] private static class CookingStation_SetSlot_TrackReturnMetadata { private static void Postfix(CookingStation __instance, int slot, string itemName) { if (!IsValidOwner(__instance.m_nview)) { return; } ZDO zDO = __instance.m_nview.GetZDO(); if (string.IsNullOrEmpty(itemName)) { zDO.Set(CookingAuthorKey(slot), 0L); zDO.Set(CookingSkillKey(slot), false); if (zDO.GetInt("SIR_LastCookingSlot", -1) == slot) { zDO.Set("SIR_LastCookingAuthor", 0L); zDO.Set("SIR_LastCookingSlot", -1); } } else if (activeCookingAuthor != 0) { zDO.Set(CookingAuthorKey(slot), activeCookingAuthor); zDO.Set(CookingSkillKey(slot), false); zDO.Set("SIR_LastCookingAuthor", activeCookingAuthor); zDO.Set("SIR_LastCookingSlot", slot); } } } [HarmonyPatch(typeof(CookingStation), "OnInteract")] private static class CookingStation_OnInteract_RecordSkillCredit { private static void Prefix(CookingStation __instance, Humanoid user, out CookingInteractionState __state) { bool flag = __instance.HaveDoneItem(); ItemData val = ((!flag && Object.op_Implicit((Object)(object)user)) ? __instance.FindCookableItem(user.GetInventory()) : null); CookingInteractionState cookingInteractionState = new CookingInteractionState { HadDoneItem = flag, FreeSlot = __instance.GetFreeSlot() }; object expectedPrefabName; if (val == null) { expectedPrefabName = null; } else { GameObject dropPrefab = val.m_dropPrefab; expectedPrefabName = ((dropPrefab != null) ? ((Object)dropPrefab).name : null); } cookingInteractionState.ExpectedPrefabName = (string)expectedPrefabName; __state = cookingInteractionState; } private static void Postfix(CookingStation __instance, bool __result, CookingInteractionState __state) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 if (__result && !__state.HadDoneItem && __state.FreeSlot >= 0 && !string.IsNullOrEmpty(__state.ExpectedPrefabName) && (int)__instance.m_skill > 0) { RequestCookingSkillCredit(__instance, __state.FreeSlot, __state.ExpectedPrefabName); } } } [HarmonyPatch(typeof(CookingStation), "Interact")] private static class CookingStation_Interact_ReturnStoredItem { [HarmonyPriority(800)] private static bool Prefix(CookingStation __instance, Humanoid user, bool hold, bool alt, bool __runOriginal) { if (!__runOriginal) { return false; } if (ShouldBlockFollowupHold((Component)(object)__instance, hold)) { return false; } if (hold || !alt || Object.op_Implicit((Object)(object)__instance.m_addFoodSwitch)) { return true; } if (!CanReturnCookingItem(__instance, checkAccess: true, out var _)) { return true; } RequestReturn(__instance.m_nview, user, "RPC_SIR_ReturnCookingItem"); BlockFollowupHold((Component)(object)__instance); return false; } } [HarmonyPatch(typeof(Fireplace), "Interact")] private static class Fireplace_Interact_ReturnFuel { [HarmonyBefore(new string[] { "shudnal.MyLittleUI", "shudnal.AnyWood" })] [HarmonyPriority(800)] private static bool Prefix(Fireplace __instance, Humanoid user, bool hold, bool alt, bool __runOriginal) { if (!__runOriginal) { return false; } if (ShouldBlockFollowupHold((Component)(object)__instance, hold)) { return false; } if (hold || !alt || !CanReturnFireplaceFuel(__instance, checkAccess: true, out var _)) { return true; } RequestReturn(__instance.m_nview, user, "RPC_SIR_ReturnFireplaceFuel"); BlockFollowupHold((Component)(object)__instance); return false; } } [HarmonyPatch(typeof(Switch), "Interact")] private static class Switch_Interact_ReturnStoredItem { [HarmonyBefore(new string[] { "shudnal.MyLittleUI", "shudnal.AnyWood" })] [HarmonyPriority(800)] private static bool Prefix(Switch __instance, Humanoid character, bool hold, bool alt, bool __runOriginal) { if (!__runOriginal) { return false; } if (ShouldBlockFollowupHold((Component)(object)__instance, hold)) { return false; } if (hold || !alt) { return true; } CookingStation val = ResolveCookingItemSwitch(__instance); if (Object.op_Implicit((Object)(object)val) && CanReturnCookingItem(val, checkAccess: true, out var sharedName)) { RequestReturn(val.m_nview, character, "RPC_SIR_ReturnCookingItem"); BlockFollowupHold((Component)(object)__instance); return false; } CookingStation val2 = ResolveCookingFuelSwitch(__instance); if (Object.op_Implicit((Object)(object)val2) && CanReturnCookingFuel(val2, checkAccess: true, out sharedName)) { RequestReturn(val2.m_nview, character, "RPC_SIR_ReturnCookingFuel"); BlockFollowupHold((Component)(object)__instance); return false; } Smelter val3 = ResolveSmelterInputSwitch(__instance); if (Object.op_Implicit((Object)(object)val3) && CanReturnSmelterInput(val3, checkAccess: true, out sharedName)) { RequestReturn(val3.m_nview, character, "RPC_SIR_ReturnSmelterInput"); BlockFollowupHold((Component)(object)__instance); return false; } Smelter val4 = ResolveSmelterFuelSwitch(__instance); if (Object.op_Implicit((Object)(object)val4) && CanReturnSmelterFuel(val4, checkAccess: true, out sharedName)) { RequestReturn(val4.m_nview, character, "RPC_SIR_ReturnSmelterFuel"); BlockFollowupHold((Component)(object)__instance); return false; } return true; } } [HarmonyPatch(typeof(Fermenter), "Interact")] private static class Fermenter_Interact_ReturnIngredient { [HarmonyPriority(800)] private static bool Prefix(Fermenter __instance, Humanoid user, bool hold, bool alt, bool __runOriginal) { if (!__runOriginal) { return false; } if (ShouldBlockFollowupHold((Component)(object)__instance, hold)) { return false; } if (hold || !alt || !CanReturnFermenterIngredient(__instance, checkAccess: true, out var _)) { return true; } RequestReturn(__instance.m_nview, user, "RPC_SIR_ReturnFermenterIngredient"); BlockFollowupHold((Component)(object)__instance); return false; } } [HarmonyPatch(typeof(Turret), "Interact")] private static class Turret_Interact_ReturnAmmo { [HarmonyPriority(800)] private static bool Prefix(Turret __instance, Humanoid character, bool hold, bool alt, bool __runOriginal) { if (!__runOriginal) { return false; } if (ShouldBlockFollowupHold((Component)(object)__instance, hold)) { return false; } if (hold || !alt || !CanReturnTurretAmmo(__instance, checkAccess: true, out var _)) { return true; } RequestReturn(__instance.m_nview, character, "RPC_SIR_ReturnTurretAmmo"); BlockFollowupHold((Component)(object)__instance); return false; } } [HarmonyPatch(typeof(ZoneSystem), "Start")] private static class ZoneSystem_Start_RegisterRoutedRpc { private static void Postfix() { if (ZRoutedRpc.instance != null && registeredRoutedRpc != ZRoutedRpc.instance) { registeredRoutedRpc = ZRoutedRpc.instance; registeredRoutedRpc.Register<int>("RPC_SIR_UndoStationSkill", (Action<long, int>)UndoStationSkill); } } } private const string ReturnCookingItemRpc = "RPC_SIR_ReturnCookingItem"; private const string ReturnCookingFuelRpc = "RPC_SIR_ReturnCookingFuel"; private const string RefreshCookingStationRpc = "RPC_SIR_RefreshCookingStation"; private const string ReturnFireplaceFuelRpc = "RPC_SIR_ReturnFireplaceFuel"; private const string RefreshFireplaceRpc = "RPC_SIR_RefreshFireplace"; private const string RecordCookingSkillRpc = "RPC_SIR_RecordCookingSkill"; private const string ReturnSmelterInputRpc = "RPC_SIR_ReturnSmelterInput"; private const string ReturnSmelterFuelRpc = "RPC_SIR_ReturnSmelterFuel"; private const string RefreshSmelterRpc = "RPC_SIR_RefreshSmelter"; private const string ReturnFermenterIngredientRpc = "RPC_SIR_ReturnFermenterIngredient"; private const string RefreshFermenterRpc = "RPC_SIR_RefreshFermenter"; private const string ReturnTurretAmmoRpc = "RPC_SIR_ReturnTurretAmmo"; private const string RefreshTurretRpc = "RPC_SIR_RefreshTurret"; private const string UndoSkillRpc = "RPC_SIR_UndoStationSkill"; private const string LastCookingAuthorKey = "SIR_LastCookingAuthor"; private const string LastCookingSlotKey = "SIR_LastCookingSlot"; private static long activeCookingAuthor; private static int blockedHoldSourceId; private static ZRoutedRpc registeredRoutedRpc; internal static bool IsEnabled { get { ConfigEntry<bool> modEnabled = StationItemReturn.ModEnabled; return modEnabled != null && modEnabled.Value && StationItemReturn.IsAvailableForCurrentSession; } } private static string CookingAuthorKey(int slot) { return "SIR_CookingAuthor_" + slot; } private static string CookingSkillKey(int slot) { return "SIR_CookingSkill_" + slot; } private static bool IsValidOwner(ZNetView view) { return Object.op_Implicit((Object)(object)view) && view.IsValid() && view.GetZDO() != null && view.IsOwner(); } private static bool IsValidView(ZNetView view) { return Object.op_Implicit((Object)(object)view) && view.IsValid() && view.GetZDO() != null; } private static GameObject GetItemPrefab(string prefabName) { if (string.IsNullOrEmpty(prefabName)) { return null; } GameObject val = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab(prefabName) : null); if (!Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)ZNetScene.instance)) { val = ZNetScene.instance.GetPrefab(prefabName); } return val; } private static string GetSharedName(GameObject prefab) { return (!Object.op_Implicit((Object)(object)prefab)) ? null : prefab.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_name; } private static Piece GetPiece(Component component) { if (!Object.op_Implicit((Object)(object)component)) { return null; } Piece componentInParent = component.GetComponentInParent<Piece>(); return Object.op_Implicit((Object)(object)componentInParent) ? componentInParent : component.GetComponentInChildren<Piece>(true); } private static bool HasLocalAccess(Component component) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) Piece piece = GetPiece(component); if (!Object.op_Implicit((Object)(object)piece)) { return true; } return Object.op_Implicit((Object)(object)Player.m_localPlayer) && PrivateArea.CheckAccess(((Component)piece).transform.position, 0f, false, false); } private static bool ShouldBlockFollowupHold(Component source, bool hold) { if (!Object.op_Implicit((Object)(object)source)) { blockedHoldSourceId = 0; return false; } int instanceID = ((Object)source).GetInstanceID(); if (hold) { return blockedHoldSourceId == instanceID; } blockedHoldSourceId = 0; return false; } private static void BlockFollowupHold(Component source) { blockedHoldSourceId = (Object.op_Implicit((Object)(object)source) ? ((Object)source).GetInstanceID() : 0); } private static bool PrepareRequest(ZNetView view) { if (!IsValidView(view)) { return false; } if (!view.HasOwner()) { view.ClaimOwnership(); } return view.HasOwner(); } private static void RequestReturn(ZNetView view, Humanoid user, string rpcName) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)user) && PrepareRequest(view)) { view.InvokeRPC(rpcName, new object[1] { ((Component)user).transform.position }); } } private static void RequestCookingSkillCredit(CookingStation station, int slot, string expectedPrefabName) { if (Object.op_Implicit((Object)(object)station) && slot >= 0 && !string.IsNullOrEmpty(expectedPrefabName) && PrepareRequest(station.m_nview)) { station.m_nview.InvokeRPC("RPC_SIR_RecordCookingSkill", new object[2] { slot, expectedPrefabName }); } } private static bool CreateItem(GameObject prefab, Vector3 position, Vector3 direction, float force, bool cheated, out ItemDrop spawnedItem) { //IL_0056: 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) //IL_0045: 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_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) spawnedItem = null; ItemDrop val = (Object.op_Implicit((Object)(object)prefab) ? prefab.GetComponent<ItemDrop>() : null); if (!Object.op_Implicit((Object)(object)val)) { return false; } if (((Vector3)(ref direction)).sqrMagnitude <= 0.0001f) { direction = Vector3.forward; } ((Vector3)(ref direction)).Normalize(); GameObject val2 = Object.Instantiate<GameObject>(prefab, position, Quaternion.Euler(0f, (float)Random.Range(0, 360), 0f)); spawnedItem = val2.GetComponent<ItemDrop>(); if (!Object.op_Implicit((Object)(object)spawnedItem)) { Object.Destroy((Object)(object)val2); return false; } ItemDrop.OnCreateNew(spawnedItem, cheated); Rigidbody component = val2.GetComponent<Rigidbody>(); if (Object.op_Implicit((Object)(object)component)) { component.linearVelocity = direction * force; } return true; } private static bool SpawnItem(GameObject prefab, Vector3 origin, Vector3 fallbackDirection, Vector3 userPoint, float force, bool cheated, out ItemDrop spawnedItem) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: 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_002c: 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_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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_0055: Unknown result type (might be due to invalid IL or missing references) Vector3 val = userPoint - origin; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude <= 0.0001f) { val = fallbackDirection; val.y = 0f; } if (((Vector3)(ref val)).sqrMagnitude <= 0.0001f) { val = Vector3.forward; } ((Vector3)(ref val)).Normalize(); return CreateItem(prefab, origin + val * 0.5f, val, force, cheated, out spawnedItem); } private static T ResolveStationSwitch<T>(Switch switchRef, Func<T, Switch> getSwitch) where T : Component { if (!Object.op_Implicit((Object)(object)switchRef)) { return default(T); } T componentInParent = ((Component)switchRef).GetComponentInParent<T>(); if (Object.op_Implicit((Object)(object)componentInParent) && (Object)(object)getSwitch(componentInParent) == (Object)(object)switchRef) { return componentInParent; } if (switchRef.m_onUse == null) { return default(T); } Delegate[] invocationList = ((Delegate)(object)switchRef.m_onUse).GetInvocationList(); foreach (Delegate obj in invocationList) { object? target = obj.Target; T val = (T)((target is T) ? target : null); if (val != null && (Object)(object)getSwitch(val) == (Object)(object)switchRef) { return val; } } return default(T); } internal static CookingStation ResolveCookingItemSwitch(Switch switchRef) { return ResolveStationSwitch<CookingStation>(switchRef, (Func<CookingStation, Switch>)((CookingStation station) => station.m_addFoodSwitch)); } internal static CookingStation ResolveCookingFuelSwitch(Switch switchRef) { return ResolveStationSwitch<CookingStation>(switchRef, (Func<CookingStation, Switch>)((CookingStation station) => station.m_addFuelSwitch)); } internal static Smelter ResolveSmelterInputSwitch(Switch switchRef) { return ResolveStationSwitch<Smelter>(switchRef, (Func<Smelter, Switch>)((Smelter station) => station.m_addOreSwitch)); } internal static Smelter ResolveSmelterFuelSwitch(Switch switchRef) { return ResolveStationSwitch<Smelter>(switchRef, (Func<Smelter, Switch>)((Smelter station) => station.m_addWoodSwitch)); } private static bool TryGetCookingItem(CookingStation station, out int slot, out GameObject prefab, out string sharedName, out bool cheated, out long author, out bool skillCredited) { //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Invalid comparison between Unknown and I4 slot = -1; prefab = null; sharedName = null; cheated = false; author = 0L; skillCredited = false; if (!Object.op_Implicit((Object)(object)station) || !IsValidView(station.m_nview) || station.m_slots == null) { return false; } ZDO zDO = station.m_nview.GetZDO(); float num = StationItemReturn.CookingStationItemReturnProgressLimit?.Value ?? 0f; string text = default(string); float num3 = default(float); Status val = default(Status); bool flag = default(bool); for (int num2 = station.m_slots.Length - 1; num2 >= 0; num2--) { station.GetSlot(num2, ref text, ref num3, ref val, ref flag); if (!string.IsNullOrEmpty(text) && (int)val <= 0) { ItemConversion itemConversion = station.GetItemConversion(text); if (itemConversion != null && Object.op_Implicit((Object)(object)itemConversion.m_from) && !(text != ((Object)itemConversion.m_from).name) && (!(num > 0f) || !(itemConversion.m_cookTime > 0f) || !(num3 > itemConversion.m_cookTime * num))) { GameObject itemPrefab = GetItemPrefab(text); string sharedName2 = GetSharedName(itemPrefab); if (Object.op_Implicit((Object)(object)itemPrefab) && !string.IsNullOrEmpty(sharedName2)) { slot = num2; prefab = itemPrefab; sharedName = sharedName2; cheated = flag && !PlayerProfile.s_bypassCheatChecks; author = zDO.GetLong(CookingAuthorKey(num2), 0L); skillCredited = zDO.GetBool(CookingSkillKey(num2), false); return true; } } } } return false; } private static bool TryGetCookingFuel(CookingStation station, out GameObject prefab, out string sharedName, out bool cheated) { prefab = null; sharedName = null; cheated = false; if (!Object.op_Implicit((Object)(object)station) || !IsValidView(station.m_nview) || !Object.op_Implicit((Object)(object)station.m_fuelItem) || station.GetFuel() <= 0f) { return false; } GameObject gameObject = ((Component)station.m_fuelItem).gameObject; string sharedName2 = GetSharedName(gameObject); if (!Object.op_Implicit((Object)(object)gameObject) || string.IsNullOrEmpty(sharedName2)) { return false; } prefab = gameObject; sharedName = sharedName2; cheated = station.m_nview.GetZDO().GetBool(ZDOVars.s_cheated, false) && !PlayerProfile.s_bypassCheatChecks; return true; } private static bool TryGetFireplaceFuel(Fireplace station, out GameObject prefab, out string sharedName) { prefab = null; sharedName = null; if (!Object.op_Implicit((Object)(object)station) || !IsValidView(station.m_nview) || station.m_infiniteFuel || !station.m_canRefill || !Object.op_Implicit((Object)(object)station.m_fuelItem) || StationItemReturn.IsFireplaceExcluded(station) || station.m_nview.GetZDO().GetFloat(ZDOVars.s_fuel, 0f) <= 0f) { return false; } GameObject gameObject = ((Component)station.m_fuelItem).gameObject; string sharedName2 = GetSharedName(gameObject); if (!Object.op_Implicit((Object)(object)gameObject) || string.IsNullOrEmpty(sharedName2)) { return false; } prefab = gameObject; sharedName = sharedName2; return true; } private static bool TryGetSmelterInput(Smelter station, out int queueIndex, out GameObject prefab, out string sharedName) { queueIndex = -1; prefab = null; sharedName = null; if (!Object.op_Implicit((Object)(object)station) || !IsValidView(station.m_nview)) { return false; } int queueSize = station.GetQueueSize(); if (queueSize <= 0) { return false; } ZDO zDO = station.m_nview.GetZDO(); int num = queueSize - 1; string prefabName = zDO.GetString("item" + num, ""); GameObject itemPrefab = GetItemPrefab(prefabName); string sharedName2 = GetSharedName(itemPrefab); if (!Object.op_Implicit((Object)(object)itemPrefab) || string.IsNullOrEmpty(sharedName2)) { return false; } queueIndex = num; prefab = itemPrefab; sharedName = sharedName2; return true; } private static bool TryGetSmelterFuel(Smelter station, out GameObject prefab, out string sharedName) { prefab = null; sharedName = null; if (!Object.op_Implicit((Object)(object)station) || !IsValidView(station.m_nview) || !Object.op_Implicit((Object)(object)station.m_fuelItem) || StationItemReturn.IsSmelterFuelExcluded(station) || station.GetFuel() <= 0f) { return false; } GameObject gameObject = ((Component)station.m_fuelItem).gameObject; string sharedName2 = GetSharedName(gameObject); if (!Object.op_Implicit((Object)(object)gameObject) || string.IsNullOrEmpty(sharedName2)) { return false; } prefab = gameObject; sharedName = sharedName2; return true; } private static bool TryGetFermenterIngredient(Fermenter station, out GameObject prefab, out string sharedName, out bool cheated) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Invalid comparison between Unknown and I4 prefab = null; sharedName = null; cheated = false; if (!Object.op_Implicit((Object)(object)station) || !IsValidView(station.m_nview) || (int)station.GetStatus() != 1) { return false; } float num = StationItemReturn.FermenterIngredientReturnProgressLimit?.Value ?? 0f; if (num > 0f && station.m_fermentationDuration > 0f && station.GetFermentationTime() > (double)(station.m_fermentationDuration * num)) { return false; } int content = station.GetContent(); if (content == 0) { return false; } ItemConversion itemConversion = station.GetItemConversion(content); GameObject val = ((itemConversion != null && Object.op_Implicit((Object)(object)itemConversion.m_from)) ? ((Component)itemConversion.m_from).gameObject : (Object.op_Implicit((Object)(object)ZNetScene.instance) ? ZNetScene.instance.GetPrefab(content) : null)); string sharedName2 = GetSharedName(val); if (!Object.op_Implicit((Object)(object)val) || string.IsNullOrEmpty(sharedName2)) { return false; } prefab = val; sharedName = sharedName2; cheated = station.m_nview.GetZDO().GetBool(ZDOVars.s_cheatedQueued, false) && !PlayerProfile.s_bypassCheatChecks; return true; } private static bool TryGetTurretAmmo(Turret station, out GameObject prefab, out string sharedName) { prefab = null; sharedName = null; if (!Object.op_Implicit((Object)(object)station) || !IsValidView(station.m_nview) || !station.m_returnAmmoOnDestroy || station.m_maxAmmo <= 0 || station.GetAmmo() <= 0) { return false; } GameObject itemPrefab = GetItemPrefab(station.GetAmmoType()); string sharedName2 = GetSharedName(itemPrefab); if (!Object.op_Implicit((Object)(object)itemPrefab) || string.IsNullOrEmpty(sharedName2)) { return false; } prefab = itemPrefab; sharedName = sharedName2; return true; } internal static bool CanReturnCookingItem(CookingStation station, bool checkAccess, out string sharedName) { sharedName = null; int result; if (IsEnabled) { ConfigEntry<bool> cookingStationItemReturnEnabled = StationItemReturn.CookingStationItemReturnEnabled; if (cookingStationItemReturnEnabled != null && cookingStationItemReturnEnabled.Value && (!checkAccess || HasLocalAccess((Component)(object)station))) { result = (TryGetCookingItem(station, out var _, out var _, out sharedName, out var _, out var _, out var _) ? 1 : 0); goto IL_003d; } } result = 0; goto IL_003d; IL_003d: return (byte)result != 0; } internal static bool CanReturnCookingFuel(CookingStation station, bool checkAccess, out string sharedName) { sharedName = null; int result; if (IsEnabled) { ConfigEntry<bool> cookingStationFuelReturnEnabled = StationItemReturn.CookingStationFuelReturnEnabled; if (cookingStationFuelReturnEnabled != null && cookingStationFuelReturnEnabled.Value && (!checkAccess || HasLocalAccess((Component)(object)station))) { result = (TryGetCookingFuel(station, out var _, out sharedName, out var _) ? 1 : 0); goto IL_0037; } } result = 0; goto IL_0037; IL_0037: return (byte)result != 0; } internal static bool CanReturnFireplaceFuel(Fireplace station, bool checkAccess, out string sharedName) { sharedName = null; int result; if (IsEnabled) { ConfigEntry<bool> fireplaceFuelReturnEnabled = StationItemReturn.FireplaceFuelReturnEnabled; if (fireplaceFuelReturnEnabled != null && fireplaceFuelReturnEnabled.Value && (!checkAccess || HasLocalAccess((Component)(object)station))) { result = (TryGetFireplaceFuel(station, out var _, out sharedName) ? 1 : 0); goto IL_0035; } } result = 0; goto IL_0035; IL_0035: return (byte)result != 0; } internal static bool CanReturnSmelterInput(Smelter station, bool checkAccess, out string sharedName) { sharedName = null; int result; if (IsEnabled) { ConfigEntry<bool> smelterInputReturnEnabled = StationItemReturn.SmelterInputReturnEnabled; if (smelterInputReturnEnabled != null && smelterInputReturnEnabled.Value && (!checkAccess || HasLocalAccess((Component)(object)station))) { result = (TryGetSmelterInput(station, out var _, out var _, out sharedName) ? 1 : 0); goto IL_0037; } } result = 0; goto IL_0037; IL_0037: return (byte)result != 0; } internal static bool CanReturnSmelterFuel(Smelter station, bool checkAccess, out string sharedName) { sharedName = null; int result; if (IsEnabled) { ConfigEntry<bool> smelterFuelReturnEnabled = StationItemReturn.SmelterFuelReturnEnabled; if (smelterFuelReturnEnabled != null && smelterFuelReturnEnabled.Value && (!checkAccess || HasLocalAccess((Component)(object)station))) { result = (TryGetSmelterFuel(station, out var _, out sharedName) ? 1 : 0); goto IL_0035; } } result = 0; goto IL_0035; IL_0035: return (byte)result != 0; } internal static bool CanReturnFermenterIngredient(Fermenter station, bool checkAccess, out string sharedName) { sharedName = null; int result; if (IsEnabled) { ConfigEntry<bool> fermenterIngredientReturnEnabled = StationItemReturn.FermenterIngredientReturnEnabled; if (fermenterIngredientReturnEnabled != null && fermenterIngredientReturnEnabled.Value && (!checkAccess || HasLocalAccess((Component)(object)station))) { result = (TryGetFermenterIngredient(station, out var _, out sharedName, out var _) ? 1 : 0); goto IL_0037; } } result = 0; goto IL_0037; IL_0037: return (byte)result != 0; } internal static bool CanReturnTurretAmmo(Turret station, bool checkAccess, out string sharedName) { sharedName = null; int result; if (IsEnabled) { ConfigEntry<bool> turretAmmoReturnEnabled = StationItemReturn.TurretAmmoReturnEnabled; if (turretAmmoReturnEnabled != null && turretAmmoReturnEnabled.Value && (!checkAccess || HasLocalAccess((Component)(object)station))) { result = (TryGetTurretAmmo(station, out var _, out sharedName) ? 1 : 0); goto IL_0035; } } result = 0; goto IL_0035; IL_0035: return (byte)result != 0; } internal static bool TryGetReturnableItem(object source, out string sharedName) { sharedName = null; CookingStation val = (CookingStation)((source is CookingStation) ? source : null); if (val == null) { Fireplace val2 = (Fireplace)((source is Fireplace) ? source : null); if (val2 == null) { Smelter val3 = (Smelter)((source is Smelter) ? source : null); if (val3 == null) { Fermenter val4 = (Fermenter)((source is Fermenter) ? source : null); if (val4 == null) { Turret val5 = (Turret)((source is Turret) ? source : null); if (val5 == null) { Switch val6 = (Switch)((source is Switch) ? source : null); if (val6 != null) { CookingStation val7 = ResolveCookingItemSwitch(val6); if (Object.op_Implicit((Object)(object)val7) && CanReturnCookingItem(val7, checkAccess: true, out sharedName)) { return true; } CookingStation val8 = ResolveCookingFuelSwitch(val6); if (Object.op_Implicit((Object)(object)val8) && CanReturnCookingFuel(val8, checkAccess: true, out sharedName)) { return true; } Smelter val9 = ResolveSmelterInputSwitch(val6); if (Object.op_Implicit((Object)(object)val9) && CanReturnSmelterInput(val9, checkAccess: true, out sharedName)) { return true; } Smelter val10 = ResolveSmelterFuelSwitch(val6); return Object.op_Implicit((Object)(object)val10) && CanReturnSmelterFuel(val10, checkAccess: true, out sharedName); } return false; } return CanReturnTurretAmmo(val5, checkAccess: true, out sharedName); } return CanReturnFermenterIngredient(val4, checkAccess: true, out sharedName); } return CanReturnSmelterInput(val3, checkAccess: true, out sharedName); } return CanReturnFireplaceFuel(val2, checkAccess: true, out sharedName); } return CanReturnCookingItem(val, checkAccess: true, out sharedName); } private static bool SpawnCookingItem(CookingStation station, int slot, GameObject prefab, Vector3 userPoint, bool cheated) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: 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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_0101: 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) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: 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) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_0156: 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_0169: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) if (slot < 0 || slot >= station.m_slots.Length || !Object.op_Implicit((Object)(object)station.m_slots[slot])) { return false; } Transform val = (Object.op_Implicit((Object)(object)station.m_spawnPoint) ? station.m_spawnPoint : station.m_slots[slot]); Vector3 val2; Vector3 position; if (Object.op_Implicit((Object)(object)station.m_spawnPoint)) { val2 = val.forward; position = val.position; } else { val2 = userPoint - val.position; val2.y = 0f; if (((Vector3)(ref val2)).sqrMagnitude <= 0.0001f) { val2 = ((Component)station).transform.forward; val2.y = 0f; } if (((Vector3)(ref val2)).sqrMagnitude <= 0.0001f) { val2 = Vector3.forward; } ((Vector3)(ref val2)).Normalize(); position = val.position + val2 * 0.5f; } if (!CreateItem(prefab, position, val2, station.m_spawnForce, cheated, out var spawnedItem)) { return false; } if (station.m_spawnFullDurability) { spawnedItem.m_itemData.m_durability = spawnedItem.m_itemData.m_shared.m_maxDurability; } station.m_pickEffector.Create(((Component)spawnedItem).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID)); return true; } private static void ReturnCookingItemOnOwner(CookingStation station, Vector3 userPoint) { //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Expected I4, but got Unknown //IL_0042: Unknown result type (might be due to invalid IL or missing references) if (!IsEnabled) { return; } ConfigEntry<bool> cookingStationItemReturnEnabled = StationItemReturn.CookingStationItemReturnEnabled; if (cookingStationItemReturnEnabled != null && cookingStationItemReturnEnabled.Value && IsValidOwner(station.m_nview) && TryGetCookingItem(station, out var slot, out var prefab, out var _, out var cheated, out var author, out var skillCredited) && SpawnCookingItem(station, slot, prefab, userPoint, cheated)) { station.SetSlot(slot, "", 0f, (Status)0, false); station.m_nview.InvokeRPC(ZNetView.Everybody, "RPC_SetSlotVisual", new object[2] { slot, "" }); StationItemReturn.LogInfo($"Returned cooking station item '{((Object)prefab).name}' from slot {slot}."); if (skillCredited && author != 0L && (int)station.m_skill != 0 && ZRoutedRpc.instance != null) { ZRoutedRpc.instance.InvokeRoutedRPC(author, "RPC_SIR_UndoStationSkill", new object[1] { (int)station.m_skill }); } } } private static void ReturnCookingFuelOnOwner(CookingStation station, Vector3 userPoint) { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) if (!IsEnabled) { return; } ConfigEntry<bool> cookingStationFuelReturnEnabled = StationItemReturn.CookingStationFuelReturnEnabled; if (cookingStationFuelReturnEnabled != null && cookingStationFuelReturnEnabled.Value && IsValidOwner(station.m_nview) && TryGetCookingFuel(station, out var prefab, out var _, out var cheated)) { Transform val = (Object.op_Implicit((Object)(object)station.m_addFuelSwitch) ? ((Component)station.m_addFuelSwitch).transform : ((Component)station).transform); if (SpawnItem(prefab, val.position, val.forward, userPoint, 2f, cheated, out var _)) { station.SetFuel(Mathf.Max(0f, station.GetFuel() - 1f)); bool flag = IsCookingStationActive(station); bool flag2 = station.GetFuel() > 0f; station.m_nview.InvokeRPC(ZNetView.Everybody, "RPC_SIR_RefreshCookingStation", new object[2] { flag, flag2 }); StationItemReturn.LogInfo("Returned cooking station fuel '" + ((Object)prefab).name + "'."); } } } private static bool IsCookingStationActive(CookingStation station) { return (station.m_requireFire && station.IsFireLit()) || (station.m_useFuel && station.GetFuel() > 0f && (station.m_useFueldWhileEmpty || station.HaveUncookedItem())); } private static void RefreshCookingStation(CookingStation station, bool active, bool hasFuel) { if (Object.op_Implicit((Object)(object)station)) { station.UpdateVisual(active); if (Object.op_Implicit((Object)(object)station.m_haveFuelObject)) { station.m_haveFuelObject.SetActive(hasFuel); } if (Object.op_Implicit((Object)(object)station.m_cookingObject)) { station.m_cookingObject.SetActive(!station.IsEverythingCooked() && hasFuel && !station.IsEmpty()); } } } private static void ReturnFireplaceFuelOnOwner(Fireplace station, Vector3 userPoint) { //IL_006a: 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) //IL_0075: Unknown result type (might be due to invalid IL or missing references) if (!IsEnabled) { return; } ConfigEntry<bool> fireplaceFuelReturnEnabled = StationItemReturn.FireplaceFuelReturnEnabled; if (fireplaceFuelReturnEnabled != null && fireplaceFuelReturnEnabled.Value && IsValidOwner(station.m_nview) && TryGetFireplaceFuel(station, out var prefab, out var _)) { Transform val = (Object.op_Implicit((Object)(object)station.m_enabledObject) ? station.m_enabledObject.transform : ((Component)station).transform); if (SpawnItem(prefab, val.position, val.forward, userPoint, 2f, cheated: false, out var _)) { ZDO zDO = station.m_nview.GetZDO(); float num = zDO.GetFloat(ZDOVars.s_fuel, 0f); zDO.Set(ZDOVars.s_fuel, Mathf.Max(0f, num - 1f)); station.m_nview.InvokeRPC(ZNetView.Everybody, "RPC_SIR_RefreshFireplace", Array.Empty<object>()); StationItemReturn.LogInfo("Returned fireplace fuel '" + ((Object)prefab).name + "' from '" + station.m_nview.GetPrefabName() + "'."); } } } private static void RefreshFireplace(Fireplace station) { if (Object.op_Implicit((Object)(object)station)) { station.UpdateState(); } } private static void ReturnSmelterInputOnOwner(Smelter station, Vector3 userPoint) { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) if (!IsEnabled) { return; } ConfigEntry<bool> smelterInputReturnEnabled = StationItemReturn.SmelterInputReturnEnabled; if (smelterInputReturnEnabled == null || !smelterInputReturnEnabled.Value || !IsValidOwner(station.m_nview) || !TryGetSmelterInput(station, out var queueIndex, out var prefab, out var _)) { return; } Transform val = (Object.op_Implicit((Object)(object)station.m_addOreSwitch) ? ((Component)station.m_addOreSwitch).transform : ((Component)station).transform); if (SpawnItem(prefab, val.position, val.forward, userPoint, 2f, cheated: false, out var _)) { ZDO zDO = station.m_nview.GetZDO(); zDO.Set("item" + queueIndex, ""); zDO.Set(ZDOVars.s_queued, queueIndex, false); if (queueIndex == 0) { station.SetBakeTimer(0f); zDO.Set(ZDOVars.s_cheatedQueued, false); } BroadcastSmelterRefresh(station); StationItemReturn.LogInfo($"Returned smelter input '{((Object)prefab).name}' from queue index {queueIndex}."); } } private static void ReturnSmelterFuelOnOwner(Smelter station, Vector3 userPoint) { //IL_0068: 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) //IL_0073: Unknown result type (might be due to invalid IL or missing references) if (!IsEnabled) { return; } ConfigEntry<bool> smelterFuelReturnEnabled = StationItemReturn.SmelterFuelReturnEnabled; if (smelterFuelReturnEnabled != null && smelterFuelReturnEnabled.Value && IsValidOwner(station.m_nview) && TryGetSmelterFuel(station, out var prefab, out var _)) { Transform val = (Object.op_Implicit((Object)(object)station.m_addWoodSwitch) ? ((Component)station.m_addWoodSwitch).transform : ((Component)station).transform); if (SpawnItem(prefab, val.position, val.forward, userPoint, 2f, cheated: false, out var _)) { station.SetFuel(Mathf.Max(0f, station.GetFuel() - 1f)); BroadcastSmelterRefresh(station); StationItemReturn.LogInfo("Returned smelter fuel '" + ((Object)prefab).name + "'."); } } } private static void BroadcastSmelterRefresh(Smelter station) { station.m_nview.InvokeRPC(ZNetView.Everybody, "RPC_SIR_RefreshSmelter", new object[3] { station.IsActive(), station.GetFuel() > 0f, station.GetQueueSize() > 0 }); } private static void RefreshSmelter(Smelter station, bool active, bool hasFuel, bool hasInput) { if (Object.op_Implicit((Object)(object)station)) { if (Object.op_Implicit((Object)(object)station.m_enabledObject)) { station.m_enabledObject.SetActive(active); } if (Object.op_Implicit((Object)(object)station.m_disabledObject)) { station.m_disabledObject.SetActive(!active); } if (Object.op_Implicit((Object)(object)station.m_haveFuelObject)) { station.m_haveFuelObject.SetActive(hasFuel); } if (Object.op_Implicit((Object)(object)station.m_haveOreObject)) { station.m_haveOreObject.SetActive(hasInput); } if (Object.op_Implicit((Object)(object)station.m_noOreObject)) { station.m_noOreObject.SetActive(!hasInput); } station.SetAnimation(active); } } private static void ReturnFermenterIngredientOnOwner(Fermenter station, Vector3 userPoint) { //IL_0067: 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) //IL_0072: Unknown result type (might be due to invalid IL or missing references) if (!IsEnabled) { return; } ConfigEntry<bool> fermenterIngredientReturnEnabled = StationItemReturn.FermenterIngredientReturnEnabled; if (fermenterIngredientReturnEnabled != null && fermenterIngredientReturnEnabled.Value && IsValidOwner(station.m_nview) && TryGetFermenterIngredient(station, out var prefab, out var _, out var cheated)) { Transform val = (Object.op_Implicit((Object)(object)station.m_outputPoint) ? station.m_outputPoint : ((Component)station).transform); if (SpawnItem(prefab, val.position, val.forward, userPoint, 2f, cheated, out var _)) { ZDO zDO = station.m_nview.GetZDO(); zDO.Set(ZDOVars.s_content, 0, false); zDO.Set(ZDOVars.s_startTime, 0L); zDO.Set(ZDOVars.s_cheatedQueued, false); station.m_nview.InvokeRPC(ZNetView.Everybody, "RPC_SIR_RefreshFermenter", Array.Empty<object>()); StationItemReturn.LogInfo("Returned fermenter ingredient '" + ((Object)prefab).name + "'."); } } } private static void RefreshFermenter(Fermenter station) { if (Object.op_Implicit((Object)(object)station)) { if (Object.op_Implicit((Object)(object)station.m_fermentingObject)) { station.m_fermentingObject.SetActive(false); } if (Object.op_Implicit((Object)(object)station.m_readyObject)) { station.m_readyObject.SetActive(false); } if (Object.op_Implicit((Object)(object)station.m_topObject)) { station.m_topObject.SetActive(false); } } } private static void ReturnTurretAmmoOnOwner(Turret station, Vector3 userPoint) { //IL_004e: 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) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) if (!IsEnabled) { return; } ConfigEntry<bool> turretAmmoReturnEnabled = StationItemReturn.TurretAmmoReturnEnabled; if (turretAmmoReturnEnabled != null && turretAmmoReturnEnabled.Value && IsValidOwner(station.m_nview) && TryGetTurretAmmo(station, out var prefab, out var _) && SpawnItem(prefab, ((Component)station).transform.position + Vector3.up, ((Component)station).transform.forward, userPoint, 2f, cheated: false, out var _)) { int num = Mathf.Max(0, station.GetAmmo() - 1); ZDO zDO = station.m_nview.GetZDO(); zDO.Set(ZDOVars.s_ammo, num, false); string text = station.GetAmmoType(); if (num == 0 && !Object.op_Implicit((Object)(object)station.m_defaultAmmo)) { zDO.Set(ZDOVars.s_ammoType, ""); text = ""; } station.m_nview.InvokeRPC(ZNetView.Everybody, "RPC_SIR_RefreshTurret", new object[2] { num, text }); StationItemReturn.LogInfo($"Returned turret ammunition '{((Object)prefab).name}', remaining: {num}."); } } private static void RefreshTurret(Turret station, int remainingAmmo, string ammoType) { //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) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)station)) { return; } station.m_lastAmmo = null; bool flag = remainingAmmo > 0 && !station.IsCoolingDown(); foreach (AmmoType item in station.m_allowedAmmo) { if (Object.op_Implicit((Object)(object)item.m_visual)) { item.m_visual.SetActive(flag && Object.op_Implicit((Object)(object)item.m_ammo) && ((Object)item.m_ammo).name == ammoType); } } } private static bool IsMatchingCookingSlot(CookingStation station, ZDO zdo, int slot, long sender, string expectedPrefabName) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (slot < 0 || station.m_slots == null || slot >= station.m_slots.Length) { return false; } string text = default(string); float num = default(float); Status val = default(Status); bool flag = default(bool); station.GetSlot(slot, ref text, ref num, ref val, ref flag); return text == expectedPrefabName && (int)val == 0 && zdo.GetLong(CookingAuthorKey(slot), 0L) == sender; } private static void MarkCookingSkillCreditOnOwner(CookingStation station, long sender, int requestedSlot, string expectedPrefabName) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 if (!IsValidOwner(station.m_nview) || (int)station.m_skill == 0 || string.IsNullOrEmpty(expectedPrefabName)) { return; } ZDO zDO = station.m_nview.GetZDO(); long num = zDO.GetLong("SIR_LastCookingAuthor", 0L); int num2 = zDO.GetInt("SIR_LastCookingSlot", -1); int num3 = (IsMatchingCookingSlot(station, zDO, num2, sender, expectedPrefabName) ? num2 : requestedSlot); if (IsMatchingCookingSlot(station, zDO, num3, sender, expectedPrefabName)) { zDO.Set(CookingSkillKey(num3), true); if (num == sender && num2 == num3) { zDO.Set("SIR_LastCookingAuthor", 0L); zDO.Set("SIR_LastCookingSlot", -1); } } } private static void UndoStationSkill(long sender, int skill) { if (Enum.IsDefined(typeof(SkillType), skill) && skill != 0 && Object.op_Implicit((Object)(object)Player.m_localPlayer)) { ((Character)Player.m_localPlayer).RaiseSkill((SkillType)skill, -0.4f); } } } }