Decompiled source of ImprovedStations v0.1.1

ImprovedStations.dll

Decompiled 2 hours ago
using System;
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 ImprovedStations.Logic;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("0.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 ImprovedStations
{
	[HarmonyPatch(typeof(Plant), "GetHoverText")]
	internal static class PlantTimerPatch
	{
		private static Func<Plant, float> GetGrowTime;

		private static bool Prepare()
		{
			MethodInfo methodInfo = AccessTools.Method(typeof(Plant), "GetGrowTime", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				ImprovedStationsPlugin.Log.LogError((object)"Plant.GetGrowTime not found; plant timers disabled.");
				return false;
			}
			GetGrowTime = AccessTools.MethodDelegate<Func<Plant, float>>(methodInfo, (object)null, true);
			return true;
		}

		[HarmonyPriority(200)]
		private static void Postfix(Plant __instance, ref string __result, ZNetView ___m_nview, Status ___m_status)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (!ImprovedStationsConfig.Plants.Value || string.IsNullOrEmpty(__result) || (Object)(object)___m_nview == (Object)null || !___m_nview.IsValid() || (int)___m_status != 0 || (Object)(object)ZNet.instance == (Object)null)
			{
				return;
			}
			ZDO zDO = ___m_nview.GetZDO();
			if (zDO != null)
			{
				long num = zDO.GetLong(ZDOVars.s_plantTime, 0L);
				if (num != 0L)
				{
					string line = StationForecasts.ReadyLine((ZNet.instance.GetTime() - new DateTime(num)).TotalSeconds, GetGrowTime(__instance));
					__result = HoverText.InsertAfterFirstLine(__result, line);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Fireplace), "GetHoverText")]
	internal static class FireplaceTimerPatch
	{
		[HarmonyPriority(200)]
		private static void Postfix(Fireplace __instance, ref string __result, ZNetView ___m_nview)
		{
			if (ImprovedStationsConfig.Fireplaces.Value && !string.IsNullOrEmpty(__result) && !((Object)(object)___m_nview == (Object)null) && ___m_nview.IsValid() && !__instance.m_infiniteFuel && __instance.IsBurning())
			{
				ZDO zDO = ___m_nview.GetZDO();
				if (zDO != null)
				{
					string line = StationForecasts.FuelLine(zDO.GetFloat(ZDOVars.s_fuel, 0f), __instance.m_secPerFuel);
					__result = HoverText.InsertAfterFirstLine(__result, line);
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class ShieldGeneratorTimerPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(ShieldGenerator), "GetHoverText", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(ShieldGenerator), "OnHoverAddFuel", (Type[])null, (Type[])null);
		}

		[HarmonyPriority(200)]
		private static void Postfix(ShieldGenerator __instance, ref string __result, ZNetView ___m_nview)
		{
			if (!ImprovedStationsConfig.ShieldGenerators.Value || string.IsNullOrEmpty(__result) || (Object)(object)___m_nview == (Object)null || !___m_nview.IsValid() || !__instance.m_enableAttack || (Object)(object)ZNet.instance == (Object)null)
			{
				return;
			}
			ZDO zDO = ___m_nview.GetZDO();
			if (zDO != null)
			{
				long num = zDO.GetLong(ZDOVars.s_startTime, 0L);
				if (num > 0)
				{
					string line = StationForecasts.ReadyLine((ZNet.instance.GetTime() - new DateTime(num)).TotalSeconds, __instance.m_attackChargeTime);
					__result = HoverText.InsertAfterFirstLine(__result, line);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Trap), "GetHoverText")]
	internal static class TrapTimerPatch
	{
		[HarmonyPriority(200)]
		private static void Postfix(Trap __instance, ref string __result, ZNetView ___m_nview)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			if (ImprovedStationsConfig.Traps.Value && !string.IsNullOrEmpty(__result) && !((Object)(object)___m_nview == (Object)null) && ___m_nview.IsValid() && !((Object)(object)ZNet.instance == (Object)null) && __instance.IsCoolingDown() && !__instance.IsArmed() && PrivateArea.CheckAccess(((Component)__instance).transform.position, 0f, false, false))
			{
				ZDO zDO = ___m_nview.GetZDO();
				if (zDO != null)
				{
					string line = StationForecasts.ReadyLine(ZNet.instance.GetTimeSeconds() - (double)zDO.GetFloat(ZDOVars.s_triggered, 0f), __instance.m_rearmCooldown);
					__result = HoverText.InsertAfterFirstLine(__result, line);
				}
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "UpdateRecipe")]
	internal static class BulkCraftPatch
	{
		private static float? _vanillaDuration;

		private static void Prefix(InventoryGui __instance)
		{
			if (!_vanillaDuration.HasValue)
			{
				_vanillaDuration = __instance.m_multiCraftDuration;
			}
			__instance.m_multiCraftDuration = BulkCraftRules.Duration(ImprovedStationsConfig.BulkEnabled.Value, ImprovedStationsConfig.BulkCraftSeconds.Value, _vanillaDuration.Value);
		}
	}
	[HarmonyPatch]
	internal static class CookingTimerPatch
	{
		private static Func<CookingStation, bool> IsFireLit;

		private static bool Prepare()
		{
			MethodInfo methodInfo = AccessTools.Method(typeof(CookingStation), "IsFireLit", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				ImprovedStationsPlugin.Log.LogError((object)"CookingStation.IsFireLit not found; cooking timers disabled.");
				return false;
			}
			IsFireLit = AccessTools.MethodDelegate<Func<CookingStation, bool>>(methodInfo, (object)null, true);
			return true;
		}

		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(CookingStation), "HoverText", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(CookingStation), "OnHoverFuelSwitch", (Type[])null, (Type[])null);
		}

		[HarmonyPriority(200)]
		private static void Postfix(CookingStation __instance, ref string __result, ZNetView ___m_nview)
		{
			if (!ImprovedStationsConfig.CookingStations.Value || string.IsNullOrEmpty(__result) || (Object)(object)___m_nview == (Object)null || !___m_nview.IsValid())
			{
				return;
			}
			Transform[] slots = __instance.m_slots;
			if (slots == null || slots.Length == 0)
			{
				return;
			}
			ZDO zDO = ___m_nview.GetZDO();
			if (zDO == null)
			{
				return;
			}
			List<CookSlot> list = null;
			bool flag = false;
			for (int i = 0; i < slots.Length; i++)
			{
				string text = zDO.GetString("slot" + i, "");
				if (string.IsNullOrEmpty(text))
				{
					continue;
				}
				int num = zDO.GetInt("slotstatus" + i, 0);
				if (num == 2)
				{
					continue;
				}
				if (num == 0)
				{
					flag = true;
				}
				ItemConversion val = FindConversion(__instance, text);
				if (val != null)
				{
					if (list == null)
					{
						list = new List<CookSlot>();
					}
					list.Add(new CookSlot
					{
						Status = num,
						Cooked = zDO.GetFloat("slot" + i, 0f),
						CookTime = val.m_cookTime
					});
				}
			}
			if (list != null || flag)
			{
				float num2 = zDO.GetFloat(ZDOVars.s_fuel, 0f);
				bool flag2 = (__instance.m_requireFire && IsFireLit(__instance)) || (__instance.m_useFuel && num2 > 0f && (__instance.m_useFueldWhileEmpty || flag));
				__result = HoverText.InsertAfterFirstLine(line: (!flag2 && flag) ? StationForecasts.PausedLine((__instance.m_useFuel && num2 <= 0f) ? "no fuel" : "needs fire") : ((!flag2) ? null : ((list != null) ? StationForecasts.CookingLine(list, __instance.m_canOvercookItems) : null)), hover: __result);
			}
		}

		private static ItemConversion FindConversion(CookingStation station, string itemName)
		{
			List<ItemConversion> conversion = station.m_conversion;
			if (conversion == null)
			{
				return null;
			}
			for (int i = 0; i < conversion.Count; i++)
			{
				ItemConversion val = conversion[i];
				if (val != null && (((Object)(object)val.m_from != (Object)null && ((Object)((Component)val.m_from).gameObject).name == itemName) || ((Object)(object)val.m_to != (Object)null && ((Object)((Component)val.m_to).gameObject).name == itemName)))
				{
					return val;
				}
			}
			return null;
		}
	}
	[HarmonyPatch(typeof(Fermenter), "GetHoverText")]
	internal static class FermenterTimerPatch
	{
		[HarmonyPriority(200)]
		private static void Postfix(Fermenter __instance, ref string __result, ZNetView ___m_nview, bool ___m_exposed, bool ___m_hasRoof)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			if (ImprovedStationsConfig.Fermenters.Value && !((Object)(object)___m_nview == (Object)null) && ___m_nview.IsValid() && !((Object)(object)ZNet.instance == (Object)null || ___m_exposed) && ___m_hasRoof && PrivateArea.CheckAccess(((Component)__instance).transform.position, 0f, false, false))
			{
				ZDO zDO = ___m_nview.GetZDO();
				if (zDO.GetInt(ZDOVars.s_content, 0) != 0)
				{
					long num = zDO.GetLong(ZDOVars.s_startTime, 0L);
					string line = StationForecasts.ReadyLine((num == 0L) ? (-1.0) : (ZNet.instance.GetTime() - new DateTime(num)).TotalSeconds, __instance.m_fermentationDuration);
					__result = HoverText.InsertAfterFirstLine(__result, line);
				}
			}
		}
	}
	internal static class ImprovedStationsConfig
	{
		public static ConfigEntry<bool> BulkEnabled;

		public static ConfigEntry<float> BulkCraftSeconds;

		public static ConfigEntry<bool> Fermenters;

		public static ConfigEntry<bool> Smelters;

		public static ConfigEntry<bool> CookingStations;

		public static ConfigEntry<bool> Beehives;

		public static ConfigEntry<bool> SapCollectors;

		public static ConfigEntry<bool> Plants;

		public static ConfigEntry<bool> Fireplaces;

		public static ConfigEntry<bool> ShieldGenerators;

		public static ConfigEntry<bool> Traps;

		public static void Bind(ConfigFile config)
		{
			BulkEnabled = config.Bind<bool>("1 - Bulk crafting", "Enabled", true, AdminOnly("Shift+Craft makes the whole batch in one short progress bar."));
			BulkCraftSeconds = config.Bind<float>("1 - Bulk crafting", "BulkCraftSeconds", 2f, AdminOnly("Seconds one Shift+Craft bulk craft takes (vanilla is 6).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 6f)));
			Fermenters = config.Bind<bool>("2 - Station timers", "Fermenters", true, "Show the time left on fermenters in the hover text.");
			Smelters = config.Bind<bool>("2 - Station timers", "Smelters", true, "Show the time left on smelters, kilns and furnaces in the hover text.");
			CookingStations = config.Bind<bool>("2 - Station timers", "CookingStations", true, "Show the time left on cooking stations and ovens in the hover text.");
			Beehives = config.Bind<bool>("2 - Station timers", "Beehives", true, "Show the time left on beehives in the hover text.");
			SapCollectors = config.Bind<bool>("2 - Station timers", "SapCollectors", true, "Show the time left on sap collectors in the hover text.");
			Plants = config.Bind<bool>("2 - Station timers", "Plants", true, "Show the time until planted crops are ripe in the hover text.");
			Fireplaces = config.Bind<bool>("2 - Station timers", "Fireplaces", true, "Show how long the fuel lasts on fireplaces, torches and braziers in the hover text.");
			ShieldGenerators = config.Bind<bool>("2 - Station timers", "ShieldGenerators", true, "Show the attack charge time on shield generators in the hover text.");
			Traps = config.Bind<bool>("2 - Station timers", "Traps", true, "Show the re-arm time on traps in the hover text.");
		}

		private static ConfigDescription AdminOnly(string description, AcceptableValueBase range = null)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			return new ConfigDescription(description, range, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} });
		}
	}
	[BepInPlugin("com.robert.improvedstations", "ImprovedStations", "0.1.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class ImprovedStationsPlugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			ImprovedStationsConfig.Bind(((BaseUnityPlugin)this).Config);
			_harmony = new Harmony("com.robert.improvedstations");
			Type[] typesFromAssembly = AccessTools.GetTypesFromAssembly(typeof(ImprovedStationsPlugin).Assembly);
			foreach (Type type in typesFromAssembly)
			{
				try
				{
					_harmony.CreateClassProcessor(type).Patch();
				}
				catch (Exception arg)
				{
					Log.LogError((object)$"Failed to apply patch {type.Name}: {arg}");
				}
			}
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	internal static class ProducerProgress
	{
		public static float Current(ZDO zdo)
		{
			float num = zdo.GetFloat(ZDOVars.s_product, 0f);
			long num2 = zdo.GetLong(ZDOVars.s_lastTime, 0L);
			if (num2 > 0 && (Object)(object)ZNet.instance != (Object)null)
			{
				num += (float)Math.Max(0.0, (ZNet.instance.GetTime() - new DateTime(num2)).TotalSeconds);
			}
			return num;
		}
	}
	[HarmonyPatch(typeof(Beehive), "GetHoverText")]
	internal static class BeehiveTimerPatch
	{
		private const float CacheSeconds = 2f;

		private static Func<Beehive, bool> CheckBiome;

		private static Func<Beehive, bool> HaveFreeSpace;

		private static int cachedId;

		private static float cachedAt = float.NegativeInfinity;

		private static bool cachedBiomeOk;

		private static bool cachedSpaceOk;

		private static bool Prepare()
		{
			MethodInfo methodInfo = AccessTools.Method(typeof(Beehive), "CheckBiome", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(Beehive), "HaveFreeSpace", (Type[])null, (Type[])null);
			if (methodInfo == null || methodInfo2 == null)
			{
				ImprovedStationsPlugin.Log.LogError((object)"Beehive.CheckBiome or Beehive.HaveFreeSpace not found; beehive timers disabled.");
				return false;
			}
			CheckBiome = AccessTools.MethodDelegate<Func<Beehive, bool>>(methodInfo, (object)null, true);
			HaveFreeSpace = AccessTools.MethodDelegate<Func<Beehive, bool>>(methodInfo2, (object)null, true);
			return true;
		}

		[HarmonyPriority(200)]
		private static void Postfix(Beehive __instance, ref string __result, ZNetView ___m_nview)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			if (!ImprovedStationsConfig.Beehives.Value || string.IsNullOrEmpty(__result) || (Object)(object)___m_nview == (Object)null || !___m_nview.IsValid() || !PrivateArea.CheckAccess(((Component)__instance).transform.position, 0f, false, false))
			{
				return;
			}
			ZDO zDO = ___m_nview.GetZDO();
			if (zDO == null)
			{
				return;
			}
			int num = zDO.GetInt(ZDOVars.s_level, 0);
			if (num < __instance.m_maxHoney)
			{
				int instanceID = ((Object)__instance).GetInstanceID();
				if (instanceID != cachedId || Time.time - cachedAt > 2f)
				{
					cachedBiomeOk = CheckBiome(__instance);
					cachedSpaceOk = cachedBiomeOk && HaveFreeSpace(__instance);
					cachedId = instanceID;
					cachedAt = Time.time;
				}
				__result = HoverText.InsertAfterFirstLine(line: (!cachedBiomeOk) ? StationForecasts.PausedLine("wrong biome") : (cachedSpaceOk ? StationForecasts.ProducerLine(__instance.m_secPerUnit, ProducerProgress.Current(zDO), num, __instance.m_maxHoney) : StationForecasts.PausedLine("needs open space")), hover: __result);
			}
		}
	}
	[HarmonyPatch(typeof(SapCollector), "GetHoverText")]
	internal static class SapCollectorTimerPatch
	{
		[HarmonyPriority(200)]
		private static void Postfix(SapCollector __instance, ref string __result, ZNetView ___m_nview, ResourceRoot ___m_root)
		{
			if (!ImprovedStationsConfig.SapCollectors.Value || string.IsNullOrEmpty(__result) || (Object)(object)___m_nview == (Object)null || !___m_nview.IsValid() || (Object)(object)___m_root == (Object)null)
			{
				return;
			}
			ZDO zDO = ___m_nview.GetZDO();
			if (zDO != null)
			{
				int num = zDO.GetInt(ZDOVars.s_level, 0);
				if (num < __instance.m_maxLevel)
				{
					string line = ((!___m_root.CanDrain(1f)) ? StationForecasts.PausedLine("no sap left") : StationForecasts.ProducerLine(__instance.m_secPerUnit, ProducerProgress.Current(zDO), num, __instance.m_maxLevel));
					__result = HoverText.InsertAfterFirstLine(__result, line);
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class SmelterTimerPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(Smelter), "OnHoverAddOre", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(Smelter), "OnHoverAddFuel", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(Smelter), "OnHoverEmptyOre", (Type[])null, (Type[])null);
		}

		[HarmonyPriority(200)]
		private static void Postfix(Smelter __instance, ref string __result, ZNetView ___m_nview, bool ___m_haveRoof, bool ___m_blockedSmoke)
		{
			if (ImprovedStationsConfig.Smelters.Value && !((Object)(object)___m_nview == (Object)null) && ___m_nview.IsValid())
			{
				ZDO zDO = ___m_nview.GetZDO();
				Windmill windmill = __instance.m_windmill;
				SmelterState smelterState = new SmelterState
				{
					SecPerProduct = __instance.m_secPerProduct,
					BakeTimer = zDO.GetFloat(ZDOVars.s_bakeTimer, 0f),
					Queued = zDO.GetInt(ZDOVars.s_queued, 0),
					NoInputNeeded = (__instance.m_maxOre == 0),
					UsesFuel = (__instance.m_maxFuel > 0),
					Fuel = zDO.GetFloat(ZDOVars.s_fuel, 0f),
					FuelPerProduct = __instance.m_fuelPerProduct,
					Power = (((Object)(object)windmill != (Object)null) ? ((double)windmill.GetPowerOutput()) : 1.0),
					Approximate = ((Object)(object)windmill != (Object)null)
				};
				__result = HoverText.InsertAfterFirstLine(line: (smelterState.Queued <= 0 && !smelterState.NoInputNeeded) ? null : ((__instance.m_requiresRoof && !___m_haveRoof) ? StationForecasts.PausedLine("needs roof") : (___m_blockedSmoke ? StationForecasts.PausedLine("smoke blocked") : ((smelterState.UsesFuel && smelterState.Fuel <= 0.0) ? StationForecasts.PausedLine("no fuel") : ((!((Object)(object)windmill != (Object)null) || !(smelterState.Power <= 0.0)) ? StationForecasts.SmelterLine(smelterState) : StationForecasts.PausedLine("no wind or covered"))))), hover: __result);
			}
		}
	}
	internal static class ModInfo
	{
		public const string Guid = "com.robert.improvedstations";

		public const string Name = "ImprovedStations";

		public const string Version = "0.1.1";
	}
}
namespace ImprovedStations.Logic
{
	public static class BulkCraftRules
	{
		public static float Duration(bool enabled, float configured, float vanilla)
		{
			if (!enabled || !(configured > 0f))
			{
				return vanilla;
			}
			return configured;
		}
	}
	public static class HoverText
	{
		public static string InsertAfterFirstLine(string hover, string line)
		{
			if (string.IsNullOrEmpty(hover) || string.IsNullOrEmpty(line))
			{
				return hover;
			}
			int num = hover.IndexOf('\n');
			if (num < 0)
			{
				return hover + "\n" + line;
			}
			return hover.Substring(0, num) + "\n" + line + hover.Substring(num);
		}
	}
	public sealed class SmelterState
	{
		public double SecPerProduct;

		public double BakeTimer;

		public double Fuel;

		public double Power;

		public int Queued;

		public int FuelPerProduct;

		public bool NoInputNeeded;

		public bool UsesFuel;

		public bool Approximate;
	}
	public sealed class CookSlot
	{
		public const int NotDone = 0;

		public const int Done = 1;

		public const int Burnt = 2;

		public int Status;

		public double Cooked;

		public double CookTime;
	}
	public static class StationForecasts
	{
		public static string CookingLine(IEnumerable<CookSlot> slots, bool canOvercook)
		{
			bool flag = false;
			bool flag2 = false;
			double num = 0.0;
			double num2 = 0.0;
			double num3 = 0.0;
			foreach (CookSlot slot in slots)
			{
				if (slot.Status == 0)
				{
					double num4 = slot.CookTime - slot.Cooked;
					if (!flag || num4 < num)
					{
						num = num4;
					}
					if (!flag || num4 > num2)
					{
						num2 = num4;
					}
					flag = true;
				}
				else if (slot.Status == 1 && canOvercook)
				{
					double num5 = slot.CookTime * 2.0 - slot.Cooked;
					if (!flag2 || num5 < num3)
					{
						num3 = num5;
					}
					flag2 = true;
				}
			}
			string text = null;
			if (flag)
			{
				text = ((TimerFormat.Duration(num) == TimerFormat.Duration(num2)) ? ("Done in " + TimerFormat.Duration(num)) : ("Next in " + TimerFormat.Duration(num) + ", all in " + TimerFormat.Duration(num2)));
			}
			string text2 = (flag2 ? ("<color=orange>Burns in " + TimerFormat.Duration(num3) + "</color>") : null);
			if (text != null && text2 != null)
			{
				return text + "\n" + text2;
			}
			return text ?? text2;
		}

		public static string SmelterLine(SmelterState s)
		{
			if (s.SecPerProduct <= 0.0 || s.Power <= 0.0)
			{
				return null;
			}
			if (!s.NoInputNeeded && s.Queued <= 0)
			{
				return null;
			}
			double secPerProduct = s.SecPerProduct;
			double num = Math.Max(0.0, secPerProduct - s.BakeTimer);
			int num2 = (s.NoInputNeeded ? 1 : s.Queued);
			double num3 = num + (double)(num2 - 1) * secPerProduct;
			string prefix = (s.Approximate ? "~" : "");
			Func<double, string> func = (double progress) => prefix + TimerFormat.Duration(progress / s.Power);
			if (s.NoInputNeeded)
			{
				return "Next in " + func(num);
			}
			if (s.UsesFuel && s.FuelPerProduct > 0)
			{
				double num4 = s.Fuel * secPerProduct / (double)s.FuelPerProduct;
				if (num4 < num3)
				{
					int num5 = ((!(num4 < num)) ? (1 + (int)Math.Floor((num4 - num) / secPerProduct)) : 0);
					string text = " lasts " + func(num4) + " (" + num5 + " of " + num2 + " finish)";
					if (num5 == 0)
					{
						return "Fuel" + text;
					}
					return "Next in " + func(num) + ", fuel" + text;
				}
			}
			if (num2 == 1)
			{
				return "Done in " + func(num);
			}
			return "Next in " + func(num) + ", all in " + func(num3);
		}

		public static string ReadyLine(double elapsed, double duration)
		{
			if (elapsed < 0.0 || elapsed > duration)
			{
				return null;
			}
			return "Ready in " + TimerFormat.Duration(duration - elapsed);
		}

		public static string FuelLine(double fuel, double secPerFuel)
		{
			if (fuel <= 0.0 || secPerFuel <= 0.0)
			{
				return null;
			}
			return "Fuel lasts " + TimerFormat.Duration(fuel * secPerFuel);
		}

		public static string ProducerLine(double secPerUnit, double product, int level, int maxLevel)
		{
			if (level >= maxLevel)
			{
				return null;
			}
			double num = Math.Max(0.0, secPerUnit - product);
			int num2 = maxLevel - level - 1;
			if (num2 <= 0)
			{
				return "Next in " + TimerFormat.Duration(num);
			}
			double seconds = num + (double)num2 * secPerUnit;
			return "Next in " + TimerFormat.Duration(num) + ", full in " + TimerFormat.Duration(seconds);
		}

		public static string PausedLine(string reason)
		{
			return "<color=orange>Paused: " + reason + "</color>";
		}
	}
	public static class TimerFormat
	{
		public static string Duration(double seconds)
		{
			long num = (long)Math.Ceiling(Math.Max(0.0, seconds));
			if (num < 60)
			{
				return num + "s";
			}
			if (num < 3600)
			{
				return num / 60 + "m " + (num % 60).ToString("00") + "s";
			}
			return num / 3600 + "h " + (num % 3600 / 60).ToString("00") + "m";
		}
	}
}