Decompiled source of ExtractionGoalSetter v1.0.0

ExtractionGoalSetter.dll

Decompiled 2 days ago
using System;
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 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: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("zabu")]
[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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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.ExtractionGoalSetterMod
{
	[BepInPlugin("REPOJP.ExtractionGoalSetter", "ExtractionGoalSetter", "1.0.0")]
	public sealed class ExtractionGoalSetter : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(PlayerAvatar), "ChatMessageSend")]
		private static class PlayerAvatar_ChatMessageSend_Patch
		{
			private static bool Prefix(PlayerAvatar __instance, string _message)
			{
				if ((Object)(object)Instance == (Object)null)
				{
					return true;
				}
				try
				{
					if (Instance.TryHandleCommand(__instance, _message))
					{
						return false;
					}
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)Instance).Logger.LogInfo((object)("[ExtractionGoalSetter] Command handling failed" + Environment.NewLine + ex));
					return false;
				}
				return true;
			}
		}

		public const string PluginGuid = "REPOJP.ExtractionGoalSetter";

		public const string PluginName = "ExtractionGoalSetter";

		public const string PluginVersion = "1.0.0";

		internal static ExtractionGoalSetter Instance;

		private Harmony harmony;

		internal ConfigEntry<bool> EnableMod;

		internal ConfigEntry<bool> EnableImmediateSuccessCheck;

		internal ConfigEntry<int> MinimumGoal;

		internal ConfigEntry<int> MaximumGoal;

		private static FieldInfo fiRoundDirectorExtractionPointCurrent;

		private static FieldInfo fiRoundDirectorExtractionPoints;

		private static FieldInfo fiRoundDirectorExtractionHaulGoal;

		private static FieldInfo fiRoundDirectorHaulGoal;

		private static FieldInfo fiRoundDirectorCurrentHaul;

		private static FieldInfo fiRoundDirectorExtractionPointSurplus;

		private static FieldInfo fiExtractionPointCurrentState;

		private static FieldInfo fiExtractionPointHaulGoal;

		private static FieldInfo fiExtractionPointSuccessDelay;

		private static FieldInfo fiExtractionPointIsShop;

		private static MethodInfo miExtractionPointHaulGoalSet;

		private static MethodInfo miExtractionPointHaulChecker;

		private const string CommandGoal = "goal";

		private const string CommandGoalAdd = "gadd";

		private const string CommandGoalSub = "gsub";

		private const string CommandGoalDouble = "gdouble";

		private const string CommandGoalReset = "greset";

		private const string CommandGoalNow = "gnow";

		private void Awake()
		{
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Expected O, but got Unknown
			Instance = this;
			EnableMod = ((BaseUnityPlugin)this).Config.Bind<bool>("A General", "EnableMod", true, "Enable or disable this mod.このMODの有効無効");
			EnableImmediateSuccessCheck = ((BaseUnityPlugin)this).Config.Bind<bool>("A General", "EnableImmediateSuccessCheck", true, "Immediately trigger success check when the new goal is already met.変更後に既に達成済みなら即時達成判定");
			MinimumGoal = ((BaseUnityPlugin)this).Config.Bind<int>("B Goal", "MinimumGoal", 0, "Minimum allowed extraction goal.設定可能最小クリア金額");
			MaximumGoal = ((BaseUnityPlugin)this).Config.Bind<int>("B Goal", "MaximumGoal", 999999, "Maximum allowed extraction goal.設定可能最大クリア金額");
			fiRoundDirectorExtractionPointCurrent = AccessTools.Field(typeof(RoundDirector), "extractionPointCurrent");
			fiRoundDirectorExtractionPoints = AccessTools.Field(typeof(RoundDirector), "extractionPoints");
			fiRoundDirectorExtractionHaulGoal = AccessTools.Field(typeof(RoundDirector), "extractionHaulGoal");
			fiRoundDirectorHaulGoal = AccessTools.Field(typeof(RoundDirector), "haulGoal");
			fiRoundDirectorCurrentHaul = AccessTools.Field(typeof(RoundDirector), "currentHaul");
			fiRoundDirectorExtractionPointSurplus = AccessTools.Field(typeof(RoundDirector), "extractionPointSurplus");
			fiExtractionPointCurrentState = AccessTools.Field(typeof(ExtractionPoint), "currentState");
			fiExtractionPointHaulGoal = AccessTools.Field(typeof(ExtractionPoint), "haulGoal");
			fiExtractionPointSuccessDelay = AccessTools.Field(typeof(ExtractionPoint), "successDelay");
			fiExtractionPointIsShop = AccessTools.Field(typeof(ExtractionPoint), "isShop");
			miExtractionPointHaulGoalSet = AccessTools.Method(typeof(ExtractionPoint), "HaulGoalSet", (Type[])null, (Type[])null);
			miExtractionPointHaulChecker = AccessTools.Method(typeof(ExtractionPoint), "HaulChecker", (Type[])null, (Type[])null);
			harmony = new Harmony("REPOJP.ExtractionGoalSetter");
			harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"ExtractionGoalSetter 1.0.0 loaded");
		}

		internal bool TryHandleCommand(PlayerAvatar playerAvatar, string message)
		{
			if (!EnableMod.Value)
			{
				return false;
			}
			if (string.IsNullOrWhiteSpace(message))
			{
				return false;
			}
			if (!message.StartsWith("/"))
			{
				return false;
			}
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				return false;
			}
			if ((Object)(object)playerAvatar == (Object)null)
			{
				return false;
			}
			if ((Object)(object)playerAvatar.photonView == (Object)null)
			{
				return false;
			}
			if (!playerAvatar.photonView.IsMine)
			{
				return false;
			}
			string[] commandTokens = GetCommandTokens(message);
			if (commandTokens.Length == 0)
			{
				return false;
			}
			string text = commandTokens[0];
			if (string.IsNullOrWhiteSpace(text))
			{
				return false;
			}
			if (!IsManagedCommand(text))
			{
				return false;
			}
			if (!TryGetActiveExtractionPoint(out ExtractionPoint extractionPoint, out string errorMessage))
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[ExtractionGoalSetter] " + errorMessage));
				return true;
			}
			int currentGoal = GetCurrentGoal(extractionPoint);
			if (string.Equals(text, "gnow", StringComparison.OrdinalIgnoreCase))
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[ExtractionGoalSetter] Current goal: " + currentGoal));
				return true;
			}
			if (string.Equals(text, "goal", StringComparison.OrdinalIgnoreCase))
			{
				if (commandTokens.Length < 2)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)"[ExtractionGoalSetter] Usage: /goal 8000");
					return true;
				}
				if (!TryParseInt(commandTokens[1], out var value))
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)("[ExtractionGoalSetter] Invalid value: " + commandTokens[1]));
					return true;
				}
				return TryApplyGoalCommand(extractionPoint, value, "GOAL");
			}
			if (string.Equals(text, "gadd", StringComparison.OrdinalIgnoreCase))
			{
				if (commandTokens.Length < 2)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)"[ExtractionGoalSetter] Usage: /gadd 1000");
					return true;
				}
				if (!TryParseInt(commandTokens[1], out var value2))
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)("[ExtractionGoalSetter] Invalid value: " + commandTokens[1]));
					return true;
				}
				return TryApplyGoalCommand(extractionPoint, currentGoal + value2, "GADD");
			}
			if (string.Equals(text, "gsub", StringComparison.OrdinalIgnoreCase))
			{
				if (commandTokens.Length < 2)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)"[ExtractionGoalSetter] Usage: /gsub 1000");
					return true;
				}
				if (!TryParseInt(commandTokens[1], out var value3))
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)("[ExtractionGoalSetter] Invalid value: " + commandTokens[1]));
					return true;
				}
				return TryApplyGoalCommand(extractionPoint, currentGoal - value3, "GSUB");
			}
			if (string.Equals(text, "gdouble", StringComparison.OrdinalIgnoreCase))
			{
				long num = (long)currentGoal * 2L;
				if (num > int.MaxValue)
				{
					num = 2147483647L;
				}
				return TryApplyGoalCommand(extractionPoint, (int)num, "GDOUBLE");
			}
			if (string.Equals(text, "greset", StringComparison.OrdinalIgnoreCase))
			{
				int vanillaGoal = GetVanillaGoal(extractionPoint);
				return TryApplyGoalCommand(extractionPoint, vanillaGoal, "GRESET");
			}
			return false;
		}

		private bool TryApplyGoalCommand(ExtractionPoint extractionPoint, int requestedGoal, string operationName)
		{
			int currentGoal = GetCurrentGoal(extractionPoint);
			int newGoal = Mathf.Clamp(requestedGoal, MinimumGoal.Value, MaximumGoal.Value);
			if (!TrySetGoal(extractionPoint, newGoal, out string errorMessage))
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[ExtractionGoalSetter] " + errorMessage));
				return true;
			}
			if (EnableImmediateSuccessCheck.Value)
			{
				TryRunImmediateSuccessCheck(extractionPoint, newGoal);
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[ExtractionGoalSetter] " + operationName + ": " + currentGoal + " -> " + newGoal));
			return true;
		}

		private bool TryGetActiveExtractionPoint(out ExtractionPoint extractionPoint, out string errorMessage)
		{
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Invalid comparison between Unknown and I4
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Invalid comparison between Unknown and I4
			extractionPoint = null;
			errorMessage = string.Empty;
			if ((Object)(object)RoundDirector.instance == (Object)null)
			{
				errorMessage = "RoundDirector not found";
				return false;
			}
			if (fiRoundDirectorExtractionPointCurrent == null)
			{
				errorMessage = "Failed to find RoundDirector.extractionPointCurrent";
				return false;
			}
			object value = fiRoundDirectorExtractionPointCurrent.GetValue(RoundDirector.instance);
			extractionPoint = (ExtractionPoint)((value is ExtractionPoint) ? value : null);
			if ((Object)(object)extractionPoint == (Object)null)
			{
				errorMessage = "No active extraction point";
				return false;
			}
			if (fiExtractionPointCurrentState == null)
			{
				errorMessage = "Failed to find ExtractionPoint.currentState";
				return false;
			}
			object value2 = fiExtractionPointCurrentState.GetValue(extractionPoint);
			if (value2 == null)
			{
				errorMessage = "Failed to read extraction point state";
				return false;
			}
			State val = (State)value2;
			if ((int)val != 2 && (int)val != 4)
			{
				errorMessage = "Current extraction point is not in an editable state";
				return false;
			}
			return true;
		}

		private bool TrySetGoal(ExtractionPoint extractionPoint, int newGoal, out string errorMessage)
		{
			errorMessage = string.Empty;
			if (miExtractionPointHaulGoalSet == null)
			{
				errorMessage = "Failed to find ExtractionPoint.HaulGoalSet";
				return false;
			}
			try
			{
				miExtractionPointHaulGoalSet.Invoke(extractionPoint, new object[1] { newGoal });
				return true;
			}
			catch (Exception ex)
			{
				errorMessage = "Failed to set goal" + Environment.NewLine + ex;
				return false;
			}
		}

		private int GetCurrentGoal(ExtractionPoint extractionPoint)
		{
			if ((Object)(object)RoundDirector.instance != (Object)null && fiRoundDirectorExtractionHaulGoal != null && fiRoundDirectorExtractionHaulGoal.GetValue(RoundDirector.instance) is int result)
			{
				return result;
			}
			if ((Object)(object)extractionPoint != (Object)null && fiExtractionPointHaulGoal != null && fiExtractionPointHaulGoal.GetValue(extractionPoint) is int result2)
			{
				return result2;
			}
			return 0;
		}

		private int GetVanillaGoal(ExtractionPoint extractionPoint)
		{
			bool flag = false;
			if (fiExtractionPointIsShop != null && (Object)(object)extractionPoint != (Object)null && fiExtractionPointIsShop.GetValue(extractionPoint) is bool flag2)
			{
				flag = flag2;
			}
			if (flag)
			{
				return SemiFunc.StatGetRunCurrency() * 1000;
			}
			if ((Object)(object)RoundDirector.instance == (Object)null)
			{
				return 0;
			}
			int num = 0;
			if (fiRoundDirectorHaulGoal != null && fiRoundDirectorHaulGoal.GetValue(RoundDirector.instance) is int num2)
			{
				num = num2;
			}
			int num3 = 1;
			if (fiRoundDirectorExtractionPoints != null && fiRoundDirectorExtractionPoints.GetValue(RoundDirector.instance) is int num4)
			{
				num3 = Mathf.Max(1, num4);
			}
			return num / num3;
		}

		private void TryRunImmediateSuccessCheck(ExtractionPoint extractionPoint, int newGoal)
		{
			if ((Object)(object)RoundDirector.instance == (Object)null || (Object)(object)extractionPoint == (Object)null)
			{
				return;
			}
			int num = 0;
			int num2 = 0;
			if (fiRoundDirectorCurrentHaul != null && fiRoundDirectorCurrentHaul.GetValue(RoundDirector.instance) is int num3)
			{
				num = num3;
			}
			if (fiRoundDirectorExtractionPointSurplus != null && fiRoundDirectorExtractionPointSurplus.GetValue(RoundDirector.instance) is int num4)
			{
				num2 = num4;
			}
			int num5 = num + num2;
			if (num5 < newGoal)
			{
				return;
			}
			if (fiExtractionPointSuccessDelay != null)
			{
				fiExtractionPointSuccessDelay.SetValue(extractionPoint, 0f);
			}
			if (!(miExtractionPointHaulChecker != null))
			{
				return;
			}
			try
			{
				miExtractionPointHaulChecker.Invoke(extractionPoint, null);
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[ExtractionGoalSetter] Failed to run immediate success check" + Environment.NewLine + ex));
			}
		}

		private bool IsManagedCommand(string commandName)
		{
			return string.Equals(commandName, "goal", StringComparison.OrdinalIgnoreCase) || string.Equals(commandName, "gadd", StringComparison.OrdinalIgnoreCase) || string.Equals(commandName, "gsub", StringComparison.OrdinalIgnoreCase) || string.Equals(commandName, "gdouble", StringComparison.OrdinalIgnoreCase) || string.Equals(commandName, "greset", StringComparison.OrdinalIgnoreCase) || string.Equals(commandName, "gnow", StringComparison.OrdinalIgnoreCase);
		}

		private string[] GetCommandTokens(string message)
		{
			if (string.IsNullOrWhiteSpace(message))
			{
				return Array.Empty<string>();
			}
			string text = message.Trim();
			if (text.StartsWith("/"))
			{
				text = text.Substring(1);
			}
			if (string.IsNullOrWhiteSpace(text))
			{
				return Array.Empty<string>();
			}
			return text.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
		}

		private bool TryParseInt(string text, out int value)
		{
			return int.TryParse(text, NumberStyles.Integer, CultureInfo.InvariantCulture, out value);
		}

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