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}");
}
}
}