Decompiled source of TimedCraftSpeed v1.0.5

plugins/TimedCraftSpeed.dll

Decompiled 6 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
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: AssemblyCompany("TimedCraftSpeed")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.5.0")]
[assembly: AssemblyInformationalVersion("1.0.5")]
[assembly: AssemblyProduct("TimedCraftSpeed")]
[assembly: AssemblyTitle("TimedCraftSpeed")]
[assembly: AssemblyVersion("1.0.5.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 TimedCraftSpeed
{
	internal sealed class ConfigurationManagerAttributes
	{
		public string DispName;
	}
	[BepInPlugin("local.timedcraftspeed", "Timed Craft Speed", "1.0.5")]
	public sealed class Plugin : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(Smelter), "Awake")]
		private static class SmelterAwakePatch
		{
			[HarmonyPostfix]
			[HarmonyPriority(0)]
			private static void Postfix(Smelter __instance)
			{
				if ((Object)(object)_instance != (Object)null)
				{
					_instance.ApplySmelter(__instance);
				}
			}
		}

		[HarmonyPatch(typeof(Fermenter), "Awake")]
		private static class FermenterAwakePatch
		{
			[HarmonyPostfix]
			[HarmonyPriority(0)]
			private static void Postfix(Fermenter __instance)
			{
				if ((Object)(object)_instance != (Object)null)
				{
					_instance.ApplyFermenter(__instance);
				}
			}
		}

		[HarmonyPatch(typeof(CookingStation), "Awake")]
		private static class CookingStationAwakePatch
		{
			[HarmonyPostfix]
			[HarmonyPriority(0)]
			private static void Postfix(CookingStation __instance)
			{
				if ((Object)(object)_instance != (Object)null)
				{
					_instance.ApplyCookingStation(__instance);
				}
			}
		}

		private sealed class ReferenceComparer : IEqualityComparer<object>
		{
			public static readonly ReferenceComparer Instance = new ReferenceComparer();

			public new bool Equals(object x, object y)
			{
				return x == y;
			}

			public int GetHashCode(object obj)
			{
				return RuntimeHelpers.GetHashCode(obj);
			}
		}

		public const string PluginGuid = "local.timedcraftspeed";

		public const string PluginName = "Timed Craft Speed";

		public const string PluginVersion = "1.0.5";

		private const string ConfigSection = "Multiplicateurs de vitesse";

		private static Plugin _instance;

		private Harmony _harmony;

		private float _nextLabelRefresh;

		private static readonly Dictionary<string, ConfigEntry<float>> Multipliers = new Dictionary<string, ConfigEntry<float>>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, ConfigurationManagerAttributes> DisplayAttributes = new Dictionary<string, ConfigurationManagerAttributes>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, string> EnglishNames = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
		{
			{ "smelter", "Smelter" },
			{ "charcoal_kiln", "Charcoal Kiln" },
			{ "blastfurnace", "Blast Furnace" },
			{ "windmill", "Windmill" },
			{ "piece_spinningwheel", "Spinning Wheel" },
			{ "eitrrefinery", "Eitr Refinery" },
			{ "fermenter", "Fermenter" },
			{ "piece_cookingstation", "Cooking Station" },
			{ "piece_cookingstation_iron", "Iron Cooking Station" },
			{ "piece_oven", "Stone Oven" },
			{ "piece_FrostKiln", "Frigid Kiln" },
			{ "piece_FrostFoundry", "Frost Foundry" }
		};

		private static readonly Dictionary<string, string> LocalizationTokens = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
		{
			{ "smelter", "$piece_smelter" },
			{ "charcoal_kiln", "$piece_charcoalkiln" },
			{ "blastfurnace", "$piece_blastfurnace" },
			{ "windmill", "$piece_windmill" },
			{ "piece_spinningwheel", "$piece_spinningwheel" },
			{ "eitrrefinery", "$piece_eitrrefinery" },
			{ "fermenter", "$piece_fermenter" },
			{ "piece_cookingstation", "$piece_cookingstation" },
			{ "piece_cookingstation_iron", "$piece_cookingstation_iron" },
			{ "piece_oven", "$piece_oven" },
			{ "piece_FrostKiln", "$piece_frostkiln" },
			{ "piece_FrostFoundry", "$piece_frostfoundry" }
		};

		private static readonly Dictionary<string, string> LegacyNames = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
		{
			{ "smelter", "Fonderie" },
			{ "charcoal_kiln", "Four a charbon" },
			{ "blastfurnace", "Haut fourneau" },
			{ "windmill", "Moulin" },
			{ "piece_spinningwheel", "Rouet" },
			{ "eitrrefinery", "Raffinerie d'Eitr" },
			{ "fermenter", "Fermenteur" },
			{ "piece_cookingstation", "Station de cuisson" },
			{ "piece_cookingstation_iron", "Station de cuisson en fer" },
			{ "piece_oven", "Four en pierre" },
			{ "piece_FrostKiln", "Four glacial" },
			{ "piece_FrostFoundry", "Fonderie du givre" }
		};

		private static readonly Dictionary<string, float> FloatBaselines = new Dictionary<string, float>();

		private static readonly Dictionary<object, float> ConversionBaselines = new Dictionary<object, float>(ReferenceComparer.Instance);

		private void Awake()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			_instance = this;
			RegisterDefaultSettings();
			_harmony = new Harmony("local.timedcraftspeed");
			_harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Timed Craft Speed actif.");
		}

		private void Update()
		{
			if (!(Time.unscaledTime < _nextLabelRefresh))
			{
				_nextLabelRefresh = Time.unscaledTime + 1f;
				RefreshLocalizedLabels();
			}
		}

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

		private void RegisterDefaultSettings()
		{
			EnsureMultiplier("smelter");
			EnsureMultiplier("charcoal_kiln");
			EnsureMultiplier("blastfurnace");
			EnsureMultiplier("windmill");
			EnsureMultiplier("piece_spinningwheel");
			EnsureMultiplier("eitrrefinery");
			EnsureMultiplier("fermenter");
			EnsureMultiplier("piece_cookingstation");
			EnsureMultiplier("piece_cookingstation_iron");
			EnsureMultiplier("piece_oven");
			EnsureMultiplier("piece_FrostKiln");
			EnsureMultiplier("piece_FrostFoundry");
		}

		private ConfigEntry<float> EnsureMultiplier(string prefabName)
		{
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected O, but got Unknown
			prefabName = NormalizePrefabName(prefabName);
			if (string.IsNullOrEmpty(prefabName))
			{
				return null;
			}
			if (Multipliers.TryGetValue(prefabName, out var value))
			{
				return value;
			}
			string englishName = GetEnglishName(prefabName);
			if (!LegacyNames.TryGetValue(prefabName, out var value2))
			{
				value2 = englishName;
			}
			string text = SanitizeConfigKey(value2 + " - " + prefabName);
			ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes
			{
				DispName = englishName
			};
			ConfigEntry<float> val = ((BaseUnityPlugin)this).Config.Bind<float>("Multiplicateurs de vitesse", text, 1f, new ConfigDescription("Multiplicateur de vitesse.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 20f), new object[1] { configurationManagerAttributes }));
			Multipliers[prefabName] = val;
			DisplayAttributes[prefabName] = configurationManagerAttributes;
			val.SettingChanged += delegate
			{
				RefreshLiveMachines();
			};
			return val;
		}

		private static string GetEnglishName(string prefabName)
		{
			if (EnglishNames.TryGetValue(prefabName, out var value))
			{
				return value;
			}
			value = prefabName;
			if (value.StartsWith("piece_", StringComparison.OrdinalIgnoreCase))
			{
				value = value.Substring(6);
			}
			return value.Replace('_', ' ');
		}

		private static string SanitizeConfigKey(string value)
		{
			if (string.IsNullOrEmpty(value))
			{
				return "Machine";
			}
			char[] array = new char[8] { '=', '\n', '\t', '\\', '"', '\'', '[', ']' };
			foreach (char oldChar in array)
			{
				value = value.Replace(oldChar, '-');
			}
			return value.Trim();
		}

		private static string NormalizePrefabName(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return string.Empty;
			}
			if (name.EndsWith("(Clone)", StringComparison.Ordinal))
			{
				name = name.Substring(0, name.Length - "(Clone)".Length);
			}
			return name.Trim();
		}

		private static object GetLocalizationInstance()
		{
			BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			for (int i = 0; i < assemblies.Length; i++)
			{
				Type type = assemblies[i].GetType("Localization", throwOnError: false);
				if (!(type == null))
				{
					FieldInfo field = type.GetField("instance", bindingAttr);
					if (field == null)
					{
						field = type.GetField("m_instance", bindingAttr);
					}
					if (field != null)
					{
						return field.GetValue(null);
					}
					PropertyInfo property = type.GetProperty("instance", bindingAttr);
					if (property != null)
					{
						return property.GetValue(null, null);
					}
				}
			}
			return null;
		}

		private static string LocalizeGameText(string token)
		{
			if (string.IsNullOrEmpty(token))
			{
				return null;
			}
			object localizationInstance = GetLocalizationInstance();
			if (localizationInstance == null)
			{
				return null;
			}
			MethodInfo method = localizationInstance.GetType().GetMethod("Localize", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null);
			if (method == null)
			{
				return null;
			}
			try
			{
				return method.Invoke(localizationInstance, new object[1] { token }) as string;
			}
			catch
			{
				return null;
			}
		}

		private void RefreshLocalizedLabels()
		{
			foreach (KeyValuePair<string, string> localizationToken in LocalizationTokens)
			{
				string text = LocalizeGameText(localizationToken.Value);
				if (!string.IsNullOrWhiteSpace(text))
				{
					SetDisplayName(localizationToken.Key, text);
				}
			}
		}

		private static void SetDisplayName(string prefabName, string localized)
		{
			if (DisplayAttributes.TryGetValue(prefabName, out var value))
			{
				string englishName = GetEnglishName(prefabName);
				if (string.IsNullOrWhiteSpace(localized) || localized.StartsWith("$"))
				{
					value.DispName = englishName;
				}
				else
				{
					value.DispName = englishName + " (" + localized + ")";
				}
			}
		}

		private void UpdateDisplayNameFromPiece(Component component, string prefabName)
		{
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			Piece val = component.GetComponent<Piece>();
			if ((Object)(object)val == (Object)null)
			{
				val = component.GetComponentInParent<Piece>();
			}
			if ((Object)(object)val == (Object)null)
			{
				val = component.GetComponentInChildren<Piece>(true);
			}
			if (!((Object)(object)val == (Object)null) && !string.IsNullOrEmpty(val.m_name))
			{
				string text = LocalizeGameText(val.m_name);
				if (!string.IsNullOrWhiteSpace(text))
				{
					SetDisplayName(prefabName, text);
				}
			}
		}

		private string GetPrefabName(Component component)
		{
			if ((Object)(object)component == (Object)null)
			{
				return string.Empty;
			}
			ZNetView val = component.GetComponent<ZNetView>();
			if ((Object)(object)val == (Object)null)
			{
				val = component.GetComponentInParent<ZNetView>();
			}
			if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).gameObject != (Object)null)
			{
				return NormalizePrefabName(((Object)((Component)val).gameObject).name);
			}
			return NormalizePrefabName(((Object)component.gameObject).name);
		}

		private static FieldInfo GetFieldSilent(Type type, string name)
		{
			while (type != null)
			{
				FieldInfo field = type.GetField(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					return field;
				}
				type = type.BaseType;
			}
			return null;
		}

		private void ApplySmelter(Smelter smelter)
		{
			if ((Object)(object)smelter == (Object)null)
			{
				return;
			}
			string prefabName = GetPrefabName((Component)(object)smelter);
			ConfigEntry<float> val = EnsureMultiplier(prefabName);
			UpdateDisplayNameFromPiece((Component)(object)smelter, prefabName);
			if (val != null)
			{
				FieldInfo fieldSilent = GetFieldSilent(((object)smelter).GetType(), "m_secPerProduct");
				if (!(fieldSilent == null) && !(fieldSilent.FieldType != typeof(float)))
				{
					ApplyFloatTimer((Component)(object)smelter, fieldSilent, prefabName, val);
				}
			}
		}

		private void ApplyFermenter(Fermenter fermenter)
		{
			if ((Object)(object)fermenter == (Object)null)
			{
				return;
			}
			string prefabName = GetPrefabName((Component)(object)fermenter);
			ConfigEntry<float> val = EnsureMultiplier(prefabName);
			UpdateDisplayNameFromPiece((Component)(object)fermenter, prefabName);
			if (val != null)
			{
				FieldInfo fieldSilent = GetFieldSilent(((object)fermenter).GetType(), "m_fermentationDuration");
				if (!(fieldSilent == null) && !(fieldSilent.FieldType != typeof(float)))
				{
					ApplyFloatTimer((Component)(object)fermenter, fieldSilent, prefabName, val);
				}
			}
		}

		private void ApplyCookingStation(CookingStation station)
		{
			if ((Object)(object)station == (Object)null)
			{
				return;
			}
			string prefabName = GetPrefabName((Component)(object)station);
			ConfigEntry<float> val = EnsureMultiplier(prefabName);
			UpdateDisplayNameFromPiece((Component)(object)station, prefabName);
			if (val == null)
			{
				return;
			}
			FieldInfo fieldSilent = GetFieldSilent(((object)station).GetType(), "m_conversion");
			if (fieldSilent == null || !(fieldSilent.GetValue(station) is IEnumerable enumerable))
			{
				return;
			}
			foreach (object item in enumerable)
			{
				if (item != null)
				{
					FieldInfo fieldSilent2 = GetFieldSilent(item.GetType(), "m_cookTime");
					if (!(fieldSilent2 == null) && !(fieldSilent2.FieldType != typeof(float)))
					{
						ApplyCookTimer(item, fieldSilent2, val);
					}
				}
			}
		}

		private void ApplyFloatTimer(Component component, FieldInfo field, string prefabName, ConfigEntry<float> multiplier)
		{
			string key = ((Object)component).GetInstanceID() + "|" + field.DeclaringType.FullName + "|" + field.Name;
			if (!FloatBaselines.TryGetValue(key, out var value))
			{
				object value2 = field.GetValue(component);
				if (!(value2 is float))
				{
					return;
				}
				value = (float)value2;
				FloatBaselines[key] = value;
			}
			float num = Math.Max(0.01f, multiplier.Value);
			field.SetValue(component, value / num);
		}

		private void ApplyCookTimer(object conversion, FieldInfo cookTime, ConfigEntry<float> multiplier)
		{
			if (!ConversionBaselines.TryGetValue(conversion, out var value))
			{
				object value2 = cookTime.GetValue(conversion);
				if (!(value2 is float))
				{
					return;
				}
				value = (float)value2;
				ConversionBaselines[conversion] = value;
			}
			float num = Math.Max(0.01f, multiplier.Value);
			cookTime.SetValue(conversion, value / num);
		}

		private void RefreshLiveMachines()
		{
			Smelter[] array = Resources.FindObjectsOfTypeAll<Smelter>();
			foreach (Smelter val in array)
			{
				if (IsLive((Component)(object)val))
				{
					ApplySmelter(val);
				}
			}
			Fermenter[] array2 = Resources.FindObjectsOfTypeAll<Fermenter>();
			foreach (Fermenter val2 in array2)
			{
				if (IsLive((Component)(object)val2))
				{
					ApplyFermenter(val2);
				}
			}
			CookingStation[] array3 = Resources.FindObjectsOfTypeAll<CookingStation>();
			foreach (CookingStation val3 in array3)
			{
				if (IsLive((Component)(object)val3))
				{
					ApplyCookingStation(val3);
				}
			}
		}

		private static bool IsLive(Component component)
		{
			if ((Object)(object)component == (Object)null)
			{
				return false;
			}
			ZNetView val = component.GetComponent<ZNetView>();
			if ((Object)(object)val == (Object)null)
			{
				val = component.GetComponentInParent<ZNetView>();
			}
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(ZNetView), "GetZDO", (Type[])null, (Type[])null);
				return methodInfo != null && methodInfo.Invoke(val, null) != null;
			}
			catch
			{
				return false;
			}
		}
	}
}