Decompiled source of Hat Loader v1.0.0

HatLoader.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Alexandria.ItemAPI;
using Alexandria.cAPI;
using BepInEx;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("HatLoader")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("N/A")]
[assembly: AssemblyProduct("HatLoader")]
[assembly: AssemblyCopyright("Copyright © N/A 2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("13bd8a8a-8724-4ced-af43-687ebc23ca8f")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[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 HatLoader
{
	[BepInPlugin("spapi.etg.hatloader", "Hat Loader", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string GUID = "spapi.etg.hatloader";

		public const string NAME = "Hat Loader";

		public const string VERSION = "1.0.0";

		public static tk2dSpriteCollectionData HatLoaderCollection;

		public void Awake()
		{
			ETGModMainBehaviour.WaitForGameManagerStart((Action<GameManager>)GMStart);
		}

		public void GMStart(GameManager gm)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_03f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0405: Unknown result type (might be due to invalid IL or missing references)
			//IL_042e: Expected O, but got Unknown
			//IL_0567: Unknown result type (might be due to invalid IL or missing references)
			HatLoaderCollection = SpriteBuilder.ConstructCollection(new GameObject(), "HatLoaderHatCollection", false);
			string[] files = Directory.GetFiles(Paths.PluginPath, "*-hat.spapi", SearchOption.AllDirectories);
			foreach (string path in files)
			{
				string[] lines = File.ReadAllLines(path);
				string file = Path.GetFileName(path);
				string directoryName = Path.GetDirectoryName(path);
				string name = "";
				int xOffs = 0;
				int yOffs = 0;
				int fps = 4;
				bool attachedToHead = true;
				bool inFrontWhenFacingBack = true;
				bool inFrontWhenFacingFront = true;
				bool flipOnRoll = true;
				bool vanishOnRoll = false;
				string flipStartSound = "";
				string flipEndSound = "";
				float flipSpeed = 1f;
				float flipHeight = 1f;
				bool? flipHorizontalWithPlayer = null;
				Dictionary<string, List<string>> hatSpritePaths = new Dictionary<string, List<string>>();
				List<tk2dSpriteDefinition> list = new List<tk2dSpriteDefinition>();
				SpapiDataReader.HandleLines(lines, new Dictionary<string, Func<List<string>, bool>>
				{
					{
						"name",
						delegate(List<string> x)
						{
							name = x.LastOrDefault();
							return true;
						}
					},
					{
						"northsprites",
						delegate(List<string> x)
						{
							hatSpritePaths["north"] = x;
							return true;
						}
					},
					{
						"southsprites",
						delegate(List<string> x)
						{
							hatSpritePaths["south"] = x;
							return true;
						}
					},
					{
						"westsprites",
						delegate(List<string> x)
						{
							hatSpritePaths["west"] = x;
							return true;
						}
					},
					{
						"eastsprites",
						delegate(List<string> x)
						{
							hatSpritePaths["east"] = x;
							return true;
						}
					},
					{
						"northwestsprites",
						delegate(List<string> x)
						{
							hatSpritePaths["northwest"] = x;
							return true;
						}
					},
					{
						"northeastsprites",
						delegate(List<string> x)
						{
							hatSpritePaths["northeast"] = x;
							return true;
						}
					},
					{
						"xoffset",
						delegate(List<string> x)
						{
							if (int.TryParse(x.LastOrDefault(), out xOffs))
							{
								return true;
							}
							Debug.LogError((object)("Error reading hat file " + file + ": XOffset should be an integer."));
							return false;
						}
					},
					{
						"yoffset",
						delegate(List<string> x)
						{
							if (int.TryParse(x.LastOrDefault(), out yOffs))
							{
								return true;
							}
							Debug.LogError((object)("Error reading hat file " + file + ": YOffset should be an integer."));
							return false;
						}
					},
					{
						"fps",
						delegate(List<string> x)
						{
							if (int.TryParse(x.LastOrDefault(), out fps))
							{
								return true;
							}
							Debug.LogError((object)("Error reading hat file " + file + ": FPS should be an integer."));
							return false;
						}
					},
					{
						"attachedtohead",
						delegate(List<string> x)
						{
							if (bool.TryParse(x.LastOrDefault(), out attachedToHead))
							{
								return true;
							}
							Debug.LogError((object)("Error reading hat file " + file + ": AttachedToHead should be True or False."));
							return false;
						}
					},
					{
						"infrontwhenfacingback",
						delegate(List<string> x)
						{
							if (bool.TryParse(x.LastOrDefault(), out inFrontWhenFacingBack))
							{
								return true;
							}
							Debug.LogError((object)("Error reading hat file " + file + ": InFrontWhenFacingBack should be True or False."));
							return false;
						}
					},
					{
						"infrontwhenfacingfront",
						delegate(List<string> x)
						{
							if (bool.TryParse(x.LastOrDefault(), out inFrontWhenFacingFront))
							{
								return true;
							}
							Debug.LogError((object)("Error reading hat file " + file + ": InFrontWhenFacingFront should be True or False."));
							return false;
						}
					},
					{
						"fliponroll",
						delegate(List<string> x)
						{
							if (bool.TryParse(x.LastOrDefault(), out flipOnRoll))
							{
								return true;
							}
							Debug.LogError((object)("Error reading hat file " + file + ": FlipOnRoll should be True or False."));
							return false;
						}
					},
					{
						"vanishonroll",
						delegate(List<string> x)
						{
							if (bool.TryParse(x.LastOrDefault(), out vanishOnRoll))
							{
								return true;
							}
							Debug.LogError((object)("Error reading hat file " + file + ": VanishOnRoll should be True or False."));
							return false;
						}
					},
					{
						"flipstartsound",
						delegate(List<string> x)
						{
							flipStartSound = x.LastOrDefault();
							return true;
						}
					},
					{
						"flipendsound",
						delegate(List<string> x)
						{
							flipEndSound = x.LastOrDefault();
							return true;
						}
					},
					{
						"flipspeed",
						delegate(List<string> x)
						{
							if (float.TryParse(x.LastOrDefault(), out flipSpeed))
							{
								return true;
							}
							Debug.LogError((object)("Error reading hat file " + file + ": FlipSpeed should be a number."));
							return false;
						}
					},
					{
						"flipheight",
						delegate(List<string> x)
						{
							if (float.TryParse(x.LastOrDefault(), out flipHeight))
							{
								return true;
							}
							Debug.LogError((object)("Error reading hat file " + file + ": FlipHeight should be a number."));
							return false;
						}
					},
					{
						"fliphorizontalwithplayer",
						delegate(List<string> x)
						{
							bool result;
							bool flag = bool.TryParse(x.LastOrDefault(), out result);
							flipHorizontalWithPlayer = result;
							if (flag)
							{
								return true;
							}
							Debug.LogError((object)("Error reading hat file " + file + ": FlipHorizontalWithPlayer should be True or False."));
							return false;
						}
					}
				}, delegate(string x)
				{
					Debug.LogError((object)("Error reading hat file " + file + ": " + x));
				});
				if (string.IsNullOrEmpty(name))
				{
					Debug.LogError((object)("Error loading hat " + file + ": hat name not given."));
					continue;
				}
				foreach (KeyValuePair<string, List<string>> item2 in hatSpritePaths)
				{
					string key = item2.Key;
					List<string> value = item2.Value;
					for (int j = 0; j < value.Count; j++)
					{
						string text = value[j].Replace('\\', Path.DirectorySeparatorChar).Replace('/', Path.DirectorySeparatorChar);
						if (!text.EndsWith(".png"))
						{
							text += ".png";
						}
						string path2 = Path.Combine(directoryName, text);
						if (!File.Exists(path2))
						{
							Debug.LogError((object)("Error loading sprites for hat " + file + ": file " + value[j] + " doesn't exist."));
							continue;
						}
						byte[] array = File.ReadAllBytes(path2);
						Texture2D val = new Texture2D(1, 1, (TextureFormat)4, false)
						{
							filterMode = (FilterMode)0,
							name = $"{ETGMod.ToID(name)}_{key}_{j + 1:D3}"
						};
						try
						{
							if (!ImageConversion.LoadImage(val, array))
							{
								Debug.LogError((object)("Error loading sprites for hat " + file + ": file " + text + " is not a valid texture."));
								continue;
							}
						}
						catch
						{
							Debug.LogError((object)("Error loading sprites for hat " + file + ": file " + text + " is not a valid texture."));
							continue;
						}
						int num = SpriteBuilder.AddSpriteToCollection(val, HatLoaderCollection, "");
						tk2dSpriteDefinition item = HatLoaderCollection.spriteDefinitions[num];
						list.Add(item);
					}
				}
				if (list.Count <= 0)
				{
					Debug.LogError((object)("Error loading hat " + file + ": hat doesn't have any sprites."));
					continue;
				}
				try
				{
					Hat val2 = HatUtility.SetupHat(name, (List<string>)null, (IntVector2?)new IntVector2(xOffs, yOffs), fps, (HatAttachLevel)((!attachedToHead) ? 1 : 0), (HatDepthType)((!inFrontWhenFacingBack) ? ((!inFrontWhenFacingFront) ? 1 : 2) : ((!inFrontWhenFacingFront) ? 3 : 0)), (HatRollReaction)(vanishOnRoll ? 1 : ((!flipOnRoll) ? 2 : 0)), string.IsNullOrEmpty(flipStartSound) ? null : flipStartSound, string.IsNullOrEmpty(flipEndSound) ? null : flipEndSound, flipSpeed, flipHeight, flipHorizontalWithPlayer, false, (List<GungeonFlags>)null, (List<DungeonPrerequisite>)null, (string)null, false);
					HatUtility.SetupHatSprites(val2, (List<string>)null, list, fps, (Assembly)null);
				}
				catch (Exception ex)
				{
					Debug.LogError((object)("Error loading hat " + file + ": " + ex.Message));
				}
			}
		}
	}
	public static class SpapiDataReader
	{
		public static bool HandleLines(string[] lines, Dictionary<string, Func<List<string>, bool>> propertyHandler, Action<string> errorHandler)
		{
			for (int i = 0; i < lines.Length; i++)
			{
				string text = lines[i];
				if (Utility.IsNullOrWhiteSpace(text))
				{
					continue;
				}
				string text2 = text.Trim();
				if (text2.StartsWith("#") && text2.Length > 1)
				{
					string text3 = text2.Substring(1).Trim().ToLowerInvariant();
					if (!Utility.IsNullOrWhiteSpace(text3))
					{
						List<string> property;
						bool flag = TryReadDataProperty(lines, ref i, out property);
						if (!propertyHandler.TryGetValue(text3.ToLowerInvariant(), out var value))
						{
							errorHandler?.Invoke("unknown property " + text3 + ".");
							return false;
						}
						if (flag && value != null && !value(property))
						{
							return false;
						}
					}
					continue;
				}
				errorHandler?.Invoke($"unexpected data at line {i + 1}.");
				return false;
			}
			return true;
		}

		private static bool TryReadDataProperty(string[] lines, ref int index, out List<string> property)
		{
			property = new List<string>();
			index++;
			while (index < lines.Length)
			{
				string text = lines[index];
				if (!Utility.IsNullOrWhiteSpace(text))
				{
					string text2 = text.Trim();
					if (text2.StartsWith("#") && text2.Length > 1)
					{
						index--;
						break;
					}
					property.Add(text2);
				}
				index++;
			}
			return property.Count > 0;
		}
	}
}