Decompiled source of SpookyUnits v1.0.0

plugins/SpookyUnits.Plugin.dll

Decompiled 2 days 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.Versioning;
using BepInEx;
using BepInEx.Logging;
using Conductor.Data.Registers;
using Conductor.Interfaces;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using RotaryHeart.Lib.SerializableDictionary;
using ShinyShoe;
using TrainworksReloaded.Base;
using TrainworksReloaded.Base.Prefab;
using TrainworksReloaded.Core;
using TrainworksReloaded.Core.Extensions;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("SpookyUnits.Plugin")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+8e753a7d6beb23c8045ae6a31d59cbe1887cfbc3")]
[assembly: AssemblyProduct("SpookyUnits.Plugin")]
[assembly: AssemblyTitle("SpookyUnits.Plugin")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[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 SpookyUnits.Plugin
{
	[BepInPlugin("SpookyUnits.Plugin", "SpookyUnits.Plugin", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		public struct PumpkinInfo
		{
			public int tickets;

			public List<string> pumpkins;
		}

		[Serializable]
		public class PumpkinUsageInfo
		{
			[JsonProperty("id")]
			public string Id { get; set; } = "";

			[JsonProperty("seen")]
			public int Seen { get; set; }

			[JsonProperty("first_seen")]
			public string FirstSeen { get; set; } = "";
		}

		[Serializable]
		public class PumpkinSaveMetaData
		{
			[JsonProperty("data")]
			public SerializableDictionaryBase<string, PumpkinUsageInfo> Data { get; set; } = new SerializableDictionaryBase<string, PumpkinUsageInfo>();
		}

		public class PumpkinActiveRunSaveData : ISaveData
		{
			[Serializable]
			public struct DTO
			{
				[JsonProperty("data")]
				public List<string> Data { get; set; }
			}

			public HashSet<string> charactersSeen = new HashSet<string>();

			public string Key => GetType().FullName;

			public void Deserialize(string data)
			{
				DTO dTO = JsonConvert.DeserializeObject<DTO>(data);
				HashSet<string> hashSet = new HashSet<string>();
				foreach (string datum in dTO.Data)
				{
					hashSet.Add(datum);
				}
				charactersSeen = hashSet;
			}

			public void Reset()
			{
				charactersSeen.Clear();
			}

			public string Serialize()
			{
				return JsonConvert.SerializeObject((object)new DTO
				{
					Data = charactersSeen.ToList()
				}, (Formatting)1);
			}

			public bool ShouldSerialize()
			{
				return true;
			}

			public bool HasCharacterBeenSeenThisRun(string id)
			{
				return charactersSeen.Contains(id);
			}

			public void MarkCharacterAsSeen(string id)
			{
				charactersSeen.Add(id);
			}
		}

		internal static ManualLogSource Logger = new ManualLogSource("SpookyUnits.Plugin");

		public static GameObject? hiddenRoot;

		public static Dictionary<string, GameObject> gameObjects = new Dictionary<string, GameObject>();

		public static int Seed;

		public static Dictionary<CollectableRarity, PumpkinInfo> pumpkinInfo = new Dictionary<CollectableRarity, PumpkinInfo>
		{
			{
				(CollectableRarity)0,
				new PumpkinInfo
				{
					tickets = 32768,
					pumpkins = new List<string>(28)
					{
						"Pumpkin1", "Pumpkin5", "Pumpkin6", "Pumpkin8", "Pumpkin9", "Pumpkin10", "Pumpkin11", "Pumpkin12", "Pumpkin17", "Pumpkin18",
						"Pumpkin19", "Pumpkin20", "Pumpkin21", "Pumpkin22", "Pumpkin23", "Pumpkin24", "Pumpkin25", "Pumpkin35", "Pumpkin36", "Pumpkin37",
						"Pumpkin38", "Pumpkin39", "Pumpkin40", "Pumpkin41", "Pumpkin42", "Pumpkin43", "Pumpkin51", "Pumpkin52"
					}
				}
			},
			{
				(CollectableRarity)1,
				new PumpkinInfo
				{
					tickets = 19660,
					pumpkins = new List<string>(21)
					{
						"Pumpkin7", "Pumpkin2", "Pumpkin3", "Pumpkin4", "Pumpkin44", "Pumpkin45", "Pumpkin46", "Pumpkin47", "Pumpkin48", "Pumpkin49",
						"Pumpkin50", "Pumpkin53", "Pumpkin55", "Pumpkin56", "Pumpkin57", "Pumpkin58", "Pumpkin60", "Pumpkin61", "Pumpkin64", "Pumpkin68",
						"Pumpkin70"
					}
				}
			},
			{
				(CollectableRarity)2,
				new PumpkinInfo
				{
					tickets = 9830,
					pumpkins = new List<string>(14)
					{
						"Pumpkin13", "Pumpkin14", "Pumpkin15", "Pumpkin16", "Pumpkin26", "Pumpkin27", "Pumpkin28", "Pumpkin54", "Pumpkin59", "Pumpkin62",
						"Pumpkin63", "Pumpkin66", "Pumpkin67", "Pumpkin69"
					}
				}
			},
			{
				(CollectableRarity)3,
				new PumpkinInfo
				{
					tickets = 3278,
					pumpkins = new List<string>(7) { "Pumpkin29", "Pumpkin30", "Pumpkin31", "Pumpkin32", "Pumpkin33", "Pumpkin34", "Pumpkin65" }
				}
			}
		};

		public static PumpkinSaveMetaData SaveMetaData = new PumpkinSaveMetaData();

		public static PumpkinActiveRunSaveData SaveRunData = new PumpkinActiveRunSaveData();

		public static string SaveFilePath = string.Empty;

		public static string ModConfigDir = string.Empty;

		public void Awake()
		{
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			Logger = ((BaseUnityPlugin)this).Logger;
			ModConfigDir = Path.Combine(Paths.ConfigPath, "SpookyUnits.Plugin");
			SaveFilePath = Path.Combine(ModConfigDir, "pumpkinSave.json");
			ReadSaveData();
			SaveDataRegistry.Register("SpookyUnits.Plugin", (ISaveData)(object)SaveRunData);
			Railhead.GetBuilder().Configure("SpookyUnits.Plugin", (Action<IConfigurationBuilder>)delegate(IConfigurationBuilder c)
			{
				ConfigurationExtensions.AddMergedJsonFile(c, new List<string>(1) { "json/plugin.json" });
			});
			Roundhouse.WhenReady("SpookyUnits.Plugin", (Action<GameDataManager>)delegate(GameDataManager ctx)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				//IL_0015: Expected O, but got Unknown
				//IL_0076: 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)
				//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
				hiddenRoot = new GameObject
				{
					name = "PumpkinPrefabs"
				};
				Object.DontDestroyOnLoad((Object)(object)hiddenRoot);
				hiddenRoot.AddComponent<TransformOnStart>();
				hiddenRoot.SetActive(false);
				Seed = Convert.ToInt32((DateTime.Now - DateTime.UnixEpoch).TotalSeconds);
				foreach (KeyValuePair<CollectableRarity, PumpkinInfo> item in pumpkinInfo)
				{
					item.Deconstruct(out var key, out var value);
					CollectableRarity rarity = key;
					foreach (string pumpkin in value.pumpkins)
					{
						Sprite sprite = ctx.GetSprite(pumpkin, (string)null);
						if (!((Object)(object)sprite == (Object)null))
						{
							gameObjects[pumpkin] = CreateFaceObject(0, pumpkin, sprite, rarity);
						}
					}
				}
			});
			Logger.LogInfo((object)"Plugin SpookyUnits.Plugin is loaded!");
			new Harmony("SpookyUnits.Plugin").PatchAll();
		}

		public static void ReadSaveData()
		{
			CreateSaveDir();
			if (!File.Exists(SaveFilePath))
			{
				Logger.LogWarning((object)("No save data found at " + SaveFilePath));
				WriteSaveData();
				return;
			}
			PumpkinSaveMetaData pumpkinSaveMetaData = JsonConvert.DeserializeObject<PumpkinSaveMetaData>(File.ReadAllText(SaveFilePath));
			if (pumpkinSaveMetaData == null)
			{
				Logger.LogWarning((object)("Failed to read save data at " + SaveFilePath));
				pumpkinSaveMetaData = new PumpkinSaveMetaData();
			}
			SaveMetaData = pumpkinSaveMetaData;
		}

		public static void CreateSaveDir()
		{
			if (!Directory.Exists(ModConfigDir))
			{
				Directory.CreateDirectory(ModConfigDir);
			}
		}

		public static void WriteSaveData()
		{
			CreateSaveDir();
			string contents = JsonConvert.SerializeObject((object)SaveMetaData, (Formatting)1);
			Logger.LogDebug((object)("Writing to " + SaveFilePath));
			File.WriteAllText(SaveFilePath, contents);
		}

		public static void LogPumpkin(string pumpkin, CharacterState character)
		{
			string iD = ((GameData)character.GetSourceCharacterData()).GetID();
			if (iD != null && !SaveRunData.HasCharacterBeenSeenThisRun(iD))
			{
				SaveRunData.MarkCharacterAsSeen(iD);
				if (!SaveMetaData.Data.ContainsKey(pumpkin))
				{
					SaveMetaData.Data[pumpkin] = new PumpkinUsageInfo
					{
						Id = pumpkin,
						Seen = 1,
						FirstSeen = ((GameData)character.GetSourceCharacterData()).GetID()
					};
				}
				else
				{
					SaveMetaData.Data[pumpkin].Seen++;
				}
			}
		}

		private static GameObject CreateFaceObject(int sortingLayerID, string name, Sprite sprite, CollectableRarity rarity)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Face");
			val.transform.parent = hiddenRoot.transform;
			GameObject val2 = new GameObject(name);
			val2.transform.SetParent(val.transform);
			CharacterOverlayImage characterOverlayImage = val.AddComponent<CharacterOverlayImage>();
			SpriteRenderer val3 = val2.AddComponent<SpriteRenderer>();
			Transform transform = ((Component)val3).transform;
			transform.localPosition += new Vector3(0f, 0f, -0.1f);
			((Component)val3).transform.localScale = new Vector3(0.456f, 0.456f);
			val3.sprite = sprite;
			((Renderer)val3).sortingLayerID = sortingLayerID;
			((Renderer)val3).sortingOrder = 1;
			characterOverlayImage.SetSpriteRenderer(val3);
			return val;
		}

		public static GameObject? GetOverlayImage(uint seed, uint hash)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Invalid comparison between Unknown and I4
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			if (gameObjects.Count == 0)
			{
				return null;
			}
			uint num = seed * hash;
			long num2 = seed;
			long num3 = num2 ^ (num2 >>> 12);
			long num4 = num3 ^ ((num3 << 25) & -1);
			seed = (uint)((num4 ^ (num4 >>> 27)) * 620316625);
			int num5 = (int)(num & 0xFFFF);
			CollectableRarity val = (CollectableRarity)(-1);
			int num6 = 0;
			foreach (KeyValuePair<CollectableRarity, PumpkinInfo> item in Plugin.pumpkinInfo)
			{
				item.Deconstruct(out var key, out var value);
				CollectableRarity val2 = key;
				PumpkinInfo pumpkinInfo = value;
				num6 += pumpkinInfo.tickets;
				if (num5 < num6)
				{
					val = val2;
					break;
				}
			}
			if ((int)val == -1)
			{
				return null;
			}
			PumpkinInfo pumpkinInfo2 = Plugin.pumpkinInfo[val];
			int index = (int)(seed * hash % pumpkinInfo2.pumpkins.Count);
			string key2 = pumpkinInfo2.pumpkins[index];
			return Object.Instantiate<GameObject>(gameObjects[key2]);
		}
	}
	public class CharacterOverlayImage : MonoBehaviour
	{
		private SpriteRenderer? spriteBase;

		private int baseInitialSortingOrder;

		public void SetSpriteRenderer(SpriteRenderer spriteRenderer)
		{
			spriteBase = spriteRenderer;
			baseInitialSortingOrder = ((Renderer)spriteBase).sortingOrder;
		}

		public void SetSortingOrder(int sortingLayer, int sortingOrderOffset)
		{
			((Renderer)spriteBase).sortingLayerID = sortingLayer;
			((Renderer)spriteBase).sortingOrder = baseInitialSortingOrder + sortingOrderOffset;
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "SpookyUnits.Plugin";

		public const string PLUGIN_NAME = "SpookyUnits.Plugin";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace SpookyUnits.Plugin.patches
{
	[HarmonyPatch(typeof(CharacterUIMeshSpine), "Setup")]
	public static class Mod_CharacterUI_Setup
	{
		private static readonly List<string> CharactersThatDontDisplayWell = new List<string>(12)
		{
			"Character_HornbreakerPrince_ClassSelect", "Character_ShardtailQueen_ClassSelect", "Character_TheSentient_ClassSelect", "Character_RootsOfWyldenten_ClassSelect", "Character_AcksoLotal_ClassSelect", "Character_SolgardTheMartyr_ClassSelect", "Character_Penumbra_ClassSelect", "Character_ShadowPrimordium_ClassSelect", "Character_RfrFlicker_ClassSelect", "Character_LilFade_ClassSelect",
			"Character_SpineChief_ClassSelect", "Character_Echowright_ClassSelect"
		};

		private static readonly MethodInfo CreateBoneFollower_Function = AccessTools.Method(typeof(CharacterUIMeshSpine), "CreateBoneFollower", (Type[])null, (Type[])null);

		private static void Postfix(CharacterUIMeshSpine __instance, string debugName, float facingDir)
		{
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			if (((Object)__instance).name == "RedCrown")
			{
				return;
			}
			int num = debugName.IndexOf(" [");
			string text = debugName[..((num == -1) ? debugName.Length : num)];
			ScreenManager screenManager = AllGameManagers.Instance.GetScreenManager();
			bool flag = false;
			if (screenManager.GetScreenActive((ScreenName)42) || screenManager.GetScreenActive((ScreenName)56))
			{
				return;
			}
			int num2 = AllGameManagers.Instance.GetSaveManager().GetStartingConditions().Seed;
			if (screenManager.GetScreenActive((ScreenName)25))
			{
				num2 = ((num2 == 0) ? Plugin.Seed : num2);
				facingDir = -1f;
				flag = true;
			}
			else if (screenManager.GetScreenActive((ScreenName)24))
			{
				facingDir = -1f;
			}
			int murmurHash = RandomManager.GetMurmurHash(text);
			GameObject overlayImage = Plugin.GetOverlayImage((uint)num2, (uint)murmurHash);
			if (!((Object)(object)overlayImage == (Object)null))
			{
				SpriteRenderer componentInChildren = overlayImage.GetComponentInChildren<SpriteRenderer>();
				((Renderer)componentInChildren).sortingLayerID = SortingLayersExtensions.LayerID(((CharacterUIMeshBase)__instance).GetSortingLayer());
				if (!flag)
				{
					CharacterState component = ((Component)((Component)__instance).transform.parent.parent.parent).GetComponent<CharacterState>();
					Plugin.LogPumpkin(((Object)componentInChildren).name, component);
				}
				AttachToBone(__instance, text, overlayImage.transform, (Location)6);
				Transform child = overlayImage.transform.GetChild(0);
				Vector3 localScale = child.localScale;
				child.localScale = new Vector3(facingDir * localScale.x, localScale.y, localScale.z);
			}
		}

		public static void AttachToBone(CharacterUIMeshSpine mesh, string name, Transform transform, Location location)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if (!CharactersThatDontDisplayWell.Contains(name))
			{
				mesh.AttachToBone(transform, location);
			}
		}
	}
	[HarmonyPatch(typeof(SaveManager), "Save")]
	public class SaveManager_Save_Patch
	{
		public static void Prefix(SaveManager __instance, bool writeToFile, bool saveReplayOnly)
		{
			if (!(__instance.PreviewMode || saveReplayOnly) && !__instance.IsInUndoMode && writeToFile)
			{
				Plugin.WriteSaveData();
			}
		}
	}
}