Decompiled source of SwapperPlugin v1.2.2

Plugins/SwapperPlugin.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using MelonLoader;
using MelonLoader.Utils;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Collections.Generic;
using Newtonsoft.Json;
using SwapperPlugin;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(Plugin), "SwapperPlugin", "1.0.0", "coolpaca", null)]
[assembly: MelonColor(255, 149, 82, 255)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("SwapperPlugin")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+8936a24bae6a548b90976e1fc86dc48837cf0171")]
[assembly: AssemblyProduct("SwapperPlugin")]
[assembly: AssemblyTitle("SwapperPlugin")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SwapperPlugin
{
	internal enum Backend
	{
		Unknown,
		Il2cpp,
		Mono,
		S1API
	}
	internal class AssemblyChecker
	{
		public static string[] monoRefs = new string[2] { "scheduleone", "system" };

		public static string[] il2cppRefs = new string[2] { "il2cppscheduleone", "il2cppsystem" };

		public static (bool, Backend) CheckAtPath(string path)
		{
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			KeyValuePair<bool, Backend> keyValuePair = new KeyValuePair<bool, Backend>(key: false, Backend.Unknown);
			string directoryName = Path.GetDirectoryName(path);
			if (!File.Exists(path))
			{
				return (false, Backend.Unknown);
			}
			if (!path.Contains(".dll"))
			{
				return (false, Backend.Unknown);
			}
			if (Path.GetFileName(path).ToLower().Contains("mono"))
			{
				return (true, Backend.Mono);
			}
			if (Path.GetFileName(path).ToLower().Contains("il2cpp"))
			{
				return (true, Backend.Il2cpp);
			}
			AssemblyDefinition val = AssemblyDefinition.ReadAssembly(path);
			Enumerator<ModuleDefinition> enumerator = val.Modules.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					ModuleDefinition current = enumerator.Current;
					IEnumerable<TypeReference> typeReferences = current.GetTypeReferences();
					if (typeReferences.Any((TypeReference x) => x.Namespace.ToLower().Contains("s1api")))
					{
						return (false, Backend.S1API);
					}
					if (typeReferences.Any((TypeReference x) => il2cppRefs.Contains(x.Namespace.ToLower())))
					{
						return (false, Backend.Il2cpp);
					}
					if (typeReferences.Any((TypeReference x) => monoRefs.Contains(x.Namespace.ToLower())))
					{
						return (false, Backend.Mono);
					}
				}
			}
			finally
			{
				((IDisposable)enumerator).Dispose();
			}
			return (false, Backend.Unknown);
		}
	}
	[Serializable]
	public class Config
	{
		public bool disableThemToo = false;

		public List<string> blackList = new List<string>();
	}
	public class Plugin : MelonPlugin
	{
		private static Backend backend = Backend.Unknown;

		public static Config conf = new Config();

		private static string configJson = "\\config.json";

		public override void OnPreInitialization()
		{
			configJson = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + configJson;
			if (File.Exists(configJson))
			{
				conf = JsonConvert.DeserializeObject<Config>(File.ReadAllText(configJson));
				if (conf.blackList.Count == 0)
				{
					conf.blackList.AddRange(new <>z__ReadOnlyArray<string>(new string[3] { "AutoWater.dll", "SwapperPlugin.dll", "MLVScan.MelonLoader.dll" }));
				}
			}
			else
			{
				MelonLogger.Msg("Config file not found. writing new one. at \n" + configJson);
				if (conf.blackList.Count == 0)
				{
					conf.blackList.AddRange(new <>z__ReadOnlyArray<string>(new string[3] { "AutoWater.dll", "SwapperPlugin.dll", "MLVScan.MelonLoader.dll" }));
				}
				File.WriteAllText(configJson, JsonConvert.SerializeObject((object)conf, (Formatting)1));
			}
			((MelonPlugin)this).OnPreInitialization();
			string path = Path.GetDirectoryName(MelonEnvironment.ModsDirectory) + "\\Mods";
			Plugin.backend = (MelonUtils.IsGameIl2Cpp() ? Backend.Il2cpp : Backend.Mono);
			if (!Directory.Exists(path))
			{
				return;
			}
			string[] files = Directory.GetFiles(path, "*", SearchOption.AllDirectories);
			for (int i = 0; i < files.Length; i++)
			{
				if (files[i].Contains(".dll"))
				{
					File.Move(files[i], files[i].Replace(".di", ""));
					files[i] = files[i].Replace(".di", "");
				}
			}
			List<string> list = new List<string>();
			string[] array = files;
			foreach (string s in array)
			{
				if (!s.Contains(".dll") || s.Contains(".old") || Path.GetFileName(s).Contains("S1API"))
				{
					continue;
				}
				var (flag, backend) = AssemblyChecker.CheckAtPath(s);
				switch (backend)
				{
				case Backend.Unknown:
					MelonLogger.Error("Found a DLL, but couldn't determine backend!\nTell coolpaca in the S1 modding discord and\nprovide the mod name! File: " + Path.GetFileName(s));
					continue;
				case Backend.S1API:
					continue;
				}
				if (backend != Plugin.backend)
				{
					GC.Collect();
					GC.WaitForPendingFinalizers();
					if ((flag || conf.disableThemToo) && !conf.blackList.Any((string x) => x == Path.GetFileName(s)))
					{
						File.Move(s, s + ".di");
					}
					else
					{
						list.Add(s);
					}
				}
			}
			MelonLogger.Warning(string.Format("Found {0} {1}\n", list.Count, (list.Count > 1) ? "files" : "file") + "that could cause an error when loading. Add the following\nto the config to disable this warning for that mod, or disable them\nCan be done by adding \".di\" to the file extension");
			foreach (string item in list)
			{
				MelonLogger.Warning(Path.GetFileName(item));
			}
		}
	}
}
internal sealed class <>z__ReadOnlyArray<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T>
{
	int ICollection.Count => _items.Length;

	bool ICollection.IsSynchronized => false;

	object ICollection.SyncRoot => this;

	object IList.this[int index]
	{
		get
		{
			return _items[index];
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	bool IList.IsFixedSize => true;

	bool IList.IsReadOnly => true;

	int IReadOnlyCollection<T>.Count => _items.Length;

	T IReadOnlyList<T>.this[int index] => _items[index];

	int ICollection<T>.Count => _items.Length;

	bool ICollection<T>.IsReadOnly => true;

	T IList<T>.this[int index]
	{
		get
		{
			return _items[index];
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	public <>z__ReadOnlyArray(T[] items)
	{
		_items = items;
	}

	IEnumerator IEnumerable.GetEnumerator()
	{
		return ((IEnumerable)_items).GetEnumerator();
	}

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

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

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

	bool IList.Contains(object value)
	{
		return ((IList)_items).Contains(value);
	}

	int IList.IndexOf(object value)
	{
		return ((IList)_items).IndexOf(value);
	}

	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 ((IEnumerable<T>)_items).GetEnumerator();
	}

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

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

	bool ICollection<T>.Contains(T item)
	{
		return ((ICollection<T>)_items).Contains(item);
	}

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

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

	int IList<T>.IndexOf(T item)
	{
		return ((IList<T>)_items).IndexOf(item);
	}

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

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