Decompiled source of MapPackLoader v1.0.2

MapPackLoader.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using Microsoft.CodeAnalysis;
using MiniJSON;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.6", FrameworkDisplayName = ".NET Framework 4.6")]
[assembly: AssemblyCompany("MapPackLoader")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("My first plugin")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("MapPackLoader")]
[assembly: AssemblyTitle("MapPackLoader")]
[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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace MapPackLoader
{
	[BepInPlugin("com.kijetesantakalu912345.MapPackLoader", "MapPackLoader", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		public static string startTimeString = DateTime.Now.ToString("yyyy-MMM-dd hhtt ss.fff");

		public void Awake()
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin MapPackLoader is loaded!");
			List<string> list = RecursivelySearchDirectoryForFile(Paths.PluginPath, "mappack.zip");
			if (list.Count == 0)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"No mappack.zip found! map pack loader will not load any map pack.");
				return;
			}
			if (list.Count > 1)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("multiple `mappack.zip`s found! The mappack.zip at `" + list[0] + "` will be used. paths of all map packs:"));
				string text = "";
				foreach (string item in list)
				{
					text = text + item + "\n";
				}
				((BaseUnityPlugin)this).Logger.LogWarning((object)text);
			}
			string archiveFileName = list[0];
			ZipArchive val = ZipFile.OpenRead(archiveFileName);
			try
			{
				string text2 = Path.Combine(Paths.PluginPath, "Maps");
				((BaseUnityPlugin)this).Logger.LogInfo((object)("maps folder: " + text2));
				if (!Directory.Exists(text2))
				{
					Directory.CreateDirectory(text2);
				}
				CheckAndUpdateOldMaps(val, text2);
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		public static List<string> RecursivelySearchDirectoryForFile(string searchPath, string containedFileName)
		{
			List<string> list = new List<string>();
			string[] files = Directory.GetFiles(searchPath);
			for (int i = 0; i < files.Count(); i++)
			{
				if (Path.GetFileName(files[i]).Contains(containedFileName))
				{
					list.Add(files[i]);
				}
			}
			string[] directories = Directory.GetDirectories(searchPath);
			for (int j = 0; j < directories.Count(); j++)
			{
				list.AddRange(RecursivelySearchDirectoryForFile(directories[j], containedFileName));
			}
			return list;
		}

		public void CheckAndUpdateOldMaps(ZipArchive mapPackZip, string mapsFolderPath)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Expected O, but got Unknown
			Dictionary<string, ZippedMap> dictionary = new Dictionary<string, ZippedMap>();
			for (int i = 0; i < mapPackZip.Entries.Count; i++)
			{
				ZipArchive val = new ZipArchive(mapPackZip.Entries[i].Open());
				ZipArchiveEntry val2 = null;
				val2 = val.GetEntry("MetaData.json");
				if (val2 == null)
				{
					throw new Exception("Invalid map \"" + mapPackZip.Entries[i].FullName + "\" in the map pack has no MetaData.json file. Map pack not extracted.");
				}
				string json = new StreamReader(val2.Open()).ReadToEnd();
				Dictionary<string, object> dictionary2 = Json.Deserialize(json) as Dictionary<string, object>;
				string text = dictionary2["MapName"].ToString();
				uint version = Convert.ToUInt32(dictionary2["MapVersion"]);
				dictionary.Add(text, new ZippedMap(text, version, val, mapPackZip.Entries[i].Name));
			}
			for (int j = 0; j < Directory.GetFiles(mapsFolderPath).Length; j++)
			{
				string text2 = Directory.GetFiles(mapsFolderPath)[j];
				if (Path.GetExtension(text2) != ".zip")
				{
					continue;
				}
				ZipArchive val3 = new ZipArchive((Stream)File.OpenRead(text2));
				try
				{
					ZipArchiveEntry val4 = null;
					val4 = val3.GetEntry("MetaData.json");
					if (val4 == null)
					{
						((BaseUnityPlugin)this).Logger.LogWarning((object)("Invalid map \"" + mapPackZip.Entries[j].FullName + "\" in your maps folder has no MetaData.json, moving..."));
						MoveMapToNewFolder(mapsFolderPath, text2);
						continue;
					}
					string json2 = new StreamReader(val4.Open()).ReadToEnd();
					Dictionary<string, object> dictionary3 = Json.Deserialize(json2) as Dictionary<string, object>;
					string key = dictionary3["MapName"].ToString();
					uint num = Convert.ToUInt32(dictionary3["MapVersion"]);
					if (dictionary.ContainsKey(key))
					{
						if (dictionary[key].version != num)
						{
							val3.Dispose();
							MoveMapToNewFolder(mapsFolderPath, text2);
							ExtractMapZipFromMainZip(mapsFolderPath, mapPackZip, dictionary[key].mapFileName);
						}
						dictionary[key].zip.Dispose();
						dictionary.Remove(key);
					}
					else
					{
						val3.Dispose();
						MoveMapToNewFolder(mapsFolderPath, text2);
					}
				}
				finally
				{
					((IDisposable)val3)?.Dispose();
				}
			}
			foreach (ZippedMap value in dictionary.Values)
			{
				ExtractMapZipFromMainZip(mapsFolderPath, mapPackZip, value.mapFileName);
				value.zip.Dispose();
			}
		}

		public void ExtractMapZipFromMainZip(string mapsFolderPath, ZipArchive mapPackZip, string mapFileName)
		{
			string destinationFileName = Path.Combine(mapsFolderPath, mapFileName);
			mapPackZip.GetEntry(mapFileName).ExtractToFile(destinationFileName);
		}

		public void MoveMapToNewFolder(string mapsFolder, string mapPath)
		{
			string text = Path.Combine(Directory.GetParent(mapsFolder).FullName, "maps moved when setting up map pack " + startTimeString);
			if (!Directory.Exists(text))
			{
				Directory.CreateDirectory(text);
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)Path.Combine(text + "/" + Path.GetFileName(mapPath)));
			File.Move(mapPath, Path.Combine(text + "/" + Path.GetFileName(mapPath)));
		}
	}
	public struct ZippedMap
	{
		public string mapName;

		public string mapFileName;

		public uint version;

		public ZipArchive zip;

		public ZippedMap(string mapName, uint version, ZipArchive zip, string mapFileName)
		{
			this.mapName = mapName;
			this.version = version;
			this.zip = zip;
			this.mapFileName = mapFileName;
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "MapPackLoader";

		public const string PLUGIN_NAME = "MapPackLoader";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace MiniJSON
{
	public static class Json
	{
		private sealed class Parser : IDisposable
		{
			private enum TOKEN
			{
				NONE,
				CURLY_OPEN,
				CURLY_CLOSE,
				SQUARED_OPEN,
				SQUARED_CLOSE,
				COLON,
				COMMA,
				STRING,
				NUMBER,
				TRUE,
				FALSE,
				NULL
			}

			private const string WORD_BREAK = "{}[],:\"";

			private StringReader json;

			private char PeekChar => Convert.ToChar(json.Peek());

			private char NextChar => Convert.ToChar(json.Read());

			private string NextWord
			{
				get
				{
					StringBuilder stringBuilder = new StringBuilder();
					while (!IsWordBreak(PeekChar))
					{
						stringBuilder.Append(NextChar);
						if (json.Peek() == -1)
						{
							break;
						}
					}
					return stringBuilder.ToString();
				}
			}

			private TOKEN NextToken
			{
				get
				{
					EatWhitespace();
					if (json.Peek() == -1)
					{
						return TOKEN.NONE;
					}
					switch (PeekChar)
					{
					case '{':
						return TOKEN.CURLY_OPEN;
					case '}':
						json.Read();
						return TOKEN.CURLY_CLOSE;
					case '[':
						return TOKEN.SQUARED_OPEN;
					case ']':
						json.Read();
						return TOKEN.SQUARED_CLOSE;
					case ',':
						json.Read();
						return TOKEN.COMMA;
					case '"':
						return TOKEN.STRING;
					case ':':
						return TOKEN.COLON;
					case '-':
					case '0':
					case '1':
					case '2':
					case '3':
					case '4':
					case '5':
					case '6':
					case '7':
					case '8':
					case '9':
						return TOKEN.NUMBER;
					default:
						return NextWord switch
						{
							"false" => TOKEN.FALSE, 
							"true" => TOKEN.TRUE, 
							"null" => TOKEN.NULL, 
							_ => TOKEN.NONE, 
						};
					}
				}
			}

			public static bool IsWordBreak(char c)
			{
				return char.IsWhiteSpace(c) || "{}[],:\"".IndexOf(c) != -1;
			}

			private Parser(string jsonString)
			{
				json = new StringReader(jsonString);
			}

			public static object Parse(string jsonString)
			{
				using Parser parser = new Parser(jsonString);
				return parser.ParseValue();
			}

			public void Dispose()
			{
				json.Dispose();
				json = null;
			}

			private Dictionary<string, object> ParseObject()
			{
				Dictionary<string, object> dictionary = new Dictionary<string, object>();
				json.Read();
				while (true)
				{
					switch (NextToken)
					{
					case TOKEN.NONE:
						return null;
					case TOKEN.CURLY_CLOSE:
						return dictionary;
					case TOKEN.COMMA:
						continue;
					}
					string text = ParseString();
					if (text == null)
					{
						return null;
					}
					if (NextToken != TOKEN.COLON)
					{
						return null;
					}
					json.Read();
					dictionary[text] = ParseValue();
				}
			}

			private List<object> ParseArray()
			{
				List<object> list = new List<object>();
				json.Read();
				bool flag = true;
				while (flag)
				{
					TOKEN nextToken = NextToken;
					switch (nextToken)
					{
					case TOKEN.NONE:
						return null;
					case TOKEN.SQUARED_CLOSE:
						flag = false;
						break;
					default:
					{
						object item = ParseByToken(nextToken);
						list.Add(item);
						break;
					}
					case TOKEN.COMMA:
						break;
					}
				}
				return list;
			}

			private object ParseValue()
			{
				TOKEN nextToken = NextToken;
				return ParseByToken(nextToken);
			}

			private object ParseByToken(TOKEN token)
			{
				return token switch
				{
					TOKEN.STRING => ParseString(), 
					TOKEN.NUMBER => ParseNumber(), 
					TOKEN.CURLY_OPEN => ParseObject(), 
					TOKEN.SQUARED_OPEN => ParseArray(), 
					TOKEN.TRUE => true, 
					TOKEN.FALSE => false, 
					TOKEN.NULL => null, 
					_ => null, 
				};
			}

			private string ParseString()
			{
				StringBuilder stringBuilder = new StringBuilder();
				json.Read();
				bool flag = true;
				while (flag)
				{
					if (json.Peek() == -1)
					{
						flag = false;
						break;
					}
					char nextChar = NextChar;
					switch (nextChar)
					{
					case '"':
						flag = false;
						break;
					case '\\':
						if (json.Peek() == -1)
						{
							flag = false;
							break;
						}
						nextChar = NextChar;
						switch (nextChar)
						{
						case '"':
						case '/':
						case '\\':
							stringBuilder.Append(nextChar);
							break;
						case 'b':
							stringBuilder.Append('\b');
							break;
						case 'f':
							stringBuilder.Append('\f');
							break;
						case 'n':
							stringBuilder.Append('\n');
							break;
						case 'r':
							stringBuilder.Append('\r');
							break;
						case 't':
							stringBuilder.Append('\t');
							break;
						case 'u':
						{
							char[] array = new char[4];
							for (int i = 0; i < 4; i++)
							{
								array[i] = NextChar;
							}
							stringBuilder.Append((char)Convert.ToInt32(new string(array), 16));
							break;
						}
						}
						break;
					default:
						stringBuilder.Append(nextChar);
						break;
					}
				}
				return stringBuilder.ToString();
			}

			private object ParseNumber()
			{
				string nextWord = NextWord;
				if (nextWord.IndexOf('.') == -1)
				{
					long.TryParse(nextWord, out var result);
					return result;
				}
				double.TryParse(nextWord, out var result2);
				return result2;
			}

			private void EatWhitespace()
			{
				while (char.IsWhiteSpace(PeekChar))
				{
					json.Read();
					if (json.Peek() == -1)
					{
						break;
					}
				}
			}
		}

		private sealed class Serializer
		{
			private StringBuilder builder;

			private Serializer()
			{
				builder = new StringBuilder();
			}

			public static string Serialize(object obj)
			{
				Serializer serializer = new Serializer();
				serializer.SerializeValue(obj);
				return serializer.builder.ToString();
			}

			private void SerializeValue(object value)
			{
				if (value == null)
				{
					builder.Append("null");
				}
				else if (value is string str)
				{
					SerializeString(str);
				}
				else if (value is bool)
				{
					builder.Append(((bool)value) ? "true" : "false");
				}
				else if (value is IList anArray)
				{
					SerializeArray(anArray);
				}
				else if (value is IDictionary obj)
				{
					SerializeObject(obj);
				}
				else if (value is char)
				{
					SerializeString(new string((char)value, 1));
				}
				else
				{
					SerializeOther(value);
				}
			}

			private void SerializeObject(IDictionary obj)
			{
				bool flag = true;
				builder.Append('{');
				foreach (object key in obj.Keys)
				{
					if (!flag)
					{
						builder.Append(',');
					}
					SerializeString(key.ToString());
					builder.Append(':');
					SerializeValue(obj[key]);
					flag = false;
				}
				builder.Append('}');
			}

			private void SerializeArray(IList anArray)
			{
				builder.Append('[');
				bool flag = true;
				foreach (object item in anArray)
				{
					if (!flag)
					{
						builder.Append(',');
					}
					SerializeValue(item);
					flag = false;
				}
				builder.Append(']');
			}

			private void SerializeString(string str)
			{
				builder.Append('"');
				char[] array = str.ToCharArray();
				char[] array2 = array;
				foreach (char c in array2)
				{
					switch (c)
					{
					case '"':
						builder.Append("\\\"");
						continue;
					case '\\':
						builder.Append("\\\\");
						continue;
					case '\b':
						builder.Append("\\b");
						continue;
					case '\f':
						builder.Append("\\f");
						continue;
					case '\n':
						builder.Append("\\n");
						continue;
					case '\r':
						builder.Append("\\r");
						continue;
					case '\t':
						builder.Append("\\t");
						continue;
					}
					int num = Convert.ToInt32(c);
					if (num >= 32 && num <= 126)
					{
						builder.Append(c);
						continue;
					}
					builder.Append("\\u");
					builder.Append(num.ToString("x4"));
				}
				builder.Append('"');
			}

			private void SerializeOther(object value)
			{
				if (value is float)
				{
					builder.Append(((float)value).ToString("R"));
				}
				else if (value is int || value is uint || value is long || value is sbyte || value is byte || value is short || value is ushort || value is ulong)
				{
					builder.Append(value);
				}
				else if (value is double || value is decimal)
				{
					builder.Append(Convert.ToDouble(value).ToString("R"));
				}
				else
				{
					SerializeString(value.ToString());
				}
			}
		}

		public static object Deserialize(string json)
		{
			if (json == null)
			{
				return null;
			}
			return Parser.Parse(json);
		}

		public static string Serialize(object obj)
		{
			return Serializer.Serialize(obj);
		}
	}
}