Decompiled source of HyperMultitudes v1.0.0

R2HyperMultitudes.dll

Decompiled 5 months ago
using System;
using System.Collections;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HG.Reflection;
using IL.RoR2;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using MonoMod.RuntimeDetour;
using On.RoR2;
using R2API.Utils;
using R2HyperMultitudes.MathParser;
using RoR2;
using UnityEngine;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: OptIn]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("R2HyperMultitudes")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("R2HyperMultitudes")]
[assembly: AssemblyTitle("R2HyperMultitudes")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace R2HyperMultitudes
{
	internal static class Log
	{
		private static ManualLogSource _logSource;

		internal static void Init(ManualLogSource logSource)
		{
			_logSource = logSource;
		}

		internal static void Debug(object data)
		{
			_logSource.LogDebug(data);
		}

		internal static void Error(object data)
		{
			_logSource.LogError(data);
		}

		internal static void Fatal(object data)
		{
			_logSource.LogFatal(data);
		}

		internal static void Info(object data)
		{
			_logSource.LogInfo(data);
		}

		internal static void Message(object data)
		{
			_logSource.LogMessage(data);
		}

		internal static void Warning(object data)
		{
			_logSource.LogWarning(data);
		}
	}
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("Raoul1808.R2HyperMultitudes", "R2HyperMultitudes", "1.0.0")]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		private delegate int RunInstanceReturnInt(Run self);

		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static hook_AdvanceStage <>9__16_0;

			public static Action<Run> <>9__16_1;

			public static Func<Instruction, bool> <>9__16_5;

			public static Func<int, int> <>9__16_6;

			public static Manipulator <>9__16_2;

			public static Func<Instruction, bool> <>9__16_7;

			public static Func<int, int> <>9__16_8;

			public static Manipulator <>9__16_3;

			internal void <Awake>b__16_0(orig_AdvanceStage orig, Run self, SceneDef nextScene)
			{
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: Invalid comparison between Unknown and I4
				orig.Invoke(self, nextScene);
				if (_hypermultitudesEnabled.Value && (int)nextScene.sceneType == 1)
				{
					StageIndex++;
				}
			}

			internal void <Awake>b__16_1(Run run)
			{
				Log.Info("Resetting HyperMultitudes Multiplier");
				StageIndex = 1;
			}

			internal void <Awake>b__16_2(ILContext il)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Expected O, but got Unknown
				ILCursor val = new ILCursor(il);
				if (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
				{
					(Instruction i) => ILPatternMatchingExt.MatchCallOrCallvirt<Run>(i, "get_livingPlayerCount")
				}))
				{
					val.EmitDelegate<Func<int, int>>((Func<int, int>)((int livingPlayerCount) => _origLivingPlayerCountValue));
				}
			}

			internal bool <Awake>b__16_5(Instruction i)
			{
				return ILPatternMatchingExt.MatchCallOrCallvirt<Run>(i, "get_livingPlayerCount");
			}

			internal int <Awake>b__16_6(int livingPlayerCount)
			{
				return _origLivingPlayerCountValue;
			}

			internal void <Awake>b__16_3(ILContext il)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Expected O, but got Unknown
				ILCursor val = new ILCursor(il);
				if (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
				{
					(Instruction i) => ILPatternMatchingExt.MatchCallOrCallvirt<Run>(i, "get_livingPlayerCount")
				}))
				{
					val.EmitDelegate<Func<int, int>>((Func<int, int>)((int livingPlayerCount) => _origLivingPlayerCountValue));
				}
			}

			internal bool <Awake>b__16_7(Instruction i)
			{
				return ILPatternMatchingExt.MatchCallOrCallvirt<Run>(i, "get_livingPlayerCount");
			}

			internal int <Awake>b__16_8(int livingPlayerCount)
			{
				return _origLivingPlayerCountValue;
			}
		}

		public const string Guid = "Raoul1808.R2HyperMultitudes";

		public const string Author = "Raoul1808";

		public const string Name = "R2HyperMultitudes";

		public const string Version = "1.0.0";

		private static ConfigEntry<string> _scalingExpression;

		private static ConfigEntry<bool> _hypermultitudesEnabled;

		public static Node MultitudesExpression;

		public static readonly ModStageContext StageContext = new ModStageContext();

		private static int _stageIndex;

		private static RunInstanceReturnInt _origLivingPlayerCount;

		private static RunInstanceReturnInt _origParticipatingPlayerCount;

		private static int _origLivingPlayerCountValue;

		private static int _origParticipatingPlayerCountValue;

		public static double MultitudesMultiplier { get; private set; }

		public static int StageIndex
		{
			get
			{
				return _stageIndex;
			}
			set
			{
				_stageIndex = value;
				StageContext.Stage = _stageIndex;
				MultitudesMultiplier = Math.Max(MultitudesExpression.Eval(StageContext), 1.0);
				string text = "HyperMultitudes Multiplier = " + MultitudesMultiplier;
				Debug.Log((object)text);
				Log.Info(text);
			}
		}

		private void Awake()
		{
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Expected O, but got Unknown
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Expected O, but got Unknown
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Expected O, but got Unknown
			Log.Init(((BaseUnityPlugin)this).Logger);
			_hypermultitudesEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("HyperMultitudes", "Enabled", true, "Whether HyperMultitudes should be enabled or not");
			_scalingExpression = ((BaseUnityPlugin)this).Config.Bind<string>("HyperMultitudes", "MultiplierExpression", "2 * stage", "A mathematical expression which is calculated on every stage to determine the new multitudes multiplier to apply. Supports additions (+), subtractions (-), multiplications (*), divisions (/), parentheses and exponents (^)");
			Log.Info("Loading expression: " + _scalingExpression.Value);
			MultitudesExpression = new ExpressionParser(_scalingExpression.Value).Parse();
			MultitudesExpression.Eval(StageContext);
			Log.Info("Testing expression");
			for (int j = 1; j < 10; j++)
			{
				StageIndex = j;
			}
			Log.Info("Test ended");
			StageIndex = 1;
			object obj = <>c.<>9__16_0;
			if (obj == null)
			{
				hook_AdvanceStage val = delegate(orig_AdvanceStage orig, Run self, SceneDef nextScene)
				{
					//IL_0015: Unknown result type (might be due to invalid IL or missing references)
					//IL_001b: Invalid comparison between Unknown and I4
					orig.Invoke(self, nextScene);
					if (_hypermultitudesEnabled.Value && (int)nextScene.sceneType == 1)
					{
						StageIndex++;
					}
				};
				<>c.<>9__16_0 = val;
				obj = (object)val;
			}
			Run.AdvanceStage += (hook_AdvanceStage)obj;
			Run.onRunStartGlobal += delegate
			{
				Log.Info("Resetting HyperMultitudes Multiplier");
				StageIndex = 1;
			};
			_origLivingPlayerCount = new Hook((MethodBase)Reflection.GetMethodCached(typeof(Run), "get_livingPlayerCount"), Reflection.GetMethodCached(typeof(Plugin), "GetLivingPlayerCountHook")).GenerateTrampoline<RunInstanceReturnInt>();
			_origParticipatingPlayerCount = new Hook((MethodBase)Reflection.GetMethodCached(typeof(Run), "get_participatingPlayerCount"), Reflection.GetMethodCached(typeof(Plugin), "GetParticipatingPlayerCountHook")).GenerateTrampoline<RunInstanceReturnInt>();
			object obj2 = <>c.<>9__16_2;
			if (obj2 == null)
			{
				Manipulator val2 = delegate(ILContext il)
				{
					//IL_0001: Unknown result type (might be due to invalid IL or missing references)
					//IL_0007: Expected O, but got Unknown
					ILCursor val5 = new ILCursor(il);
					if (val5.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
					{
						(Instruction i) => ILPatternMatchingExt.MatchCallOrCallvirt<Run>(i, "get_livingPlayerCount")
					}))
					{
						val5.EmitDelegate<Func<int, int>>((Func<int, int>)((int livingPlayerCount) => _origLivingPlayerCountValue));
					}
				};
				<>c.<>9__16_2 = val2;
				obj2 = (object)val2;
			}
			AllPlayersTrigger.FixedUpdate += (Manipulator)obj2;
			object obj3 = <>c.<>9__16_3;
			if (obj3 == null)
			{
				Manipulator val3 = delegate(ILContext il)
				{
					//IL_0001: Unknown result type (might be due to invalid IL or missing references)
					//IL_0007: Expected O, but got Unknown
					ILCursor val4 = new ILCursor(il);
					if (val4.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
					{
						(Instruction i) => ILPatternMatchingExt.MatchCallOrCallvirt<Run>(i, "get_livingPlayerCount")
					}))
					{
						val4.EmitDelegate<Func<int, int>>((Func<int, int>)((int livingPlayerCount) => _origLivingPlayerCountValue));
					}
				};
				<>c.<>9__16_3 = val3;
				obj3 = (object)val3;
			}
			MultiBodyTrigger.FixedUpdate += (Manipulator)obj3;
			Stage.onStageStartGlobal += delegate
			{
				if (_hypermultitudesEnabled.Value)
				{
					((MonoBehaviour)this).StartCoroutine(SendChatScalingDelayed());
				}
			};
		}

		private IEnumerator SendChatScalingDelayed()
		{
			yield return (object)new WaitForSeconds(2f);
			SendChatScaling();
		}

		private static void SendChatScaling()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			if (NetworkServer.active)
			{
				SimpleChatMessage val = new SimpleChatMessage();
				val.baseToken = "HyperMultitudes Multiplier now at: {0}";
				val.paramTokens = new string[1] { MultitudesMultiplier.ToString(CultureInfo.InvariantCulture) };
				Chat.SendBroadcastChat((ChatMessageBase)(object)val);
			}
		}

		private static void SendChatExpression()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			if (NetworkServer.active)
			{
				SimpleChatMessage val = new SimpleChatMessage();
				val.baseToken = "HyperMultitudes Expression set to: {0}";
				val.paramTokens = new string[1] { _scalingExpression.Value };
				Chat.SendBroadcastChat((ChatMessageBase)(object)val);
			}
		}

		private static int GetLivingPlayerCountHook(Run self)
		{
			_origLivingPlayerCountValue = _origLivingPlayerCount(self);
			return (int)((double)_origLivingPlayerCountValue * MultitudesMultiplier);
		}

		private static int GetParticipatingPlayerCountHook(Run self)
		{
			_origParticipatingPlayerCountValue = _origParticipatingPlayerCount(self);
			return (int)((double)_origParticipatingPlayerCountValue * MultitudesMultiplier);
		}

		[ConCommand(/*Could not decode attribute arguments.*/)]
		private static void CCEnable(ConCommandArgs args)
		{
			if (((ConCommandArgs)(ref args)).Count != 0)
			{
				Debug.LogError((object)"Invalid arguments. Did you mean mod_hm_set_expression or mod_hm_test_expression?");
				return;
			}
			if (_hypermultitudesEnabled.Value)
			{
				Debug.LogWarning((object)"HyperMultitudes is already enabled.");
				return;
			}
			_hypermultitudesEnabled.Value = true;
			Debug.Log((object)"HyperMultitudes enabled. Good luck");
		}

		[ConCommand(/*Could not decode attribute arguments.*/)]
		private static void CCDisable(ConCommandArgs args)
		{
			if (((ConCommandArgs)(ref args)).Count != 0)
			{
				Debug.LogError((object)"Invalid arguments. Did you mean mod_hm_set_expression or mod_hm_test_expression?");
				return;
			}
			if (!_hypermultitudesEnabled.Value)
			{
				Debug.LogWarning((object)"HyperMultitudes is already disabled.");
				return;
			}
			_hypermultitudesEnabled.Value = false;
			Debug.Log((object)"HyperMultitudes disabled.");
		}

		[ConCommand(/*Could not decode attribute arguments.*/)]
		private static void CCSetExpression(ConCommandArgs args)
		{
			((ConCommandArgs)(ref args)).CheckArgumentCount(1);
			try
			{
				string text = ((ConCommandArgs)(ref args))[0];
				Node node = new ExpressionParser(text).Parse();
				ModStageContext modStageContext = new ModStageContext
				{
					Stage = 1.0
				};
				node.Eval(new ModStageContext
				{
					Stage = 1.0
				});
				MultitudesExpression = node;
				_scalingExpression.Value = text;
				Debug.Log((object)("New HyperMultitudes expression set to: " + text));
				Debug.Log((object)"Testing new expression...");
				for (int i = 1; i <= 10; i++)
				{
					modStageContext.Stage = i;
					double num = node.Eval(modStageContext);
					Debug.Log((object)$"Stage = {i}, Result = {num}");
				}
				Debug.Log((object)"Testing done. If these results don't look right to you, double-check your expression and make sure it is properly wrapped between quotation marks (e.g: \"2 * stage\")");
				SendChatExpression();
			}
			catch (Exception arg)
			{
				Debug.LogError((object)"Invalid expression given. Make sure the expression is put in quotes! (e.g: \"2 * stage\")");
				Debug.LogError((object)"Check the logs for (potentially) more details");
				Log.Error($"Caught exception when setting new expression: {arg}");
			}
		}

		[ConCommand(/*Could not decode attribute arguments.*/)]
		private static void CCGetExpression(ConCommandArgs args)
		{
			Debug.LogWarning((object)((((ConCommandArgs)(ref args)).Count == 0) ? ("Current Expression: " + _scalingExpression.Value) : "Invalid arguments. Did you mean mod_hm_set_expression or mod_hm_test_expression?"));
		}

		[ConCommand(/*Could not decode attribute arguments.*/)]
		private static void CCTestExpression(ConCommandArgs args)
		{
			((ConCommandArgs)(ref args)).CheckArgumentCount(1);
			if (double.TryParse(((ConCommandArgs)(ref args))[0], out var result))
			{
				try
				{
					double num = new ExpressionParser(_scalingExpression.Value).Parse().Eval(new ModStageContext
					{
						Stage = result
					});
					Debug.Log((object)$"Result = {num}");
					return;
				}
				catch (Exception arg)
				{
					Log.Error($"Caught exception when testing existing expression: {arg}");
					return;
				}
			}
			Debug.LogError((object)"Invalid Argument. Correct usage is `mod_hm_test_expression <number>`");
		}
	}
	public class ModStageContext : IContext
	{
		public double Stage { get; set; }

		public double ResolveVariable(string name)
		{
			if (name.ToLower() == "stage" || name.ToLower() == "x")
			{
				return Stage;
			}
			throw new InvalidDataException("Unknown variable: " + name);
		}
	}
}
namespace R2HyperMultitudes.MathParser
{
	public class ExpressionParser
	{
		private Tokenizer _tokenizer;

		public ExpressionParser(string expression)
		{
			_tokenizer = new Tokenizer(new StringReader(expression));
		}

		public Node Parse()
		{
			Node result = ParseAddSubtract();
			if (_tokenizer.Token != 0)
			{
				throw new InvalidDataException("Unexpected characters at end of expression");
			}
			return result;
		}

		private Node ParseAddSubtract()
		{
			Node node = ParseMultiplyDivide();
			while (true)
			{
				Func<double, double, double> func = null;
				switch (_tokenizer.Token)
				{
				case Token.Add:
					func = (double a, double b) => a + b;
					break;
				case Token.Subtract:
					func = (double a, double b) => a - b;
					break;
				}
				if (func == null)
				{
					break;
				}
				_tokenizer.NextToken();
				Node rhs = ParseMultiplyDivide();
				node = new NodeBinary(node, rhs, func);
			}
			return node;
		}

		private Node ParseMultiplyDivide()
		{
			Node node = ParseUnary();
			while (true)
			{
				Func<double, double, double> func = null;
				switch (_tokenizer.Token)
				{
				case Token.Multiply:
					func = (double a, double b) => a * b;
					break;
				case Token.Divide:
					func = (double a, double b) => a / b;
					break;
				}
				if (func == null)
				{
					break;
				}
				_tokenizer.NextToken();
				Node rhs = ParseUnary();
				node = new NodeBinary(node, rhs, func);
			}
			return node;
		}

		private Node ParseUnary()
		{
			if (_tokenizer.Token == Token.Add)
			{
				_tokenizer.NextToken();
				return ParseUnary();
			}
			if (_tokenizer.Token == Token.Subtract)
			{
				_tokenizer.NextToken();
				return new NodeUnary(ParseUnary(), (double a) => 0.0 - a);
			}
			return ParsePow();
		}

		private Node ParsePow()
		{
			Node node = ParseLeaf();
			if (_tokenizer.Token == Token.Pow)
			{
				_tokenizer.NextToken();
				Node rhs = ParseLeaf();
				node = new NodeBinary(node, rhs, Math.Pow);
			}
			return node;
		}

		private Node ParseLeaf()
		{
			if (_tokenizer.Token == Token.Variable)
			{
				NodeVariable result = new NodeVariable(_tokenizer.Variable);
				_tokenizer.NextToken();
				return result;
			}
			if (_tokenizer.Token == Token.Number)
			{
				NodeNumber result2 = new NodeNumber(_tokenizer.Number);
				_tokenizer.NextToken();
				return result2;
			}
			if (_tokenizer.Token == Token.OpenParens)
			{
				_tokenizer.NextToken();
				Node result3 = ParseAddSubtract();
				if (_tokenizer.Token != Token.CloseParens)
				{
					throw new InvalidDataException("Missing close parenthesis");
				}
				_tokenizer.NextToken();
				return result3;
			}
			throw new InvalidDataException($"Unexpected token: {_tokenizer.Token}");
		}
	}
	public interface IContext
	{
		double ResolveVariable(string name);
	}
	public abstract class Node
	{
		public abstract double Eval(IContext ctx);
	}
	public class NodeNumber : Node
	{
		private double _number;

		public NodeNumber(double number)
		{
			_number = number;
		}

		public override double Eval(IContext ctx)
		{
			return _number;
		}
	}
	public class NodeBinary : Node
	{
		private Node _lhs;

		private Node _rhs;

		private Func<double, double, double> _op;

		public NodeBinary(Node lhs, Node rhs, Func<double, double, double> op)
		{
			_lhs = lhs;
			_rhs = rhs;
			_op = op;
		}

		public override double Eval(IContext ctx)
		{
			return _op(_lhs.Eval(ctx), _rhs.Eval(ctx));
		}
	}
	public class NodeUnary : Node
	{
		private Node _rhs;

		private Func<double, double> _op;

		public NodeUnary(Node rhs, Func<double, double> op)
		{
			_rhs = rhs;
			_op = op;
		}

		public override double Eval(IContext ctx)
		{
			return _op(_rhs.Eval(ctx));
		}
	}
	public class NodeVariable : Node
	{
		private string _variableName;

		public NodeVariable(string variable)
		{
			_variableName = variable;
		}

		public override double Eval(IContext ctx)
		{
			return ctx.ResolveVariable(_variableName);
		}
	}
	public enum Token
	{
		None,
		Number,
		Add,
		Subtract,
		Multiply,
		Divide,
		Pow,
		OpenParens,
		CloseParens,
		Variable
	}
	public class Tokenizer
	{
		private StringReader _reader;

		private char _currentChar;

		public double Number { get; private set; }

		public string Variable { get; private set; }

		public Token Token { get; private set; }

		public Tokenizer(StringReader reader)
		{
			_reader = reader;
			NextChar();
			NextToken();
		}

		private void NextChar()
		{
			int num = _reader.Read();
			_currentChar = ((num >= 0) ? ((char)num) : '\0');
		}

		public void NextToken()
		{
			while (char.IsWhiteSpace(_currentChar))
			{
				NextChar();
			}
			switch (_currentChar)
			{
			case '\0':
				Token = Token.None;
				return;
			case '+':
				NextChar();
				Token = Token.Add;
				return;
			case '-':
				NextChar();
				Token = Token.Subtract;
				return;
			case '*':
				NextChar();
				Token = Token.Multiply;
				return;
			case '/':
				NextChar();
				Token = Token.Divide;
				return;
			case '(':
				NextChar();
				Token = Token.OpenParens;
				return;
			case ')':
				NextChar();
				Token = Token.CloseParens;
				return;
			case '^':
				NextChar();
				Token = Token.Pow;
				return;
			}
			if (char.IsLetter(_currentChar) || _currentChar == '_')
			{
				StringBuilder stringBuilder = new StringBuilder();
				while (char.IsLetterOrDigit(_currentChar) || _currentChar == '_')
				{
					stringBuilder.Append(_currentChar);
					NextChar();
				}
				Variable = stringBuilder.ToString();
				Token = Token.Variable;
				return;
			}
			if (char.IsDigit(_currentChar) || _currentChar == '.')
			{
				StringBuilder stringBuilder2 = new StringBuilder();
				bool flag = false;
				while (char.IsDigit(_currentChar) || (!flag && _currentChar == '.'))
				{
					stringBuilder2.Append(_currentChar);
					flag = flag || _currentChar == '.';
					NextChar();
				}
				Number = double.Parse(stringBuilder2.ToString(), CultureInfo.InvariantCulture);
				Token = Token.Number;
				return;
			}
			throw new InvalidDataException($"Unexpected character: {_currentChar}");
		}
	}
}