Decompiled source of ExtractionGoalSetter v4.0.0

ExtractionGoalSetter.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("REPOJP")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("zabuMod")]
[assembly: AssemblyTitle("zabuMod")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 REPOJP.ExtractionGoalSetter
{
	[BepInPlugin("REPOJP.ExtractionGoalSetter", "ExtractionGoalSetter", "1.0.1")]
	public sealed class ExtractionGoalSetterPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "REPOJP.ExtractionGoalSetter";

		public const string PluginName = "ExtractionGoalSetter";

		public const string PluginVersion = "1.0.1";

		internal static ExtractionGoalSetterPlugin Instance;

		internal static ManualLogSource Log;

		private Harmony harmony;

		private ConfigEntry<bool> enableMod;

		private ConfigEntry<bool> enableLog;

		private ConfigEntry<bool> allowAddCommand;

		private ConfigEntry<bool> allowMulCommand;

		private ConfigEntry<bool> allowResetCommand;

		private ConfigEntry<bool> allowSyncCommand;

		private ConfigEntry<bool> allowDuringWarning;

		private ConfigEntry<bool> alsoAdjustGlobalRoundGoal;

		private ConfigEntry<bool> autoTriggerSuccessCheckAfterChange;

		private ConfigEntry<bool> roundToNearestHundred;

		private ConfigEntry<bool> notifyWithFocusText;

		private ConfigEntry<bool> broadcastTruckMessage;

		private ConfigEntry<int> minimumGoal;

		private ConfigEntry<int> maximumGoal;

		private static readonly MethodInfo HaulGoalSetMethod = AccessTools.Method(typeof(ExtractionPoint), "HaulGoalSet", (Type[])null, (Type[])null);

		private static readonly MethodInfo StateSetMethod = AccessTools.Method(typeof(ExtractionPoint), "StateSet", (Type[])null, (Type[])null);

		private static readonly FieldInfo CurrentStateField = AccessTools.Field(typeof(ExtractionPoint), "currentState");

		private static readonly FieldInfo DebugCommandHandlerCommandsField = AccessTools.Field(typeof(DebugCommandHandler), "_commands");

		private static readonly FieldInfo RoundExtractionPointCurrentField = AccessTools.Field(typeof(RoundDirector), "extractionPointCurrent");

		private static readonly FieldInfo RoundExtractionPointListField = AccessTools.Field(typeof(RoundDirector), "extractionPointList");

		private static readonly FieldInfo RoundExtractionHaulGoalField = AccessTools.Field(typeof(RoundDirector), "extractionHaulGoal");

		private static readonly FieldInfo RoundExtractionPointsField = AccessTools.Field(typeof(RoundDirector), "extractionPoints");

		private static readonly FieldInfo RoundCurrentHaulField = AccessTools.Field(typeof(RoundDirector), "currentHaul");

		private static readonly FieldInfo RoundHaulGoalField = AccessTools.Field(typeof(RoundDirector), "haulGoal");

		private static readonly FieldInfo RoundExtractionPointSurplusField = AccessTools.Field(typeof(RoundDirector), "extractionPointSurplus");

		private void Awake()
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			try
			{
				((Component)this).transform.parent = null;
				((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
				Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Failure: Persist plugin object\n" + ex));
			}
			BindConfigs();
			try
			{
				harmony = new Harmony("REPOJP.ExtractionGoalSetter");
				harmony.PatchAll();
				WriteLog("Harmony patches applied");
			}
			catch (Exception ex2)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Failure: Apply Harmony patches\n" + ex2));
			}
			TryRegisterCommands(DebugCommandHandler.instance);
		}

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

		private void BindConfigs()
		{
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Expected O, but got Unknown
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Expected O, but got Unknown
			enableMod = ((BaseUnityPlugin)this).Config.Bind<bool>("A General", "EnableMod", true, "Enable this mod / このMODを有効化");
			enableLog = ((BaseUnityPlugin)this).Config.Bind<bool>("A General", "EnableLog", true, "Enable BepInEx console logs / BepInExコンソールログを有効化");
			allowAddCommand = ((BaseUnityPlugin)this).Config.Bind<bool>("B Commands", "AllowAddCommand", true, "Enable /hauladd command / /hauladd コマンドを有効化");
			allowMulCommand = ((BaseUnityPlugin)this).Config.Bind<bool>("B Commands", "AllowMulCommand", true, "Enable /haulmul command / /haulmul コマンドを有効化");
			allowResetCommand = ((BaseUnityPlugin)this).Config.Bind<bool>("B Commands", "AllowResetCommand", true, "Enable /haulreset command / /haulreset コマンドを有効化");
			allowSyncCommand = ((BaseUnityPlugin)this).Config.Bind<bool>("B Commands", "AllowSyncCommand", true, "Enable /haulsync command / /haulsync コマンドを有効化");
			allowDuringWarning = ((BaseUnityPlugin)this).Config.Bind<bool>("C Safety", "AllowDuringWarning", true, "Allow changing the goal during warning countdown / 警告カウントダウン中の目標変更を許可");
			alsoAdjustGlobalRoundGoal = ((BaseUnityPlugin)this).Config.Bind<bool>("C Safety", "AlsoAdjustGlobalRoundGoal", true, "Also update the round-wide haul goal for truck screen synchronization / トラック画面同期用にラウンド全体目標も更新");
			autoTriggerSuccessCheckAfterChange = ((BaseUnityPlugin)this).Config.Bind<bool>("C Safety", "AutoTriggerSuccessCheckAfterChange", true, "Trigger Success state immediately when the current haul already meets the changed goal / 現在の納品額が変更後目標を満たす場合に即Successへ遷移");
			minimumGoal = ((BaseUnityPlugin)this).Config.Bind<int>("D Goal", "MinimumGoal", 0, new ConfigDescription("Minimum allowed extraction goal / 設定可能な最小納品目標", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 999999999), Array.Empty<object>()));
			maximumGoal = ((BaseUnityPlugin)this).Config.Bind<int>("D Goal", "MaximumGoal", 999999999, new ConfigDescription("Maximum allowed extraction goal / 設定可能な最大納品目標", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 999999999), Array.Empty<object>()));
			roundToNearestHundred = ((BaseUnityPlugin)this).Config.Bind<bool>("D Goal", "RoundToNearestHundred", true, "Round changed goal to nearest 100 / 変更後の目標金額を100単位に丸める");
			notifyWithFocusText = ((BaseUnityPlugin)this).Config.Bind<bool>("E Notification", "NotifyWithFocusText", true, "Show local focus text after command execution / コマンド実行後にローカル通知を表示");
			broadcastTruckMessage = ((BaseUnityPlugin)this).Config.Bind<bool>("E Notification", "BroadcastTruckMessage", false, "Broadcast command result to truck chat screen / コマンド結果をトラック画面チャットに共有");
		}

		internal bool IsEnabled()
		{
			return enableMod != null && enableMod.Value;
		}

		internal static void WriteLog(string message)
		{
			if (!((Object)(object)Instance == (Object)null) && Log != null && Instance.enableLog != null && Instance.enableLog.Value)
			{
				Log.LogInfo((object)message);
			}
		}

		internal static void WriteWarning(string message)
		{
			if (Log != null)
			{
				Log.LogWarning((object)message);
			}
		}

		internal static void WriteError(string message)
		{
			if (Log != null)
			{
				Log.LogError((object)message);
			}
		}

		internal void TryRegisterCommands(DebugCommandHandler handler)
		{
			if ((Object)(object)handler == (Object)null)
			{
				return;
			}
			try
			{
				RegisterCommand(handler, "haulset", "Set the current extraction goal", ExecuteHaulSetCommand, GetAmountSuggestions);
				RegisterCommand(handler, "goal", "Set the current extraction goal", ExecuteHaulSetCommand, GetAmountSuggestions);
				RegisterCommand(handler, "extractgoal", "Set the current extraction goal", ExecuteHaulSetCommand, GetAmountSuggestions);
				RegisterCommand(handler, "hauladd", "Add to the current extraction goal", ExecuteHaulAddCommand, GetSignedAmountSuggestions);
				RegisterCommand(handler, "haulmul", "Multiply the current extraction goal", ExecuteHaulMulCommand, GetMultiplierSuggestions);
				RegisterCommand(handler, "haulreset", "Reset the current extraction goal to vanilla split goal", ExecuteHaulResetCommand, GetEmptySuggestions);
				RegisterCommand(handler, "haulsync", "Sync the current extraction goal display", ExecuteHaulSyncCommand, GetEmptySuggestions);
				RegisterCommand(handler, "haullist", "Show the current extraction goal status", ExecuteHaulListCommand, GetEmptySuggestions);
				WriteLog("Chat commands registered: /haulset /goal /extractgoal /hauladd /haulmul /haulreset /haulsync /haullist");
			}
			catch (Exception ex)
			{
				WriteError("Failure: Register chat commands\n" + ex);
			}
		}

		private void RegisterCommand(DebugCommandHandler handler, string name, string description, Action<bool, string[]> execute, Func<bool, string, string[], List<string>> suggest)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			if (!HasCommand(handler, name))
			{
				ChatCommand val = new ChatCommand(name, description + " / 現在開いている納品所の目標金額を変更", execute, suggest, (Func<bool>)IsCommandEnabled, false);
				handler.Register(val);
			}
		}

		private bool HasCommand(DebugCommandHandler handler, string name)
		{
			if ((Object)(object)handler == (Object)null || DebugCommandHandlerCommandsField == null)
			{
				return false;
			}
			if (!(DebugCommandHandlerCommandsField.GetValue(handler) is Dictionary<string, ChatCommand> dictionary))
			{
				return false;
			}
			return dictionary.ContainsKey(name.ToLowerInvariant());
		}

		private bool IsCommandEnabled()
		{
			return IsEnabled();
		}

		private List<string> GetAmountSuggestions(bool isDebugConsole, string partial, string[] args)
		{
			return new List<string> { "1000", "5000", "10000", "25000", "50000", "100000" };
		}

		private List<string> GetSignedAmountSuggestions(bool isDebugConsole, string partial, string[] args)
		{
			return new List<string> { "1000", "5000", "-1000", "-5000" };
		}

		private List<string> GetMultiplierSuggestions(bool isDebugConsole, string partial, string[] args)
		{
			return new List<string> { "0.5", "1.5", "2", "3" };
		}

		private List<string> GetEmptySuggestions(bool isDebugConsole, string partial, string[] args)
		{
			return new List<string>();
		}

		private void ExecuteHaulSetCommand(bool isDebugConsole, string[] args)
		{
			if (ValidateCommonCommandState())
			{
				int value;
				if (args == null || args.Length < 1)
				{
					Notify("Usage: /haulset <amount>");
				}
				else if (!TryParseAmount(args[0], out value))
				{
					Notify("Failure: Invalid amount - " + args[0]);
				}
				else
				{
					SetCurrentExtractionGoal(value, "Set");
				}
			}
		}

		private void ExecuteHaulAddCommand(bool isDebugConsole, string[] args)
		{
			if (!ValidateCommonCommandState())
			{
				return;
			}
			if (allowAddCommand == null || !allowAddCommand.Value)
			{
				Notify("Failure: /hauladd is disabled");
				return;
			}
			if (args == null || args.Length < 1)
			{
				Notify("Usage: /hauladd <amount>");
				return;
			}
			if (!TryParseAmount(args[0], out var value))
			{
				Notify("Failure: Invalid amount - " + args[0]);
				return;
			}
			ExtractionPoint val = FindTargetExtractionPoint();
			if ((Object)(object)val == (Object)null)
			{
				Notify("Failure: No active extraction point");
			}
			else
			{
				SetCurrentExtractionGoal((double)val.haulGoal + (double)value, "Add");
			}
		}

		private void ExecuteHaulMulCommand(bool isDebugConsole, string[] args)
		{
			if (!ValidateCommonCommandState())
			{
				return;
			}
			if (allowMulCommand == null || !allowMulCommand.Value)
			{
				Notify("Failure: /haulmul is disabled");
				return;
			}
			if (args == null || args.Length < 1)
			{
				Notify("Usage: /haulmul <multiplier>");
				return;
			}
			if (!TryParseMultiplier(args[0], out var value))
			{
				Notify("Failure: Invalid multiplier - " + args[0]);
				return;
			}
			ExtractionPoint val = FindTargetExtractionPoint();
			if ((Object)(object)val == (Object)null)
			{
				Notify("Failure: No active extraction point");
				return;
			}
			double requestedGoal = (double)val.haulGoal * value;
			SetCurrentExtractionGoal(requestedGoal, "Multiply");
		}

		private void ExecuteHaulResetCommand(bool isDebugConsole, string[] args)
		{
			if (ValidateCommonCommandState())
			{
				if (allowResetCommand == null || !allowResetCommand.Value)
				{
					Notify("Failure: /haulreset is disabled");
					return;
				}
				int vanillaSplitGoal = GetVanillaSplitGoal();
				SetCurrentExtractionGoal(vanillaSplitGoal, "Reset");
			}
		}

		private void ExecuteHaulSyncCommand(bool isDebugConsole, string[] args)
		{
			if (!ValidateCommonCommandState())
			{
				return;
			}
			if (allowSyncCommand == null || !allowSyncCommand.Value)
			{
				Notify("Failure: /haulsync is disabled");
				return;
			}
			ExtractionPoint val = FindTargetExtractionPoint();
			if ((Object)(object)val == (Object)null)
			{
				Notify("Failure: No active extraction point");
				return;
			}
			ApplyGoalToExtractionPoint(val, val.haulGoal);
			Notify(BuildGoalStatusText("Sync", val, val.haulGoal, val.haulGoal));
		}

		private void ExecuteHaulListCommand(bool isDebugConsole, string[] args)
		{
			if (ValidateCommonCommandState())
			{
				ExtractionPoint val = FindTargetExtractionPoint();
				if ((Object)(object)val == (Object)null)
				{
					Notify("Failure: No active extraction point");
				}
				else
				{
					Notify(BuildGoalStatusText("List", val, val.haulGoal, val.haulGoal));
				}
			}
		}

		private bool ValidateCommonCommandState()
		{
			if (!IsEnabled())
			{
				return false;
			}
			if ((Object)(object)RoundDirector.instance == (Object)null)
			{
				Notify("Failure: RoundDirector not found");
				return false;
			}
			if (!IsMasterClientOrSingleplayerSafe())
			{
				Notify("Failure: Host only command");
				return false;
			}
			if (!IsNormalLevelSafe())
			{
				Notify("Failure: This command is available only in normal levels");
				return false;
			}
			return true;
		}

		private bool IsMasterClientOrSingleplayerSafe()
		{
			try
			{
				return SemiFunc.IsMasterClientOrSingleplayer();
			}
			catch
			{
				if ((Object)(object)GameManager.instance == (Object)null)
				{
					return false;
				}
				if (GameManager.instance.gameMode == 0)
				{
					return true;
				}
				return PhotonNetwork.IsMasterClient;
			}
		}

		private bool IsNormalLevelSafe()
		{
			try
			{
				if (!SemiFunc.RunIsLevel())
				{
					return false;
				}
				if (SemiFunc.RunIsShop())
				{
					return false;
				}
				if (SemiFunc.RunIsArena())
				{
					return false;
				}
				return true;
			}
			catch
			{
				return false;
			}
		}

		private bool SetCurrentExtractionGoal(double requestedGoal, string reason)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			ExtractionPoint val = FindTargetExtractionPoint();
			if ((Object)(object)val == (Object)null)
			{
				Notify("Failure: No active extraction point");
				return false;
			}
			State extractionPointState = GetExtractionPointState(val);
			if (!IsAllowedTargetState(extractionPointState))
			{
				Notify("Failure: Cannot change goal in state " + ((object)(State)(ref extractionPointState)).ToString());
				return false;
			}
			int haulGoal = val.haulGoal;
			int newGoal = NormalizeGoal(requestedGoal);
			ApplyGoalToExtractionPoint(val, newGoal);
			TryAutoTriggerSuccess(val, newGoal);
			string message = BuildGoalStatusText(reason, val, haulGoal, newGoal);
			Notify(message);
			WriteLog(message);
			return true;
		}

		private void ApplyGoalToExtractionPoint(ExtractionPoint point, int newGoal)
		{
			if (HaulGoalSetMethod != null)
			{
				HaulGoalSetMethod.Invoke(point, new object[1] { newGoal });
			}
			else
			{
				point.haulGoal = newGoal;
				SetRoundInt(RoundExtractionHaulGoalField, newGoal);
			}
			if (alsoAdjustGlobalRoundGoal != null && alsoAdjustGlobalRoundGoal.Value)
			{
				int num = GetRoundInt(RoundExtractionPointsField);
				if (num <= 0)
				{
					num = 1;
				}
				long value = (long)newGoal * (long)num;
				int value2 = ClampToIntRange(value);
				SetRoundInt(RoundHaulGoalField, value2);
			}
		}

		private void TryAutoTriggerSuccess(ExtractionPoint point, int newGoal)
		{
			//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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Invalid comparison between Unknown and I4
			if (autoTriggerSuccessCheckAfterChange == null || !autoTriggerSuccessCheckAfterChange.Value || StateSetMethod == null)
			{
				return;
			}
			State extractionPointState = GetExtractionPointState(point);
			if ((int)extractionPointState != 2)
			{
				return;
			}
			int roundInt = GetRoundInt(RoundCurrentHaulField);
			int roundInt2 = GetRoundInt(RoundExtractionPointSurplusField);
			if (roundInt + roundInt2 < newGoal)
			{
				return;
			}
			try
			{
				StateSetMethod.Invoke(point, new object[1] { (object)(State)3 });
			}
			catch (Exception ex)
			{
				WriteWarning("Failure: Auto trigger success\n" + ex);
			}
		}

		private ExtractionPoint FindTargetExtractionPoint()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			ExtractionPoint roundExtractionPointCurrent = GetRoundExtractionPointCurrent();
			if ((Object)(object)roundExtractionPointCurrent != (Object)null && IsAllowedTargetState(GetExtractionPointState(roundExtractionPointCurrent)))
			{
				return roundExtractionPointCurrent;
			}
			List<GameObject> roundExtractionPointList = GetRoundExtractionPointList();
			if (roundExtractionPointList != null)
			{
				for (int i = 0; i < roundExtractionPointList.Count; i++)
				{
					GameObject val = roundExtractionPointList[i];
					if (!((Object)(object)val == (Object)null))
					{
						ExtractionPoint component = val.GetComponent<ExtractionPoint>();
						if ((Object)(object)component != (Object)null && IsAllowedTargetState(GetExtractionPointState(component)))
						{
							return component;
						}
					}
				}
			}
			ExtractionPoint[] array = Object.FindObjectsOfType<ExtractionPoint>();
			foreach (ExtractionPoint val2 in array)
			{
				if ((Object)(object)val2 != (Object)null && IsAllowedTargetState(GetExtractionPointState(val2)))
				{
					return val2;
				}
			}
			return null;
		}

		private ExtractionPoint GetRoundExtractionPointCurrent()
		{
			if ((Object)(object)RoundDirector.instance == (Object)null || RoundExtractionPointCurrentField == null)
			{
				return null;
			}
			object? value = RoundExtractionPointCurrentField.GetValue(RoundDirector.instance);
			return (ExtractionPoint)((value is ExtractionPoint) ? value : null);
		}

		private List<GameObject> GetRoundExtractionPointList()
		{
			if ((Object)(object)RoundDirector.instance == (Object)null || RoundExtractionPointListField == null)
			{
				return null;
			}
			return RoundExtractionPointListField.GetValue(RoundDirector.instance) as List<GameObject>;
		}

		private State GetExtractionPointState(ExtractionPoint point)
		{
			//IL_001e: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)point == (Object)null || CurrentStateField == null)
			{
				return (State)0;
			}
			if (!(CurrentStateField.GetValue(point) is State result))
			{
				return (State)0;
			}
			return result;
		}

		private bool IsAllowedTargetState(State state)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between Unknown and I4
			if ((int)state == 2)
			{
				return true;
			}
			if ((int)state == 4 && allowDuringWarning != null && allowDuringWarning.Value)
			{
				return true;
			}
			return false;
		}

		private int GetVanillaSplitGoal()
		{
			int roundInt = GetRoundInt(RoundHaulGoalField);
			int num = GetRoundInt(RoundExtractionPointsField);
			if (num <= 0)
			{
				num = 1;
			}
			return NormalizeGoal(roundInt / num);
		}

		private int NormalizeGoal(double requestedGoal)
		{
			if (double.IsNaN(requestedGoal) || double.IsInfinity(requestedGoal))
			{
				requestedGoal = 0.0;
			}
			double value = Math.Round(requestedGoal, MidpointRounding.AwayFromZero);
			int num = ClampToIntRange(value);
			if (roundToNearestHundred != null && roundToNearestHundred.Value)
			{
				num = Mathf.RoundToInt((float)num / 100f) * 100;
			}
			int num2 = ((minimumGoal != null) ? minimumGoal.Value : 0);
			int num3 = ((maximumGoal != null) ? maximumGoal.Value : 999999999);
			if (num2 > num3)
			{
				int num4 = num2;
				num2 = num3;
				num3 = num4;
			}
			return Mathf.Clamp(num, num2, num3);
		}

		private int ClampToIntRange(double value)
		{
			if (value > 2147483647.0)
			{
				return int.MaxValue;
			}
			if (value < -2147483648.0)
			{
				return int.MinValue;
			}
			return (int)value;
		}

		private int ClampToIntRange(long value)
		{
			if (value > int.MaxValue)
			{
				return int.MaxValue;
			}
			if (value < int.MinValue)
			{
				return int.MinValue;
			}
			return (int)value;
		}

		private int GetRoundInt(FieldInfo fieldInfo)
		{
			if ((Object)(object)RoundDirector.instance == (Object)null || fieldInfo == null)
			{
				return 0;
			}
			if (!(fieldInfo.GetValue(RoundDirector.instance) is int result))
			{
				return 0;
			}
			return result;
		}

		private void SetRoundInt(FieldInfo fieldInfo, int value)
		{
			if (!((Object)(object)RoundDirector.instance == (Object)null) && !(fieldInfo == null))
			{
				fieldInfo.SetValue(RoundDirector.instance, value);
			}
		}

		private bool TryParseAmount(string text, out int value)
		{
			value = 0;
			if (string.IsNullOrWhiteSpace(text))
			{
				return false;
			}
			string text2 = text.Trim().Replace(",", string.Empty).Replace("_", string.Empty)
				.Replace("$", string.Empty);
			double num = 1.0;
			if (text2.EndsWith("k", StringComparison.OrdinalIgnoreCase))
			{
				num = 1000.0;
				text2 = text2.Substring(0, text2.Length - 1);
			}
			else if (text2.EndsWith("m", StringComparison.OrdinalIgnoreCase))
			{
				num = 1000000.0;
				text2 = text2.Substring(0, text2.Length - 1);
			}
			if (!double.TryParse(text2, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
			{
				return false;
			}
			result *= num;
			value = ClampToIntRange(Math.Round(result, MidpointRounding.AwayFromZero));
			return true;
		}

		private bool TryParseMultiplier(string text, out double value)
		{
			value = 1.0;
			if (string.IsNullOrWhiteSpace(text))
			{
				return false;
			}
			string text2 = text.Trim().Replace(",", string.Empty);
			if (text2.EndsWith("x", StringComparison.OrdinalIgnoreCase))
			{
				text2 = text2.Substring(0, text2.Length - 1);
			}
			if (!double.TryParse(text2, NumberStyles.Float, CultureInfo.InvariantCulture, out value))
			{
				return false;
			}
			if (double.IsNaN(value) || double.IsInfinity(value) || value < 0.0)
			{
				return false;
			}
			return true;
		}

		private string BuildGoalStatusText(string reason, ExtractionPoint point, int previousGoal, int newGoal)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			int roundInt = GetRoundInt(RoundHaulGoalField);
			int roundInt2 = GetRoundInt(RoundCurrentHaulField);
			State extractionPointState = GetExtractionPointState(point);
			return $"ExtractionGoalSetter: {reason} {previousGoal} -> {newGoal} | CurrentHaul={roundInt2} | RoundGoal={roundInt} | State={extractionPointState}";
		}

		private void Notify(string message)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			WriteLog(message);
			if (notifyWithFocusText != null && notifyWithFocusText.Value)
			{
				try
				{
					if ((Object)(object)MissionUI.instance != (Object)null)
					{
						SemiFunc.UIFocusText(message, Color.white, AssetManager.instance.colorYellow, 3f);
					}
				}
				catch
				{
				}
			}
			if (broadcastTruckMessage == null || !broadcastTruckMessage.Value)
			{
				return;
			}
			try
			{
				if ((Object)(object)TruckScreenText.instance != (Object)null)
				{
					TruckScreenText.instance.MessageSendCustom("", message, 0);
				}
			}
			catch
			{
			}
		}
	}
	[HarmonyPatch(typeof(DebugCommandHandler), "Start")]
	internal static class DebugCommandHandlerStartPatch
	{
		private static void Postfix(DebugCommandHandler __instance)
		{
			if (!((Object)(object)ExtractionGoalSetterPlugin.Instance == (Object)null))
			{
				ExtractionGoalSetterPlugin.Instance.TryRegisterCommands(__instance);
			}
		}
	}
}