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();
}
}
}
}