Decompiled source of ExploitPatches v0.1.1

GDWeave/mods/SaruShinobie.ExploitPatches/SaruShinobie.ExploitPatches.dll

Decompiled 21 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.Json.Serialization;
using GDWeave;
using GDWeave.Godot;
using GDWeave.Godot.Variants;
using GDWeave.Modding;
using patchlist;
using util.LexicalTransformer;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v8.0", FrameworkDisplayName = ".NET 8.0")]
[assembly: AssemblyCompany("SaruShinobie.ExploitPatches")]
[assembly: AssemblyConfiguration("release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0.0+8670b8bddc13550031e4ff8a4046035c07f9807a")]
[assembly: AssemblyProduct("SaruShinobie.ExploitPatches")]
[assembly: AssemblyTitle("SaruShinobie.ExploitPatches")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
[CompilerGenerated]
internal sealed class <>z__ReadOnlySingleElementList<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T>
{
	private sealed class Enumerator : IDisposable, IEnumerator, IEnumerator<T>
	{
		object IEnumerator.Current => _item;

		T IEnumerator<T>.Current => _item;

		public Enumerator(T item)
		{
			_item = item;
		}

		bool IEnumerator.MoveNext()
		{
			if (!_moveNextCalled)
			{
				return _moveNextCalled = true;
			}
			return false;
		}

		void IEnumerator.Reset()
		{
			_moveNextCalled = false;
		}

		void IDisposable.Dispose()
		{
		}
	}

	int ICollection.Count => 1;

	bool ICollection.IsSynchronized => false;

	object ICollection.SyncRoot => this;

	object? IList.this[int index]
	{
		get
		{
			if (index != 0)
			{
				throw new IndexOutOfRangeException();
			}
			return _item;
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	bool IList.IsFixedSize => true;

	bool IList.IsReadOnly => true;

	int IReadOnlyCollection<T>.Count => 1;

	T IReadOnlyList<T>.this[int index]
	{
		get
		{
			if (index != 0)
			{
				throw new IndexOutOfRangeException();
			}
			return _item;
		}
	}

	int ICollection<T>.Count => 1;

	bool ICollection<T>.IsReadOnly => true;

	T IList<T>.this[int index]
	{
		get
		{
			if (index != 0)
			{
				throw new IndexOutOfRangeException();
			}
			return _item;
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	public <>z__ReadOnlySingleElementList(T item)
	{
		_item = item;
	}

	IEnumerator IEnumerable.GetEnumerator()
	{
		return new Enumerator(_item);
	}

	void ICollection.CopyTo(Array array, int index)
	{
		array.SetValue(_item, index);
	}

	int IList.Add(object? value)
	{
		throw new NotSupportedException();
	}

	void IList.Clear()
	{
		throw new NotSupportedException();
	}

	bool IList.Contains(object? value)
	{
		return EqualityComparer<T>.Default.Equals(_item, (T)value);
	}

	int IList.IndexOf(object? value)
	{
		if (!EqualityComparer<T>.Default.Equals(_item, (T)value))
		{
			return -1;
		}
		return 0;
	}

	void IList.Insert(int index, object? value)
	{
		throw new NotSupportedException();
	}

	void IList.Remove(object? value)
	{
		throw new NotSupportedException();
	}

	void IList.RemoveAt(int index)
	{
		throw new NotSupportedException();
	}

	IEnumerator<T> IEnumerable<T>.GetEnumerator()
	{
		return new Enumerator(_item);
	}

	void ICollection<T>.Add(T item)
	{
		throw new NotSupportedException();
	}

	void ICollection<T>.Clear()
	{
		throw new NotSupportedException();
	}

	bool ICollection<T>.Contains(T item)
	{
		return EqualityComparer<T>.Default.Equals(_item, item);
	}

	void ICollection<T>.CopyTo(T[] array, int arrayIndex)
	{
		array[arrayIndex] = _item;
	}

	bool ICollection<T>.Remove(T item)
	{
		throw new NotSupportedException();
	}

	int IList<T>.IndexOf(T item)
	{
		if (!EqualityComparer<T>.Default.Equals(_item, item))
		{
			return -1;
		}
		return 0;
	}

	void IList<T>.Insert(int index, T item)
	{
		throw new NotSupportedException();
	}

	void IList<T>.RemoveAt(int index)
	{
		throw new NotSupportedException();
	}
}
namespace util
{
	public enum BuiltinFunc : uint
	{
		sin,
		cos,
		tan,
		sinh,
		cosh,
		tanh,
		asin,
		acos,
		atan,
		atan2,
		sqrt,
		fmod,
		fposmod,
		posmod,
		floor,
		ceil,
		round,
		abs,
		sign,
		pow,
		log,
		exp,
		is_nan,
		is_inf,
		is_equal_approx,
		is_zero_approx,
		ease,
		decimals,
		step_decimals,
		stepify,
		lerp,
		lerp_angle,
		inverse_lerp,
		range_lerp,
		smoothstep,
		move_toward,
		dectime,
		randomize,
		randi,
		randf,
		rand_range,
		seed,
		rand_seed,
		deg2rad,
		rad2deg,
		linear2db,
		db2linear,
		polar2cartesian,
		cartesian2polar,
		wrapi,
		wrapf,
		max,
		min,
		clamp,
		nearest_po2,
		weakref,
		funcref,
		convert,
		@typeof,
		type_exists,
		@char,
		ord,
		str,
		print,
		printt,
		prints,
		printerr,
		printraw,
		print_debug,
		push_error,
		push_warning,
		var2str,
		str2var,
		var2bytes,
		bytes2var,
		range,
		load,
		inst2dict,
		dict2inst,
		validate_json,
		parse_json,
		to_json,
		hash,
		Color8,
		ColorN,
		print_stack,
		get_stack,
		instance_from_id,
		len,
		is_instance_valid,
		deep_equal,
		MAX
	}
	public static class ScriptTokenizer
	{
		private static readonly IReadOnlyDictionary<string, TokenType> Tokens = new Dictionary<string, TokenType>
		{
			{
				"continue",
				(TokenType)44
			},
			{
				"return",
				(TokenType)46
			},
			{
				"break",
				(TokenType)43
			},
			{
				"match",
				(TokenType)47
			},
			{
				"while",
				(TokenType)42
			},
			{
				"elif",
				(TokenType)39
			},
			{
				"else",
				(TokenType)40
			},
			{
				"pass",
				(TokenType)45
			},
			{
				"for",
				(TokenType)41
			},
			{
				"if",
				(TokenType)38
			},
			{
				"const",
				(TokenType)58
			},
			{
				"var",
				(TokenType)59
			},
			{
				"func",
				(TokenType)48
			},
			{
				"class",
				(TokenType)49
			},
			{
				"extends",
				(TokenType)51
			},
			{
				"is",
				(TokenType)52
			},
			{
				"as",
				(TokenType)60
			},
			{
				"onready",
				(TokenType)53
			},
			{
				"@tool",
				(TokenType)54
			},
			{
				"@export",
				(TokenType)56
			},
			{
				"yield",
				(TokenType)65
			},
			{
				"setget",
				(TokenType)57
			},
			{
				"static",
				(TokenType)55
			},
			{
				"void",
				(TokenType)61
			},
			{
				"enum",
				(TokenType)62
			},
			{
				"preload",
				(TokenType)63
			},
			{
				"assert",
				(TokenType)64
			},
			{
				"signal",
				(TokenType)66
			},
			{
				"breakpoint",
				(TokenType)67
			},
			{
				"sync",
				(TokenType)69
			},
			{
				"remote",
				(TokenType)68
			},
			{
				"master",
				(TokenType)70
			},
			{
				"slave",
				(TokenType)71
			},
			{
				"puppet",
				(TokenType)72
			},
			{
				"remotesync",
				(TokenType)73
			},
			{
				"mastersync",
				(TokenType)74
			},
			{
				"puppetsync",
				(TokenType)75
			},
			{
				"\n",
				(TokenType)89
			},
			{
				"PI",
				(TokenType)90
			},
			{
				"TAU",
				(TokenType)91
			},
			{
				"INF",
				(TokenType)93
			},
			{
				"NAN",
				(TokenType)94
			},
			{
				"error",
				(TokenType)95
			},
			{
				"cursor",
				(TokenType)97
			},
			{
				"self",
				(TokenType)3
			},
			{
				"in",
				(TokenType)6
			},
			{
				"or",
				(TokenType)14
			},
			{
				"and",
				(TokenType)13
			},
			{
				"not",
				(TokenType)15
			},
			{
				"_",
				(TokenType)92
			},
			{
				"[",
				(TokenType)76
			},
			{
				"]",
				(TokenType)77
			},
			{
				"{",
				(TokenType)78
			},
			{
				"}",
				(TokenType)79
			},
			{
				"(",
				(TokenType)80
			},
			{
				")",
				(TokenType)81
			},
			{
				",",
				(TokenType)82
			},
			{
				";",
				(TokenType)83
			},
			{
				".",
				(TokenType)84
			},
			{
				"?",
				(TokenType)85
			},
			{
				":",
				(TokenType)86
			},
			{
				"$",
				(TokenType)87
			},
			{
				"->",
				(TokenType)88
			},
			{
				">>=",
				(TokenType)30
			},
			{
				"<<=",
				(TokenType)29
			},
			{
				">>",
				(TokenType)22
			},
			{
				"<<",
				(TokenType)21
			},
			{
				"==",
				(TokenType)7
			},
			{
				"!=",
				(TokenType)8
			},
			{
				"&&",
				(TokenType)13
			},
			{
				"||",
				(TokenType)14
			},
			{
				"!",
				(TokenType)15
			},
			{
				"+=",
				(TokenType)24
			},
			{
				"-=",
				(TokenType)25
			},
			{
				"*=",
				(TokenType)26
			},
			{
				"/=",
				(TokenType)27
			},
			{
				"%=",
				(TokenType)28
			},
			{
				"&=",
				(TokenType)31
			},
			{
				"|=",
				(TokenType)32
			},
			{
				"^=",
				(TokenType)33
			},
			{
				"+",
				(TokenType)16
			},
			{
				"-",
				(TokenType)17
			},
			{
				"*",
				(TokenType)18
			},
			{
				"/",
				(TokenType)19
			},
			{
				"%",
				(TokenType)20
			},
			{
				"~",
				(TokenType)37
			},
			{
				"&",
				(TokenType)34
			},
			{
				"|",
				(TokenType)35
			},
			{
				"^",
				(TokenType)36
			},
			{
				"<=",
				(TokenType)10
			},
			{
				">=",
				(TokenType)12
			},
			{
				"<",
				(TokenType)9
			},
			{
				">",
				(TokenType)11
			},
			{
				"=",
				(TokenType)23
			}
		};

		private static readonly IReadOnlySet<string> Symbols = new HashSet<string>
		{
			"->", ">>=", "<<=", ">>", "<<", "==", "!=", "&&", "||", "!",
			"+=", "-=", "*=", "/=", "%=", "&=", "|=", "^=", "[", "]",
			"{", "}", "(", ")", ",", ";", ".", "?", ":", "$",
			"+", "-", "*", "/", "%", "~", "&", "|", "^", "<=",
			">=", "<", ">", "="
		};

		private static readonly IReadOnlyDictionary<string, uint> BuiltinTypeIds = new Dictionary<string, uint>
		{
			{ "int", 2u },
			{ "Vector3", 7u },
			{ "Color", 14u }
		};

		private static void InsertNewLine(IEnumerator<string> enumerator, uint baseIndent, List<Token> toFlush)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			if (enumerator.MoveNext())
			{
				uint num = uint.Parse(enumerator.Current);
				toFlush.Add(new Token((TokenType)89, (uint?)(num + baseIndent)));
			}
		}

		private static void BuildNumber(IEnumerator<string> enumerator, List<Token> toFlush, out bool foundFull)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Expected O, but got Unknown
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Expected O, but got Unknown
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Expected O, but got Unknown
			foundFull = true;
			int num = 1;
			if (enumerator.Current == "-")
			{
				num = -1;
				if (!enumerator.MoveNext())
				{
					return;
				}
			}
			if (!long.TryParse(enumerator.Current, out var result))
			{
				toFlush.Add(new Token((TokenType)17, (uint?)null));
				foundFull = false;
			}
			else if (enumerator.MoveNext())
			{
				long result2;
				if (enumerator.Current != ".")
				{
					toFlush.Add((Token)new ConstantToken((Variant)new IntVariant(result * num, false)));
					foundFull = false;
				}
				else if (enumerator.MoveNext() && long.TryParse(enumerator.Current, out result2))
				{
					double num2 = (double)result + (double)result2 / Math.Pow(10.0, result2.ToString().Length);
					toFlush.Add((Token)new ConstantToken((Variant)new RealVariant(num2 * (double)num, false)));
				}
			}
		}

		public static IEnumerable<Token> Tokenize(string gdScript, uint baseIndent = 0u)
		{
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Expected O, but got Unknown
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Expected O, but got Unknown
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Expected O, but got Unknown
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Expected O, but got Unknown
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Expected O, but got Unknown
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Expected O, but got Unknown
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Expected O, but got Unknown
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Expected O, but got Unknown
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Expected O, but got Unknown
			List<Token> finalTokens = new List<Token>();
			IEnumerable<string> enumerable = SanitizeInput(TokenizeString(gdScript + " "));
			string previous = string.Empty;
			string idName = string.Empty;
			List<Token> toFlush = new List<Token>(2);
			IEnumerator<string> enumerator = enumerable.GetEnumerator();
			bool flag = false;
			while (flag || enumerator.MoveNext())
			{
				flag = false;
				uint value;
				BuiltinFunc result;
				TokenType value2;
				bool result2;
				if (enumerator.Current == "\n")
				{
					InsertNewLine(enumerator, baseIndent, toFlush);
					endAndFlushId();
				}
				else if (char.IsDigit(enumerator.Current[0]))
				{
					BuildNumber(enumerator, toFlush, out var foundFull);
					flag = !foundFull;
					endAndFlushId();
				}
				else if (BuiltinTypeIds.TryGetValue(enumerator.Current, out value))
				{
					toFlush.Add(new Token((TokenType)4, (uint?)value));
					endAndFlushId();
				}
				else if (enumerator.Current == "null")
				{
					toFlush.Add((Token)new ConstantToken((Variant)new NilVariant()));
					endAndFlushId();
				}
				else if (Enum.TryParse<BuiltinFunc>(enumerator.Current, out result))
				{
					toFlush.Add(new Token((TokenType)5, (uint?)(uint)result));
					endAndFlushId();
				}
				else if (Tokens.TryGetValue(enumerator.Current, out value2))
				{
					toFlush.Add(new Token(value2, (uint?)null));
					endAndFlushId();
				}
				else if (enumerator.Current.StartsWith('"') || enumerator.Current.StartsWith('\''))
				{
					string current = enumerator.Current;
					toFlush.Add((Token)new ConstantToken((Variant)new StringVariant(current.Substring(1, current.Length - 2))));
					endAndFlushId();
				}
				else if (bool.TryParse(enumerator.Current, out result2))
				{
					toFlush.Add((Token)new ConstantToken((Variant)new BoolVariant(result2)));
					endAndFlushId();
				}
				else
				{
					idName += enumerator.Current;
					end();
				}
			}
			return finalTokens.ToArray();
			void end()
			{
				previous = enumerator.Current;
				finalTokens.AddRange(toFlush);
				toFlush.Clear();
			}
			void endAndFlushId()
			{
				//IL_002a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0034: Expected O, but got Unknown
				if (idName == string.Empty)
				{
					end();
				}
				else
				{
					finalTokens.Add((Token)new IdentifierToken(idName.Trim()));
					idName = string.Empty;
					end();
				}
			}
		}

		private static IEnumerable<string> SanitizeInput(IEnumerable<string> tokens)
		{
			foreach (string token in tokens)
			{
				if (!(token != "\n") || !string.IsNullOrWhiteSpace(token))
				{
					yield return token;
				}
			}
		}

		private static IEnumerable<string> TokenizeString(string text)
		{
			StringBuilder builder = new StringBuilder(20);
			for (int i = 0; i < text.Length; i++)
			{
				if (text[i] == '\'' || text[i] == '"')
				{
					char delimiter = text[i];
					yield return ClearBuilder();
					builder.Append(delimiter);
					for (i++; i < text.Length; i++)
					{
						builder.Append(text[i]);
						if (text[i] == delimiter)
						{
							break;
						}
					}
					yield return ClearBuilder();
				}
				else
				{
					if (text[i] == '\r')
					{
						continue;
					}
					if (text[i] == '\n')
					{
						yield return ClearBuilder();
						int start = i;
						for (i++; i < text.Length && text[i] == '\t'; i++)
						{
						}
						i--;
						yield return "\n";
						yield return $"{i - start}";
						continue;
					}
					bool flag = false;
					foreach (string delimiter2 in Symbols)
					{
						if (Match(text, i, delimiter2))
						{
							yield return ClearBuilder();
							yield return delimiter2;
							i += delimiter2.Length - 1;
							flag = true;
							break;
						}
					}
					if (!flag)
					{
						if (text[i] == ' ')
						{
							yield return ClearBuilder();
						}
						else
						{
							builder.Append(text[i]);
						}
					}
				}
			}
			yield return "\n";
			string ClearBuilder()
			{
				string result = builder.ToString();
				builder.Clear();
				return result;
			}
		}

		private static bool Match(string text, int index, string match)
		{
			if (index + match.Length > text.Length)
			{
				return false;
			}
			for (int i = 0; i < match.Length; i++)
			{
				if (text[index + i] != match[i])
				{
					return false;
				}
			}
			return true;
		}
	}
}
namespace util.LexicalTransformer
{
	public static class TransformationPatternFactory
	{
		public static Func<Token, bool>[] CreateGlobalsPattern()
		{
			return new Func<Token, bool>[3]
			{
				(Token t) => (int)t.Type == 51,
				(Token t) => (int)t.Type == 1,
				(Token t) => (int)t.Type == 89
			};
		}

		public static Func<Token, bool>[] CreateFunctionDefinitionPattern(string name, string[]? args = null)
		{
			List<Func<Token, bool>> list = new List<Func<Token, bool>>();
			list.Add((Token t) => (int)t.Type == 48);
			list.Add(delegate(Token t)
			{
				IdentifierToken val = (IdentifierToken)(object)((t is IdentifierToken) ? t : null);
				return val != null && val.Name == name;
			});
			list.Add((Token t) => (int)t.Type == 80);
			if (args != null && args.Length > 0)
			{
				foreach (string arg in args)
				{
					list.Add(delegate(Token t)
					{
						IdentifierToken val = (IdentifierToken)(object)((t is IdentifierToken) ? t : null);
						return val != null && val.Name == arg;
					});
					list.Add((Token t) => (int)t.Type == 82);
				}
				list.RemoveAt(list.Count - 1);
			}
			list.Add((Token t) => (int)t.Type == 81);
			list.Add((Token t) => (int)t.Type == 86);
			return list.ToArray();
		}

		public static Func<Token, bool>[] CreateGdSnippetPattern(string snippet, uint indent = 0u)
		{
			return ScriptTokenizer.Tokenize(snippet, indent).Select((Func<Token, Func<Token, bool>>)((Token snippetToken) => delegate(Token t)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Invalid comparison between Unknown and I4
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				//IL_003d: Invalid comparison between Unknown and I4
				//IL_006d: 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)
				if ((int)t.Type == 1)
				{
					Token obj = snippetToken;
					IdentifierToken val = (IdentifierToken)(object)((obj is IdentifierToken) ? obj : null);
					if (val != null)
					{
						IdentifierToken val2 = (IdentifierToken)(object)((t is IdentifierToken) ? t : null);
						if (val2 != null)
						{
							return val.Name == val2.Name;
						}
					}
					return false;
				}
				if ((int)t.Type == 2)
				{
					Token obj2 = snippetToken;
					ConstantToken val3 = (ConstantToken)(object)((obj2 is ConstantToken) ? obj2 : null);
					if (val3 != null)
					{
						ConstantToken val4 = (ConstantToken)(object)((t is ConstantToken) ? t : null);
						if (val4 != null)
						{
							return val3.Value.Equals(val4.Value);
						}
					}
					return false;
				}
				return t.Type == snippetToken.Type;
			})).ToArray();
		}
	}
	public enum Operation
	{
		None,
		ReplaceAll,
		ReplaceLast,
		Append,
		Prepend
	}
	public static class OperationExtensions
	{
		public static bool RequiresBuffer(this Operation operation)
		{
			if (operation == Operation.ReplaceAll || operation == Operation.Prepend)
			{
				return true;
			}
			return false;
		}

		public static bool YieldTokenBeforeOperation(this Operation operation)
		{
			if (operation == Operation.None || operation == Operation.Append)
			{
				return true;
			}
			return false;
		}

		public static bool YieldTokenAfterOperation(this Operation operation)
		{
			if (!operation.RequiresBuffer() && !operation.YieldTokenBeforeOperation())
			{
				return operation != Operation.ReplaceLast;
			}
			return false;
		}
	}
	public record TransformationRule(string Name, Func<Token, bool>[] Pattern, Func<Token, bool>[] ScopePattern, IEnumerable<Token> Tokens, Operation Operation, uint Times, Func<bool> Predicate)
	{
		public MultiTokenWaiter CreateMultiTokenWaiter()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			return new MultiTokenWaiter(Pattern, false, false);
		}

		public MultiTokenWaiter CreateMultiTokenWaiterForScope()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			return new MultiTokenWaiter(ScopePattern, false, false);
		}
	}
	public class TransformationRuleBuilder
	{
		private string? _name;

		private Func<Token, bool>[]? _pattern;

		private Func<Token, bool>[] _scopePattern = Array.Empty<Func<Token, bool>>();

		private IEnumerable<Token>? _tokens;

		private uint _times = 1u;

		private Operation _operation = Operation.Append;

		private Func<bool> _predicate = () => true;

		public TransformationRuleBuilder Named(string name)
		{
			_name = name;
			return this;
		}

		public TransformationRuleBuilder Matching(Func<Token, bool>[] pattern)
		{
			_pattern = pattern;
			return this;
		}

		public TransformationRuleBuilder With(IEnumerable<Token> tokens)
		{
			_tokens = tokens;
			return this;
		}

		public TransformationRuleBuilder With(Token token)
		{
			_tokens = new <>z__ReadOnlySingleElementList<Token>(token);
			return this;
		}

		public TransformationRuleBuilder With(string snippet, uint indent = 0u)
		{
			_tokens = ScriptTokenizer.Tokenize(snippet, indent);
			return this;
		}

		public TransformationRuleBuilder Do(Operation operation)
		{
			_operation = operation;
			return this;
		}

		public TransformationRuleBuilder ExpectTimes(uint times)
		{
			_times = times;
			return this;
		}

		public TransformationRuleBuilder ScopedTo(Func<Token, bool>[] scopePattern)
		{
			_scopePattern = scopePattern;
			return this;
		}

		public TransformationRuleBuilder When(Func<bool> predicate)
		{
			_predicate = predicate;
			return this;
		}

		public TransformationRuleBuilder When(bool eligible)
		{
			_predicate = () => eligible;
			return this;
		}

		public TransformationRule Build()
		{
			if (string.IsNullOrEmpty(_name))
			{
				throw new ArgumentNullException("_name", "Name cannot be null or empty");
			}
			if (_pattern == null)
			{
				throw new ArgumentNullException("_pattern", "Pattern cannot be null");
			}
			if (_tokens == null)
			{
				throw new ArgumentNullException("_tokens", "Tokens cannot be null");
			}
			return new TransformationRule(_name, _pattern, _scopePattern, _tokens, _operation, _times, _predicate);
		}
	}
	public class TransformationRuleScriptMod(IModInterface mod, string name, string scriptPath, Func<bool> predicate, TransformationRule[] rules) : IScriptMod
	{
		public bool ShouldRun(string path)
		{
			if (path != scriptPath)
			{
				return false;
			}
			if (!predicate())
			{
				mod.Logger.Warning(string.Concat(Enumerable.Repeat("!", 15)));
				mod.Logger.Warning("[" + name + "] Predicate failed!!!!!!, not patching.");
				mod.Logger.Warning(string.Concat(Enumerable.Repeat("!", 15)));
				return false;
			}
			return true;
		}

		public IEnumerable<Token> Modify(string path, IEnumerable<Token> tokens)
		{
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Invalid comparison between Unknown and I4
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Invalid comparison between Unknown and I4
			List<TransformationRule> source = rules.Where(delegate(TransformationRule rule)
			{
				bool num2 = rule.Predicate();
				if (!num2)
				{
					mod.Logger.Information($"[{name}] Skipping patch {rule.Name}...");
				}
				return num2;
			}).ToList();
			List<(TransformationRule, MultiTokenWaiter, List<Token>)> list = source.Select((TransformationRule rule) => (Rule: rule, Waiter: rule.CreateMultiTokenWaiter(), Buffer: new List<Token>())).ToList();
			mod.Logger.Information("[" + name + "] Patching " + path);
			Dictionary<string, (int, uint)> dictionary = source.ToDictionary((TransformationRule r) => r.Name, (TransformationRule r) => (Occurred: 0, Expected: r.Times));
			bool flag = true;
			List<Token> list2 = new List<Token>();
			list2.AddRange(tokens);
			List<Token> list3 = new List<Token>();
			foreach (var item in list)
			{
				bool flag2 = item.Item1.ScopePattern.Length != 0;
				bool flag3 = !flag2;
				uint? num = null;
				MultiTokenWaiter val = item.Item1.CreateMultiTokenWaiterForScope();
				foreach (Token item2 in list2)
				{
					if (flag3 && flag2)
					{
						if (!num.HasValue && (int)item2.Type == 89)
						{
							num = item2.AssociatedData.GetValueOrDefault();
						}
						else if (num.HasValue && (int)item2.Type == 89)
						{
							flag3 = item2.AssociatedData.GetValueOrDefault() >= num;
						}
					}
					else if (flag2 && val.Check(item2))
					{
						val.Reset();
						flag3 = true;
					}
					if (!flag3)
					{
						list3.Add(item2);
						continue;
					}
					item.Item2.Check(item2);
					if (item.Item2.Step == 0)
					{
						list3.AddRange(item.Item3);
						item.Item3.Clear();
					}
					else
					{
						if (item.Item1.Operation.RequiresBuffer())
						{
							item.Item3.Add(item2);
							flag = false;
						}
						if (item.Item2.Matched)
						{
							item.Item2.Reset();
							if (item.Item1.Operation.YieldTokenBeforeOperation())
							{
								list3.Add(item2);
								flag = false;
							}
							else
							{
								flag = item.Item1.Operation.YieldTokenAfterOperation();
							}
							switch (item.Item1.Operation)
							{
							case Operation.Prepend:
								list3.AddRange(item.Item1.Tokens);
								list3.AddRange(item.Item3);
								item.Item3.Clear();
								break;
							case Operation.ReplaceAll:
							case Operation.ReplaceLast:
							case Operation.Append:
								item.Item3.Clear();
								list3.AddRange(item.Item1.Tokens);
								break;
							}
							mod.Logger.Information($"[{name}] Patch {item.Item1.Name} OK!");
							string name = item.Item1.Name;
							(int, uint) value = dictionary[item.Item1.Name];
							value.Item1 = dictionary[item.Item1.Name].Item1 + 1;
							dictionary[name] = value;
						}
					}
					if (flag)
					{
						list3.Add(item2);
					}
					else
					{
						flag = true;
					}
				}
				list2.Clear();
				list2.AddRange(list3);
				list3.Clear();
			}
			foreach (KeyValuePair<string, (int, uint)> item3 in dictionary.Where<KeyValuePair<string, (int, uint)>>((KeyValuePair<string, (int Occurred, uint Expected)> result) => result.Value.Occurred != result.Value.Expected))
			{
				mod.Logger.Error($"[{name}] Patch {item3.Key} FAILED!!!!!!! Times expected={item3.Value.Item2}, actual={item3.Value.Item1}");
			}
			return list2;
		}
	}
	public class TransformationRuleScriptModBuilder
	{
		private IModInterface? _mod;

		private string? _name;

		private string? _scriptPath;

		private Func<bool> _predicate = () => true;

		private List<TransformationRule> _rules = new List<TransformationRule>();

		public TransformationRuleScriptModBuilder ForMod(IModInterface mod)
		{
			_mod = mod;
			return this;
		}

		public TransformationRuleScriptModBuilder When(Func<bool> predicate)
		{
			_predicate = predicate;
			return this;
		}

		public TransformationRuleScriptModBuilder Named(string name)
		{
			_name = name;
			return this;
		}

		public TransformationRuleScriptModBuilder Patching(string scriptPath)
		{
			_scriptPath = scriptPath;
			if (scriptPath.EndsWith(".gd"))
			{
				throw new ArgumentException("Your script path should end in gdc NOT gd");
			}
			return this;
		}

		public TransformationRuleScriptModBuilder AddRule(TransformationRule rule)
		{
			if (_rules.Select((TransformationRule r) => r.Name).Contains(rule.Name))
			{
				throw new InvalidOperationException("Another rule with the name '" + rule.Name + "' already exists!");
			}
			_rules.Add(rule);
			return this;
		}

		public TransformationRuleScriptModBuilder AddRule(TransformationRuleBuilder rule)
		{
			return AddRule(rule.Build());
		}

		public TransformationRuleScriptMod Build()
		{
			if (_mod == null)
			{
				throw new ArgumentNullException("_mod", "Mod cannot be null");
			}
			if (string.IsNullOrEmpty(_name))
			{
				throw new ArgumentNullException("_name", "Name cannot be null or empty");
			}
			if (string.IsNullOrEmpty(_scriptPath))
			{
				throw new ArgumentNullException("_scriptPath", "Script path cannot be null or empty");
			}
			return new TransformationRuleScriptMod(_mod, _name, _scriptPath, _predicate, _rules.ToArray());
		}
	}
}
namespace patchlist
{
	public static class networkPatch
	{
		public static IScriptMod Create(IModInterface modInterface)
		{
			return (IScriptMod)(object)new TransformationRuleScriptModBuilder().ForMod(modInterface).Named("zoe's shitty patches (network exploits)").Patching("res://Scenes/Singletons/SteamNetwork.gdc")
				.AddRule(new TransformationRuleBuilder().Named("Define crash checker node, add debounce vars").Matching(TransformationPatternFactory.CreateGlobalsPattern()).With("\nvar lastLetterAcceptedTime = 0\nvar lastLetterDeniedTime = 0\n\nvar naughty_list = {}\n\nfunc arraySafetyCheck(arr = []):\n\tfor c in arr:\n\t\tif typeof(c) == TYPE_NIL or (typeof(c) == TYPE_REAL and is_nan(c)):\n\t\t\treturn false\n\n\t\tif typeof(c) == TYPE_ARRAY:\n\t\t\treturn arraySafetyCheck(c)\n\n\treturn true\n\nfunc packetSafetyCheck(type, DATA):\n\tvar safe = true\n\n\tif type == \"actor_action\" and DATA.get(\"action\") == \"_play_sfx\":\n\t\treturn true\n\n\tvar parameters = DATA.get(\"params\")\n\n\tif typeof(parameters) == TYPE_ARRAY:\n\t\tsafe = arraySafetyCheck(parameters)\n\telif typeof(parameters) == TYPE_DICTIONARY:\n\t\tsafe = arraySafetyCheck(parameters.values())\n\n\treturn safe\n"))
				.AddRule(new TransformationRuleBuilder().Named("Adjust default packet timeout limits").Do(Operation.ReplaceAll).Matching(TransformationPatternFactory.CreateGdSnippetPattern("const MAX_PACKET_TIMEOUT_LIMIT = 1500\nconst MAX_MAJOR_PACKET_TIMEOUT_LIMIT = 3000"))
					.With("const MAX_PACKET_TIMEOUT_LIMIT = 1000\nconst MAX_MAJOR_PACKET_TIMEOUT_LIMIT = 2000"))
				.AddRule(new TransformationRuleBuilder().Named("Throttling for letter notifications").Do(Operation.ReplaceAll).Matching(TransformationPatternFactory.CreateGdSnippetPattern("\"letter_was_accepted\":\n\tPlayerData._letter_was_accepted()\n\"letter_was_denied\":\n\tPlayerData._letter_was_denied()"))
					.With("\"letter_was_accepted\":\n\tif Time.get_ticks_msec() - lastLetterAcceptedTime > 1000:\n\t\tlastLetterAcceptedTime = Time.get_ticks_msec()\n\t\tPlayerData._letter_was_accepted()\n\"letter_was_denied\":\n\tif Time.get_ticks_msec() - lastLetterDeniedTime > 1000:\n\t\tlastLetterDeniedTime = Time.get_ticks_msec()\n\t\tPlayerData._letter_was_denied()", 3u))
				.AddRule(new TransformationRuleBuilder().Named("Packet validation and early return for invalid packets").Do(Operation.ReplaceAll).Matching(TransformationPatternFactory.CreateGdSnippetPattern("FLUSH_PACKET_INFORMATION[PACKET_SENDER] += 1"))
					.With("FLUSH_PACKET_INFORMATION[PACKET_SENDER] += 1\n\nif DATA.has(\"parameters\"):\n\tvar safe = packetSafetyCheck(type, DATA)\n\n\tif not safe:\n\t\treturn", 2u))
				.AddRule(new TransformationRuleBuilder().Named("Drop message packets over 480 chars hopefully (base game limit)").Do(Operation.ReplaceAll).Matching(TransformationPatternFactory.CreateGdSnippetPattern("if not _message_cap(PACKET_SENDER): return"))
					.With("if not _message_cap(PACKET_SENDER): return\n\nif DATA[\"message\"].length() > 484:\n\tprint(\"message blocked, too long, sent by:\", PACKET_SENDER)\n\treturn", 4u))
				.AddRule(new TransformationRuleBuilder().Named("Peer rate limit for large packets").Do(Operation.ReplaceAll).Matching(TransformationPatternFactory.CreateGdSnippetPattern("if not PACKET.keys().has(\"identity\") or not PACKET.keys().has(\"payload\"):\n\tprint(\"Packet Disregarded! Invalid Packet Structure\")\n\treturn\n\nvar PACKET_SENDER: int = int(PACKET[\"identity\"])"))
					.With("if not PACKET.keys().has(\"identity\") or not PACKET.keys().has(\"payload\"):\n\tprint(\"Packet Disregarded! Invalid Packet Structure\")\n\treturn\n\nvar PACKET_SENDER: int = int(PACKET[\"identity\"])\n\nif naughty_list.has(PACKET_SENDER):\n\tprint(PACKET_SENDER, \"is on the naughty list, packet blocked\")\n\nif PACKET_SIZE > 8000 and not naughty_list.has(PACKET_SENDER):\n\tnaughty_list[PACKET_SENDER] = 0\n\tprint(PACKET_SENDER, \"added to the naughty list. :c\")\n\treturn\n", 2u))
				.AddRule(new TransformationRuleBuilder().Named("Prevent bad *packet arrays* from being logged maybe hopefully").Do(Operation.ReplaceAll).Matching(TransformationPatternFactory.CreateGdSnippetPattern("if not valid:\n\tprint(array)\n\tprint(\"Array is invalid.\")\n"))
					.With("if not valid:\n\tprint(\"Array is invalid. Packet dump bypassed by ExploitPatches.\")\n\t\t", 1u))
				.AddRule(new TransformationRuleBuilder().Named("Prevent bad *packets* from being logged maybe hopefully").Do(Operation.ReplaceAll).Matching(TransformationPatternFactory.CreateGdSnippetPattern("if not valid:\n\tprint(data)\n\tprint(\"Packet is invalid.\")\n"))
					.With("if not valid:\n\tprint(\"Packet is invalid. Packet dump bypassed by ExploitPatches.\")\n", 1u))
				.AddRule(new TransformationRuleBuilder().Named("Prevent bad *actor action packets* from being logged maybe hopefully").Do(Operation.ReplaceAll).Matching(TransformationPatternFactory.CreateGdSnippetPattern("if ACTOR_ACTIONS[DATA[\"actor_id\"]].size() > 128:\n\tprint(DATA[\"actor_id\"], \" Too many actor actions queued. Disregarding.\")\n\tprint(\"Packet Dump: \", ACTOR_ACTIONS[DATA[\"actor_id\"]])\n\treturn"))
					.With("if ACTOR_ACTIONS[DATA[\"actor_id\"]].size() > 128:\n\tprint(\"Too many actor actions. Dump bypassed by ExploitPatches.\")\n\treturn", 4u))
				.Build();
		}
	}
}
namespace SaruShinobie.ExploitPatches
{
	public class Config
	{
		[JsonInclude]
		public bool SomeSetting = true;
	}
	public class Mod : IMod, IDisposable
	{
		public Mod(IModInterface modInterface)
		{
			modInterface.RegisterScriptMod(networkPatch.Create(modInterface));
		}

		public void Dispose()
		{
		}
	}
}