Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Cookie v1.1.0
BepInEx/plugins/CustomPaintings.dll
Decompiled a year agousing 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 System.Threading.Tasks; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using UnityEngine; using UnityEngine.SceneManagement; [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("CustomPaintings")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+a794a6ea736b49b31c473c4544f0f50bbf25360d")] [assembly: AssemblyProduct("CustomPaintings")] [assembly: AssemblyTitle("CustomPaintings")] [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 CustomPaintings { [BepInPlugin("UnderratedJunk.CustomPaintings", "CustomPaintings", "1.1.6")] public class CustomPaintings : BaseUnityPlugin { [HarmonyPatch(typeof(LoadingUI), "LevelAnimationComplete")] public class PaintingSwapPatch { private static void Postfix() { Task.Run(async delegate { int waited = 0; int interval = 50; while (!receivedSeed.HasValue && waited < maxWaitTimeMs) { await Task.Delay(interval); waited += interval; } if (receivedSeed.HasValue) { logger.LogInfo($"[Postfix] Client using received seed: {receivedSeed.Value}"); oldreceivedSeed = CustomPaintingsSwap.ReceivedSeed; CustomPaintingsSwap.ReceivedSeed = receivedSeed.Value; receivedSeed = null; } else if (CustomPaintingsSwap.ReceivedSeed == oldreceivedSeed) { logger.LogWarning("[Postfix] Client did not receive seed in time. Proceeding without it."); } swapper.ReplacePaintings(); }); } private static void Prefix() { if (swapper.GetModState() == CustomPaintingsSwap.ModState.Client) { PhotonNetwork.AddCallbackTarget((object)sync); } if (swapper.GetModState() == CustomPaintingsSwap.ModState.Host) { CustomPaintingsSwap.HostSeed = Random.Range(0, int.MaxValue); logger.LogInfo($"Generated Hostseed: {CustomPaintingsSwap.HostSeed}"); PhotonNetwork.AddCallbackTarget((object)sync); sync.SendSeed(CustomPaintingsSwap.HostSeed); if (CustomPaintingsConfig.SeperateImages.Value) { sync.SendHostSettings("on", CustomPaintingsConfig.RugsAndBanners.Value, CustomPaintingsConfig.ChaosMode.Value); } else if (!CustomPaintingsConfig.SeperateImages.Value) { sync.SendHostSettings("off", CustomPaintingsConfig.RugsAndBanners.Value, CustomPaintingsConfig.ChaosMode.Value); } } loader.UpdateGrungeMaterialParameters(); } } [HarmonyPatch(typeof(NetworkConnect), "TryJoiningRoom")] public class JoinLobbyPatch { private static void Prefix() { if (swapper.GetModState() != 0) { swapper.SetState(CustomPaintingsSwap.ModState.Client); } } } [HarmonyPatch(typeof(SteamManager), "HostLobby")] public class HostLobbyPatch { private static bool Prefix() { swapper.SetState(CustomPaintingsSwap.ModState.Host); return true; } } [HarmonyPatch(typeof(SteamManager), "LeaveLobby")] public class LeaveLobbyPatch { private static void Postfix() { PhotonNetwork.RemoveCallbackTarget((object)sync); swapper.SetState(CustomPaintingsSwap.ModState.SinglePlayer); CustomPaintingsSwap.SeperateState = "Singleplayer"; } } private static Logger logger; private static CustomPaintingsLoader loader; private static CustomPaintingsSwap swapper; private static CustomPaintingsSync sync; private static CustomPaintingsGroupList grouper; private static CustomPaintingsConfig configfile; public static int? receivedSeed = null; public static int? oldreceivedSeed = null; public static readonly int maxWaitTimeMs = 1000; private readonly Harmony harmony = new Harmony("UnderratedJunk.CustomPaintings"); private void Awake() { logger = new Logger("CustomPaintings"); logger.LogInfo("CustomPaintings mod initialized."); CustomPaintingsConfig.Init(((BaseUnityPlugin)this).Config); loader = new CustomPaintingsLoader(logger); loader.LoadImagesFromAllPlugins(); configfile = new CustomPaintingsConfig(); grouper = new CustomPaintingsGroupList(logger); swapper = new CustomPaintingsSwap(logger, loader, grouper); sync = new CustomPaintingsSync(logger); harmony.PatchAll(); } public void Update() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (Input.GetKeyDown(configfile.ForceSwapKey)) { swapper.ReplacePaintings(); } } } public class CustomPaintingsConfig { internal static class Grunge { internal static ConfigEntry<bool> State; internal static ConfigEntry<float> Intensity; internal static ConfigEntry<Color> _BaseColor; internal static ConfigEntry<Color> _MainColor; internal static ConfigEntry<Color> _CracksColor; internal static ConfigEntry<Color> _OutlineColor; } internal static class Graphics { internal static ConfigEntry<bool> PointFiltering; } public static ConfigEntry<bool> HostControl; public static ConfigEntry<bool> SeperateImages; public static ConfigEntry<bool> RugsAndBanners; public static ConfigEntry<bool> ChaosMode; public KeyCode ForceSwapKey { get; set; } public CustomPaintingsConfig() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) ForceSwapKey = (KeyCode)Enum.Parse(typeof(KeyCode), PlayerPrefs.GetString("ForceSwapKey", "P")); } internal static void Init(ConfigFile config) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Expected O, but got Unknown //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Expected O, but got Unknown //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Expected O, but got Unknown //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Expected O, but got Unknown //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Expected O, but got Unknown //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Expected O, but got Unknown //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Expected O, but got Unknown HostControl = config.Bind<bool>("Image Settings", "Host Control", true, new ConfigDescription("choose if host controls seperate state", (AcceptableValueBase)null, Array.Empty<object>())); SeperateImages = config.Bind<bool>("Image Settings", "Seperate paintings", false, new ConfigDescription("seperate square, landscape and portrait images on swap", (AcceptableValueBase)null, Array.Empty<object>())); RugsAndBanners = config.Bind<bool>("Image Settings", "enable rugs and banners", false, new ConfigDescription("add rugs and banners to the swap pool", (AcceptableValueBase)null, Array.Empty<object>())); ChaosMode = config.Bind<bool>("Image Settings", "Chaos Mode", false, new ConfigDescription("adds a bunch of materials that shouldn't be changed to the pool", (AcceptableValueBase)null, Array.Empty<object>())); Grunge.State = config.Bind<bool>("Grunge", "Grunge state", true, new ConfigDescription("Whether the grunge effect is enabled", (AcceptableValueBase)null, Array.Empty<object>())); Grunge.Intensity = config.Bind<float>("Grunge", "Grunge intensity", 0.5f, new ConfigDescription("change how intense the grunge is applied", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 2f), Array.Empty<object>())); Grunge._BaseColor = config.Bind<Color>("Grunge", "_GrungeBaseColor", new Color(0f, 0f, 0f, 1f), new ConfigDescription("The base color of the grunge", (AcceptableValueBase)null, Array.Empty<object>())); Grunge._MainColor = config.Bind<Color>("Grunge", "_GrungeMainColor", new Color(0f, 0f, 0f, 0.5f), new ConfigDescription("The color of the main overlay of grunge", (AcceptableValueBase)null, Array.Empty<object>())); Grunge._CracksColor = config.Bind<Color>("Grunge", "_GrungeCracksColor", new Color(0.25f, 0.25f, 0.25f, 1f), new ConfigDescription("The color of the cracks in the grunge", (AcceptableValueBase)null, Array.Empty<object>())); Grunge._OutlineColor = config.Bind<Color>("Grunge", "_GrungeOutlineColor", new Color(0f, 0f, 0f, 1f), new ConfigDescription("The color of the grunge outlining the painting", (AcceptableValueBase)null, Array.Empty<object>())); Graphics.PointFiltering = config.Bind<bool>("Graphics", "PointFiltering", true, new ConfigDescription("Point filtering will match the pixelated effect the game has", (AcceptableValueBase)null, Array.Empty<object>())); } } public class CustomPaintingsGroupList { private readonly Logger logger; public static readonly Dictionary<string, List<string>> MaterialNameToGroup = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase) { { "Painting_H_Landscape", new List<string> { "Landscape", "Normal", "RugsAndBanners", "Chaos" } }, { "Painting_H_crow", new List<string> { "Landscape", "Normal", "RugsAndBanners", "Chaos" } }, { "Painting_H_crow_0", new List<string> { "Landscape", "Normal", "RugsAndBanners", "Chaos" } }, { "PaintingMedium", new List<string> { "Landscape", "Normal", "RugsAndBanners", "Chaos" } }, { "Painting_Danish_Flag", new List<string> { "Landscape", "Normal", "RugsAndBanners", "Chaos" } }, { "Painting_Board", new List<string> { "Landscape", "Normal", "RugsAndBanners", "Chaos" } }, { "Painting Danish Flag", new List<string> { "Landscape", "Normal", "RugsAndBanners", "Chaos" } }, { "Painting Board", new List<string> { "Landscape", "Normal", "RugsAndBanners", "Chaos" } }, { "Shop Outside Billboard Ad", new List<string> { "Landscape", "Normal", "RugsAndBanners", "Chaos" } }, { "Painting_S_Creep", new List<string> { "Square", "Normal", "RugsAndBanners", "Chaos" } }, { "Painting_S_Creep 2_0", new List<string> { "Square", "Normal", "RugsAndBanners", "Chaos" } }, { "Painting_S_Creep 2", new List<string> { "Square", "Normal", "RugsAndBanners", "Chaos" } }, { "Painting Wizard Class", new List<string> { "Square", "Normal", "RugsAndBanners", "Chaos" } }, { "Picture Frame - Picture 01", new List<string> { "Square", "Normal", "RugsAndBanners", "Chaos" } }, { "Painting_Aurora", new List<string> { "Square", "Normal", "RugsAndBanners", "Chaos" } }, { "Painting_McJannek", new List<string> { "Square", "Normal", "RugsAndBanners", "Chaos" } }, { "Painting Aurora", new List<string> { "Square", "Normal", "RugsAndBanners", "Chaos" } }, { "Painting McJannek", new List<string> { "Square", "Normal", "RugsAndBanners", "Chaos" } }, { "Painting_V_jannk", new List<string> { "Portrait", "Normal", "RugsAndBanners", "Chaos" } }, { "Painting_V_Furman", new List<string> { "Portrait", "Normal", "RugsAndBanners", "Chaos" } }, { "Painting_V_surrealistic", new List<string> { "Portrait", "Normal", "RugsAndBanners", "Chaos" } }, { "Painting_V_surrealistic_0", new List<string> { "Portrait", "Normal", "RugsAndBanners", "Chaos" } }, { "painting teacher01", new List<string> { "Portrait", "Normal", "RugsAndBanners", "Chaos" } }, { "painting teacher02", new List<string> { "Portrait", "Normal", "RugsAndBanners", "Chaos" } }, { "painting teacher03", new List<string> { "Portrait", "Normal", "RugsAndBanners", "Chaos" } }, { "painting teacher04", new List<string> { "Portrait", "Normal", "RugsAndBanners", "Chaos" } }, { "Painting_S_Tree", new List<string> { "Portrait", "Normal", "RugsAndBanners", "Chaos" } }, { "Painting Calendar", new List<string> { "Portrait", "Normal", "RugsAndBanners", "Chaos" } }, { "Magazine01", new List<string> { "Portrait", "Normal", "RugsAndBanners", "Chaos" } }, { "Magazine02", new List<string> { "Portrait", "Normal", "RugsAndBanners", "Chaos" } }, { "Magazine03", new List<string> { "Portrait", "Normal", "RugsAndBanners", "Chaos" } }, { "Magazine04", new List<string> { "Portrait", "Normal", "RugsAndBanners", "Chaos" } }, { "Magazine05", new List<string> { "Portrait", "Normal", "RugsAndBanners", "Chaos" } }, { "Valuable_Painting", new List<string> { "Portrait", "Normal", "RugsAndBanners", "Chaos" } }, { "Rug", new List<string> { "Square", "RugsAndBanners", "Chaos" } }, { "shop rug", new List<string> { "Square", "RugsAndBanners", "Chaos" } }, { "Bathroom Rug", new List<string> { "Square", "RugsAndBanners", "Chaos" } }, { "Rug Plain Red", new List<string> { "Landscape", "RugsAndBanners", "Chaos" } }, { "Wizard Wall Flag", new List<string> { "Portrait", "RugsAndBanners", "Chaos" } }, { "regular material 01", new List<string> { "Square", "Chaos" } }, { "Arctic Sign Accounting", new List<string> { "Landscape", "Chaos" } }, { "Arctic Sign Bathroom", new List<string> { "Landscape", "Chaos" } }, { "Arctic Sign Botanical Research", new List<string> { "Landscape", "Chaos" } }, { "Arctic Sign Brige 4B", new List<string> { "Landscape", "Chaos" } }, { "Arctic Sign Brige 8N", new List<string> { "Landscape", "Chaos" } }, { "Arctic Sign Cafeteria", new List<string> { "Landscape", "Chaos" } }, { "Arctic Sign Cargo processing", new List<string> { "Landscape", "Chaos" } }, { "Arctic Sign Catwalk L5", new List<string> { "Landscape", "Chaos" } }, { "Arctic Sign Cooling Center", new List<string> { "Landscape", "Chaos" } }, { "Arctic Sign Epsilon Station", new List<string> { "Landscape", "Chaos" } }, { "Arctic Sign Exotic Materials Division", new List<string> { "Landscape", "Chaos" } }, { "Arctic Sign Infirmary", new List<string> { "Landscape", "Chaos" } }, { "Arctic Sign Kitchen", new List<string> { "Landscape", "Chaos" } }, { "Arctic Sign Living Quarters", new List<string> { "Landscape", "Chaos" } }, { "Arctic Sign Loading Dock", new List<string> { "Landscape", "Chaos" } }, { "Arctic Sign Maintenance2", new List<string> { "Landscape", "Chaos" } }, { "Arctic Sign Observation Platform", new List<string> { "Landscape", "Chaos" } }, { "Arctic Sign Recreation", new List<string> { "Landscape", "Chaos" } }, { "Arctic Sign Research Lab", new List<string> { "Landscape", "Chaos" } }, { "Arctic Sign Storage Yard", new List<string> { "Landscape", "Chaos" } }, { "Arctic Sign Testing Lab", new List<string> { "Landscape", "Chaos" } }, { "Arctic Sign Vehicle Maintenance", new List<string> { "Landscape", "Chaos" } }, { "Arctic Sign Ventilation Chamber", new List<string> { "Landscape", "Chaos" } }, { "Arctic Sign Warehouse", new List<string> { "Landscape", "Chaos" } }, { "Arctic Sign", new List<string> { "Landscape", "Chaos" } }, { "Lobby Sign - Closed Road", new List<string> { "Square", "Chaos" } }, { "Lobby Sign - No stopping", new List<string> { "Square", "Chaos" } }, { "Robot Company Sign 2", new List<string> { "Square", "Chaos" } }, { "Robot Company Sign 3", new List<string> { "Landscape", "Chaos" } }, { "Robot Company Sign 4", new List<string> { "Portrait", "Chaos" } }, { "Robot Company Sign 5", new List<string> { "Landscape", "Chaos" } }, { "Robot Company Sign 6", new List<string> { "Portrait", "Chaos" } }, { "Robot Company Sign 7", new List<string> { "Square", "Chaos" } }, { "Robot Company Sign", new List<string> { "Square", "Chaos" } }, { "Wizard Sign Cauldron Storage", new List<string> { "Landscape", "Chaos" } }, { "Wizard Sign Common Room", new List<string> { "Landscape", "Chaos" } }, { "Wizard Sign Courtyard", new List<string> { "Landscape", "Chaos" } }, { "Wizard Sign Dark Arts", new List<string> { "Landscape", "Chaos" } }, { "Wizard Sign Deathpit Corridor", new List<string> { "Landscape", "Chaos" } }, { "Wizard Sign Dining Hall", new List<string> { "Landscape", "Chaos" } }, { "Wizard Sign Dormatory", new List<string> { "Landscape", "Chaos" } }, { "Wizard Sign Dungeon", new List<string> { "Landscape", "Chaos" } }, { "Wizard Sign East Wing Lobby", new List<string> { "Landscape", "Chaos" } }, { "Wizard Sign Enchanted Lava Room", new List<string> { "Landscape", "Chaos" } }, { "Wizard Sign Gnome Alley", new List<string> { "Landscape", "Chaos" } }, { "Wizard Sign Headmasters Study", new List<string> { "Landscape", "Chaos" } }, { "Wizard Sign Lecture Hall", new List<string> { "Landscape", "Chaos" } }, { "Wizard Sign Magic Plant School", new List<string> { "Landscape", "Chaos" } }, { "Wizard Sign Potions And Spells", new List<string> { "Landscape", "Chaos" } }, { "Wizard Sign Relaxation Room", new List<string> { "Landscape", "Chaos" } }, { "Wizard Sign Sludge Pits of Joy", new List<string> { "Landscape", "Chaos" } }, { "Wizard Sign Sludge Pits", new List<string> { "Landscape", "Chaos" } }, { "Wizard Sign Sorcery Class", new List<string> { "Landscape", "Chaos" } }, { "Wizard Sign Storage Room", new List<string> { "Landscape", "Chaos" } }, { "Wizard Sign The Great Library", new List<string> { "Landscape", "Chaos" } }, { "Wizard Sign Thinking Chamber", new List<string> { "Landscape", "Chaos" } }, { "Wizard Sign West Wing Garden", new List<string> { "Landscape", "Chaos" } }, { "upgrade_throw", new List<string> { "Landscape", "Chaos" } }, { "upgrade_strength", new List<string> { "Landscape", "Chaos" } }, { "upgrade_speed", new List<string> { "Landscape", "Chaos" } }, { "upgrade_health", new List<string> { "Landscape", "Chaos" } }, { "upgrade_grab range", new List<string> { "Landscape", "Chaos" } }, { "upgrade_energy", new List<string> { "Landscape", "Chaos" } }, { "upgrade_tumble_launch", new List<string> { "Landscape", "Chaos" } }, { "upgrade_map_player_count", new List<string> { "Landscape", "Chaos" } }, { "upgrade_extra_jump", new List<string> { "Landscape", "Chaos" } }, { "Welcome_Flag_Front", new List<string> { "Landscape", "Chaos" } }, { "Welcome_Flag_Back", new List<string> { "Landscape", "Chaos" } }, { "Wizard Door Double", new List<string> { "Portrait", "Chaos" } }, { "Wizard Door Double Blocked", new List<string> { "Portrait", "Chaos" } }, { "Wizard Door Double Blocked Lock", new List<string> { "Portrait", "Chaos" } }, { "Door Wizard", new List<string> { "Portrait", "Chaos" } }, { "Shop Door", new List<string> { "Portrait", "Chaos" } }, { "Door Shop WC", new List<string> { "Portrait", "Chaos" } }, { "Garage Door", new List<string> { "Landscape", "Chaos" } }, { "Arctic Door", new List<string> { "Portrait", "Chaos" } }, { "Arctic Door Blocked", new List<string> { "Portrait", "Chaos" } }, { "Museum Door", new List<string> { "Portrait", "Chaos" } }, { "door base", new List<string> { "Portrait", "Chaos" } }, { "Kitchen Fridge", new List<string> { "Square", "Chaos" } }, { "Inflatable Hammer", new List<string> { "Square", "Chaos" } }, { "Moon", new List<string> { "Square", "Chaos" } }, { "Soda Machine", new List<string> { "Landscape", "Chaos" } }, { "Soda Shelf Sodas", new List<string> { "Square", "Chaos" } }, { "Truck Item Shelf", new List<string> { "Square", "Chaos" } }, { "Map - Truck Wall", new List<string> { "Landscape", "Chaos" } }, { "Map - Truck Floor", new List<string> { "Landscape", "Chaos" } }, { "Truck Interior Front", new List<string> { "Square", "Chaos" } }, { "Truck Interior Back", new List<string> { "Square", "Chaos" } }, { "Truck Door", new List<string> { "Square", "Chaos" } }, { "Truck", new List<string> { "Landscape", "Chaos" } }, { "Truck_0", new List<string> { "Landscape", "Chaos" } }, { "Truck Glass Not Transparent", new List<string> { "Landscape", "Chaos" } }, { "Truck Glass Not Transparent Demolished", new List<string> { "Landscape", "Chaos" } }, { "Truck Demolished", new List<string> { "Landscape", "Chaos" } }, { "Truck Depot", new List<string> { "Square", "Chaos" } }, { "Truck Healer", new List<string> { "Square", "Chaos" } }, { "Valuable Arctic Guitar", new List<string> { "Landscape", "Chaos" } } }; public CustomPaintingsGroupList(Logger logger) { this.logger = logger; } } public class CustomPaintingsLoader { private const string IMAGE_FOLDER_NAME = "CustomPaintings"; private readonly Logger logger; public Dictionary<string, List<Material>> MaterialGroups = new Dictionary<string, List<Material>>(); private const string GRUNGE_ASSET_BUNDLE = "GrungeAssets"; private const string MATERIAL_LANDSCAPE_ASSET_NAME = "GrungeHorizontalMaterial"; private const string MATERIAL_PORTRAIT_ASSET_NAME = "GrungeVerticalMaterial"; private static Material _LandscapeMaterial; private static Material _PortraitMaterial; public List<Material> LoadedMaterials { get; } = new List<Material>(); public CustomPaintingsLoader(Logger logger) { this.logger = logger; } public void LoadImagesFromAllPlugins() { string text = Path.Combine(Paths.PluginPath); if (!Directory.Exists(text)) { logger.LogWarning("Plugins directory not found: " + text); return; } string[] directories = Directory.GetDirectories(text, "CustomPaintings", SearchOption.AllDirectories); LoadGrungeMaterials(); BindConfigUpdates(); if (directories.Length == 0) { logger.LogWarning("No 'CustomPaintings' folders found in plugins."); return; } string[] array = directories; foreach (string text2 in array) { logger.LogInfo("Loading images from: " + text2); LoadImagesFromDirectory(text2); } } private void LoadImagesFromDirectory(string directoryPath) { if (!Directory.Exists(directoryPath)) { logger.LogWarning("Directory does not exist: " + directoryPath); return; } string[] validExtensions = new string[4] { ".png", ".jpg", ".jpeg", ".bmp" }; string[] array = (from file in Directory.EnumerateFiles(directoryPath, "*.*", SearchOption.AllDirectories) where validExtensions.Contains(Path.GetExtension(file).ToLower()) select file).ToArray(); if (array.Length == 0) { logger.LogWarning("No images found in " + directoryPath); return; } for (int i = 0; i < array.Length; i++) { string text = array[i]; Texture2D val = LoadTextureFromFile(text); if ((Object)(object)val == (Object)null) { logger.LogWarning($"Failed to load image #{i + 1}: {text}"); continue; } float num = (float)((Texture)val).width / (float)((Texture)val).height; if (num > 1.3f) { AddGrungeMaterial("Landscape", _LandscapeMaterial, val); } else if (num < 0.769f) { AddGrungeMaterial("Portrait", _PortraitMaterial, val); } else { AddGrungeMaterial("Square", _LandscapeMaterial, val); } logger.LogInfo($"Loaded image #{i + 1}: {Path.GetFileName(text)}"); } foreach (KeyValuePair<string, List<Material>> materialGroup in MaterialGroups) { LoadedMaterials.AddRange(materialGroup.Value); } logger.LogInfo($"Total images loaded: {LoadedMaterials.Count}"); } private Material AddGrungeMaterial(Material grungeMaterial, Texture2D texture) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown if ((Object)(object)grungeMaterial == (Object)null) { logger.LogWarning("Falling back to default shader"); return new Material(Shader.Find("Standard")); } return new Material(grungeMaterial) { mainTexture = (Texture)(object)texture }; } private void AddGrungeMaterial(string paintingType, Material grungeMaterial, Texture2D texture) { if (!MaterialGroups.ContainsKey(paintingType)) { MaterialGroups[paintingType] = new List<Material>(); } Material item = AddGrungeMaterial(grungeMaterial, texture); MaterialGroups[paintingType].Add(item); } private Texture2D LoadTextureFromFile(string filePath) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown byte[] array = File.ReadAllBytes(filePath); Texture2D val = new Texture2D(2, 2); if (ImageConversion.LoadImage(val, array)) { SetFilterMode((Texture)(object)val); val.Apply(); return val; } return null; } private void LoadGrungeMaterials() { string? directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string text = "GrungeAssets"; string text2 = Path.Combine(directoryName, text); logger.LogInfo("Loading [" + text2 + "]"); if (File.Exists(text2)) { logger.LogInfo("Grunge Asset Bundle exists."); } else { logger.LogWarning("Grunge Asset Bundle doesn't exist!"); } AssetBundle val = AssetBundle.LoadFromFile(text2); if ((Object)(object)val == (Object)null) { logger.LogError("Failed to load [" + text + "]!"); } else { _LandscapeMaterial = val.LoadAsset<Material>("GrungeHorizontalMaterial"); if ((Object)(object)_LandscapeMaterial == (Object)null) { logger.LogError("Could not load landscape painting material [GrungeHorizontalMaterial]!"); } _PortraitMaterial = val.LoadAsset<Material>("GrungeVerticalMaterial"); if ((Object)(object)_PortraitMaterial == (Object)null) { logger.LogError("Could not load portrait painting material [GrungeVerticalMaterial]!"); } } if ((Object)(object)_LandscapeMaterial != (Object)null && (Object)(object)_PortraitMaterial != (Object)null) { logger.LogInfo("Grunge materials successfully loaded!"); } } internal void BindConfigUpdates() { CustomPaintingsConfig.Grunge.State.SettingChanged += OnGrungeConfigOptionChanged; CustomPaintingsConfig.Grunge.Intensity.SettingChanged += OnGrungeConfigOptionChanged; CustomPaintingsConfig.Grunge._BaseColor.SettingChanged += OnGrungeConfigOptionChanged; CustomPaintingsConfig.Grunge._BaseColor.SettingChanged += OnGrungeConfigOptionChanged; CustomPaintingsConfig.Grunge._MainColor.SettingChanged += OnGrungeConfigOptionChanged; CustomPaintingsConfig.Grunge._CracksColor.SettingChanged += OnGrungeConfigOptionChanged; CustomPaintingsConfig.Grunge._OutlineColor.SettingChanged += OnGrungeConfigOptionChanged; CustomPaintingsConfig.Graphics.PointFiltering.SettingChanged += OnPointFilteringConfigOptionChange; } internal void OnPointFilteringConfigOptionChange(object sender, EventArgs e) { foreach (Material loadedMaterial in LoadedMaterials) { SetFilterMode(loadedMaterial.mainTexture); } } internal void SetFilterMode(Texture texture) { if (CustomPaintingsConfig.Graphics.PointFiltering.Value) { texture.filterMode = (FilterMode)0; } else { texture.filterMode = (FilterMode)2; } } internal void OnGrungeConfigOptionChanged(object sender, EventArgs e) { UpdateGrungeMaterialParameters(); } internal void UpdateGrungeMaterialParameters() { //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) logger.LogDebug("Updating Grunge Material Parameters..."); bool value = CustomPaintingsConfig.Grunge.State.Value; float value2 = CustomPaintingsConfig.Grunge.Intensity.Value; Color val = default(Color); ((Color)(ref val))..ctor(1f, 1f, 1f, value2); logger.LogDebug($"Grunge state is [{value}]!"); logger.LogDebug($"Grunge intensity is [{value2}]!"); logger.LogDebug($"Number of loaded painting materials = [{LoadedMaterials.Count}]"); foreach (Material loadedMaterial in LoadedMaterials) { if ((Object)(object)loadedMaterial == (Object)null) { logger.LogWarning("No material found!"); } else if (value) { loadedMaterial.SetColor(((ConfigEntryBase)CustomPaintingsConfig.Grunge._BaseColor).Definition.Key, CustomPaintingsConfig.Grunge._BaseColor.Value); loadedMaterial.SetColor(((ConfigEntryBase)CustomPaintingsConfig.Grunge._MainColor).Definition.Key, CustomPaintingsConfig.Grunge._MainColor.Value * val); loadedMaterial.SetColor(((ConfigEntryBase)CustomPaintingsConfig.Grunge._CracksColor).Definition.Key, CustomPaintingsConfig.Grunge._CracksColor.Value * val); loadedMaterial.SetColor(((ConfigEntryBase)CustomPaintingsConfig.Grunge._OutlineColor).Definition.Key, CustomPaintingsConfig.Grunge._OutlineColor.Value * val); } else { loadedMaterial.SetColor(((ConfigEntryBase)CustomPaintingsConfig.Grunge._BaseColor).Definition.Key, Color.clear); loadedMaterial.SetColor(((ConfigEntryBase)CustomPaintingsConfig.Grunge._MainColor).Definition.Key, Color.clear); loadedMaterial.SetColor(((ConfigEntryBase)CustomPaintingsConfig.Grunge._CracksColor).Definition.Key, Color.clear); loadedMaterial.SetColor(((ConfigEntryBase)CustomPaintingsConfig.Grunge._OutlineColor).Definition.Key, Color.clear); } } } } public class CustomPaintingsSwap { public enum ModState { Host, Client, SinglePlayer } private readonly Logger logger; private readonly CustomPaintingsLoader loader; private readonly CustomPaintingsGroupList grouper; private static CustomPaintingsConfig configfile; public static int HostSeed = 0; public static int ReceivedSeed = 0; public static int Seed = 0; public static string SeperateState = "Singleplayer"; public static bool RBState = false; public static bool ChaosState = false; public static string ImageMode = "Normal"; private int paintingsChangedCount; private int LandscapeChangedCount; private int SquareChangedCount; private int PortraitChangedCount; private static ModState currentState = ModState.SinglePlayer; public ModState GetModState() { return currentState; } public CustomPaintingsSwap(Logger logger, CustomPaintingsLoader loader, CustomPaintingsGroupList grouper) { this.logger = logger; this.loader = loader; this.grouper = grouper; logger.LogInfo($"Initial ModState: {currentState}"); } public void ReplacePaintings() { //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_036a: Unknown result type (might be due to invalid IL or missing references) //IL_036f: Unknown result type (might be due to invalid IL or missing references) if (currentState == ModState.SinglePlayer) { Seed = Random.Range(0, int.MaxValue); logger.LogInfo($"Generated new random singleplayer seed: {Seed}"); } if (currentState == ModState.Host) { Seed = HostSeed; } if (currentState == ModState.Client) { Seed = ReceivedSeed; } if ((CustomPaintingsConfig.ChaosMode.Value && !CustomPaintingsConfig.HostControl.Value) || (ChaosState && CustomPaintingsConfig.HostControl.Value)) { ImageMode = "Chaos"; } else if ((!CustomPaintingsConfig.ChaosMode.Value && !CustomPaintingsConfig.HostControl.Value) || (!ChaosState && CustomPaintingsConfig.HostControl.Value)) { if ((CustomPaintingsConfig.RugsAndBanners.Value && !CustomPaintingsConfig.HostControl.Value) || (RBState && CustomPaintingsConfig.HostControl.Value)) { ImageMode = "RugsAndBanners"; } else if ((!CustomPaintingsConfig.RugsAndBanners.Value && !CustomPaintingsConfig.HostControl.Value) || (!RBState && CustomPaintingsConfig.HostControl.Value)) { ImageMode = "Normal"; } } Scene activeScene = SceneManager.GetActiveScene(); logger.LogInfo($"Applying seed {Seed} for painting swaps in scene: {((Scene)(ref activeScene)).name}"); logger.LogInfo("Replacing all paintings with custom images..."); paintingsChangedCount = 0; int num = 0; Scene activeScene2; if ((!CustomPaintingsConfig.SeperateImages.Value && SeperateState == "Singleplayer") || (SeperateState == "off" && CustomPaintingsConfig.HostControl.Value) || (!CustomPaintingsConfig.HostControl.Value && !CustomPaintingsConfig.SeperateImages.Value)) { activeScene2 = SceneManager.GetActiveScene(); GameObject[] rootGameObjects = ((Scene)(ref activeScene2)).GetRootGameObjects(); for (int i = 0; i < rootGameObjects.Length; i++) { MeshRenderer[] componentsInChildren = rootGameObjects[i].GetComponentsInChildren<MeshRenderer>(); foreach (MeshRenderer val in componentsInChildren) { Material[] sharedMaterials = ((Renderer)val).sharedMaterials; for (int k = 0; k < sharedMaterials.Length; k++) { num++; string key = ((Object)sharedMaterials[k]).name.Trim(); if (CustomPaintingsGroupList.MaterialNameToGroup.TryGetValue(key, out var value) && (Object)(object)sharedMaterials[k] != (Object)null && value.Contains(ImageMode) && !((Object)sharedMaterials[k]).name.Contains("Painting Frame Vertical Gold") && !((Object)sharedMaterials[k]).name.Contains("Painting Frame Horizontal Gold") && loader.LoadedMaterials.Count > 0) { int index = Mathf.Abs((Seed + paintingsChangedCount) % loader.LoadedMaterials.Count); sharedMaterials[k] = loader.LoadedMaterials[index]; paintingsChangedCount++; } } ((Renderer)val).sharedMaterials = sharedMaterials; } } } else { if ((!CustomPaintingsConfig.SeperateImages.Value || !(SeperateState == "Singleplayer")) && (!(SeperateState == "on") || !CustomPaintingsConfig.HostControl.Value) && (CustomPaintingsConfig.HostControl.Value || !CustomPaintingsConfig.SeperateImages.Value)) { return; } activeScene2 = SceneManager.GetActiveScene(); GameObject[] rootGameObjects = ((Scene)(ref activeScene2)).GetRootGameObjects(); for (int i = 0; i < rootGameObjects.Length; i++) { MeshRenderer[] componentsInChildren = rootGameObjects[i].GetComponentsInChildren<MeshRenderer>(); foreach (MeshRenderer val2 in componentsInChildren) { Material[] sharedMaterials2 = ((Renderer)val2).sharedMaterials; for (int l = 0; l < sharedMaterials2.Length; l++) { num++; string key2 = ((Object)sharedMaterials2[l]).name.Trim(); if (CustomPaintingsGroupList.MaterialNameToGroup.TryGetValue(key2, out var value2) && (Object)(object)sharedMaterials2[l] != (Object)null && value2.Contains(ImageMode)) { if (((Object)sharedMaterials2[l]).name.Contains("Painting Frame Vertical Gold") || ((Object)sharedMaterials2[l]).name.Contains("Painting Frame Horizontal Gold")) { continue; } if (value2.Contains("Landscape")) { int index2 = Mathf.Abs((Seed + LandscapeChangedCount) % loader.MaterialGroups["Landscape"].Count); sharedMaterials2[l] = loader.MaterialGroups["Landscape"][index2]; LandscapeChangedCount++; } else if (value2.Contains("Square")) { int index3 = Mathf.Abs((Seed + SquareChangedCount) % loader.MaterialGroups["Square"].Count); sharedMaterials2[l] = loader.MaterialGroups["Square"][index3]; SquareChangedCount++; } else if (value2.Contains("Portrait")) { int index4 = Mathf.Abs((Seed + PortraitChangedCount) % loader.MaterialGroups["Portrait"].Count); sharedMaterials2[l] = loader.MaterialGroups["Portrait"][index4]; PortraitChangedCount++; } } ((Renderer)val2).sharedMaterials = sharedMaterials2; } } } logger.LogInfo($"Total materials checked: {num}"); logger.LogInfo($"Total paintings changed in this scene: {LandscapeChangedCount + SquareChangedCount + PortraitChangedCount}"); } } public void SetState(ModState newState) { currentState = newState; logger.LogInfo($"Mod state set to: {currentState}"); } } public class CustomPaintingsSync : MonoBehaviourPunCallbacks, IOnEventCallback { private readonly Logger logger; public const byte SeedEventCode = 1; public const byte HostSettingsCode = 2; public CustomPaintingsSync(Logger logger) { this.logger = logger; } public void SendSeed(int seed) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_0037: Unknown result type (might be due to invalid IL or missing references) object[] array = new object[1] { seed }; logger.LogInfo("sharing seed with other clients"); RaiseEventOptions val = new RaiseEventOptions { Receivers = (ReceiverGroup)1, CachingOption = (EventCaching)4 }; PhotonNetwork.RaiseEvent((byte)1, (object)array, val, SendOptions.SendReliable); } public void SendHostSettings(string HostSeperateState, bool HostRBState, bool Chaosstate) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) object[] array = new object[3] { HostSeperateState, HostRBState, Chaosstate }; logger.LogInfo("sharing seperation setting"); RaiseEventOptions val = new RaiseEventOptions { Receivers = (ReceiverGroup)1, CachingOption = (EventCaching)4 }; PhotonNetwork.RaiseEvent((byte)2, (object)array, val, SendOptions.SendReliable); } public void OnEvent(EventData photonEvent) { if (photonEvent.Code == 1) { int num = (int)((object[])photonEvent.CustomData)[0]; logger.LogInfo($"Received seed: {num}"); CustomPaintingsSwap.ReceivedSeed = num; } if (photonEvent.Code == 2) { object[] obj = (object[])photonEvent.CustomData; string text = (string)obj[0]; bool flag = (bool)obj[1]; bool flag2 = (bool)obj[2]; logger.LogInfo("Received seperate state: " + text); logger.LogInfo($"Received Rug and Banner state: {flag}"); logger.LogInfo($"Received chaos state: {flag2}"); CustomPaintingsSwap.SeperateState = text; CustomPaintingsSwap.RBState = flag; CustomPaintingsSwap.ChaosState = flag2; } } } public class Logger { private readonly string logFilePath; private readonly ManualLogSource logSource; public Logger(string modName) { string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); logFilePath = Path.Combine(directoryName, modName + "_log.txt"); if (File.Exists(logFilePath)) { File.Delete(logFilePath); } logSource = Logger.CreateLogSource(modName); } public void LogDebug(string message) { WriteLog("DEBUG", message); logSource.LogDebug((object)message); } public void LogInfo(string message) { WriteLog("INFO", message); logSource.LogInfo((object)message); } public void LogWarning(string message) { WriteLog("WARNING", message); logSource.LogWarning((object)message); } public void LogError(string message) { WriteLog("ERROR", message); logSource.LogError((object)message); } private void WriteLog(string level, string message) { string text = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} [{level}] {message}"; File.AppendAllText(logFilePath, text + Environment.NewLine); } public void LogMaterial(Material material) { if ((Object)(object)material != (Object)null && ((Object)material).name.ToLower().Contains("painting")) { LogInfo("Material containing 'painting': " + ((Object)material).name); } } public void ClearLog() { if (File.Exists(logFilePath)) { File.Delete(logFilePath); } } } }
BepInEx/REPOLib.dll
Decompiled a year ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using REPOLib.Commands; using REPOLib.Extensions; using REPOLib.Modules; using REPOLib.Objects; using REPOLib.Objects.Sdk; using REPOLib.Patches; using TMPro; using UnityEngine; using UnityEngine.Audio; using UnityEngine.UI; [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("Zehs")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright © 2025 Zehs")] [assembly: AssemblyDescription("Library for adding content to R.E.P.O.")] [assembly: AssemblyFileVersion("2.0.1.0")] [assembly: AssemblyInformationalVersion("2.0.1+56712f43ffba9641e36a63c6b573cff6e2791c96")] [assembly: AssemblyProduct("REPOLib")] [assembly: AssemblyTitle("REPOLib")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/ZehsTeam/REPOLib")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.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.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] [Microsoft.CodeAnalysis.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] [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 REPOLib { public static class BundleLoader { private class LoadOperation { public enum State { LoadingBundle, LoadingContent } public string Path { get; } public DateTime StartTime { get; } public State CurrentState { get; set; } public bool LoadContents { get; } public Func<AssetBundle, IEnumerator>? OnBundleLoaded { get; } public AssetBundleCreateRequest BundleRequest { get; } public TimeSpan ElapsedTime => DateTime.Now - StartTime; public string FileName => System.IO.Path.GetFileNameWithoutExtension(Path); public LoadOperation(string path, Func<AssetBundle, IEnumerator>? onBundleLoaded = null, bool loadContents = true) { Path = path; StartTime = DateTime.Now; LoadContents = loadContents; OnBundleLoaded = onBundleLoaded; BundleRequest = AssetBundle.LoadFromFileAsync(path); base..ctor(); } } [StructLayout(LayoutKind.Auto)] [CompilerGenerated] private struct <>c__DisplayClass11_0 { public LoadOperation operation; } [CompilerGenerated] private sealed class <>c__DisplayClass6_0 { public Action<AssetBundle> onLoaded; } [CompilerGenerated] private sealed class <FinishLoadOperation>d__11 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public LoadOperation operation; private <>c__DisplayClass11_0 <>8__1; private AssetBundle <bundle>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <FinishLoadOperation>d__11(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>8__1 = default(<>c__DisplayClass11_0); <bundle>5__2 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>8__1.operation = operation; <>2__current = <>8__1.operation.BundleRequest; <>1__state = 1; return true; case 1: <>1__state = -1; <bundle>5__2 = <>8__1.operation.BundleRequest.assetBundle; if ((Object)(object)<bundle>5__2 == (Object)null) { Logger.LogError("Failed to load bundle " + <>8__1.operation.FileName + "!"); <FinishLoadOperation>g__Finish|11_0(ref <>8__1); return false; } if (<>8__1.operation.LoadContents) { <>2__current = LoadBundleContent(<>8__1.operation, <bundle>5__2); <>1__state = 2; return true; } goto IL_00f6; case 2: <>1__state = -1; goto IL_00f6; case 3: { <>1__state = -1; break; } IL_00f6: if (<>8__1.operation.OnBundleLoaded != null) { <>2__current = <>8__1.operation.OnBundleLoaded(<bundle>5__2); <>1__state = 3; return true; } break; } if (ConfigManager.ExtendedLogging.Value) { Logger.LogInfo($"Loaded bundle {<>8__1.operation.FileName} in {<>8__1.operation.ElapsedTime.TotalSeconds:N1}s"); } <FinishLoadOperation>g__Finish|11_0(ref <>8__1); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <FinishLoadOperationsRoutine>d__9 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public MonoBehaviour behaviour; private TMP_Text <text>5__2; private Action <disableLoadingUI>5__3; private float <lastUpdate>5__4; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <FinishLoadOperationsRoutine>d__9(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <text>5__2 = null; <disableLoadingUI>5__3 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: { <>1__state = -1; LoadOperation[] array = _operations.ToArray(); foreach (LoadOperation operation in array) { behaviour.StartCoroutine(FinishLoadOperation(operation)); } (TMP_Text, Action) tuple = SetupLoadingUI(); <text>5__2 = tuple.Item1; <disableLoadingUI>5__3 = tuple.Item2; <lastUpdate>5__4 = Time.time; break; } case 2: <>1__state = -1; break; } while (_operations.Count > 0) { if (Time.time - <lastUpdate>5__4 > 1f) { <lastUpdate>5__4 = Time.time; string arg = ((_operations.Count == 1) ? "bundle" : "bundles"); <text>5__2.text = $"REPOLib: Waiting for {_operations.Count} {arg} to load..."; if (!ConfigManager.ExtendedLogging.Value) { continue; } foreach (LoadOperation operation2 in _operations) { string text = $"Loading {operation2.FileName}: {operation2.CurrentState}"; float? num = ((operation2.CurrentState != 0) ? null : new float?(((AsyncOperation)operation2.BundleRequest).progress)); float? num2 = num; if (num2.HasValue) { text += $" {num2.Value:P0}"; } Logger.LogDebug(text); } } <>2__current = null; <>1__state = 2; return true; } Logger.LogInfo("Finished loading bundles."); <disableLoadingUI>5__3(); Utilities.SafeInvokeEvent(BundleLoader.OnAllBundlesLoaded); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <LoadBundleContent>d__12 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public LoadOperation operation; public AssetBundle bundle; private AssetBundleRequest <assetRequest>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <LoadBundleContent>d__12(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <assetRequest>5__2 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; operation.CurrentState = LoadOperation.State.LoadingContent; <assetRequest>5__2 = bundle.LoadAllAssetsAsync<ScriptableObject>(); <>2__current = <assetRequest>5__2; <>1__state = 1; return true; case 1: { <>1__state = -1; Object[] allAssets = <assetRequest>5__2.allAssets; Mod[] array = allAssets.OfType<Mod>().ToArray(); int num = array.Length; if (num <= 1) { if (num == 0) { Logger.LogError("Bundle " + operation.FileName + " contains no mods!"); return false; } Mod mod = array[0]; foreach (Content item in allAssets.OfType<Content>()) { try { item.Initialize(mod); } catch (Exception ex) { Logger.LogError($"Failed to load {item.Name} ({((object)item).GetType().Name}) from bundle {operation.FileName} ({mod.Identifier}): {ex}"); } } return false; } Logger.LogError("Bundle " + operation.FileName + " contains more than one mod!"); return false; } } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static readonly List<LoadOperation> _operations = new List<LoadOperation>(); public static event Action? OnAllBundlesLoaded; internal static void LoadAllBundles(string root, string withExtension) { Logger.LogInfo("Loading all bundles with extension " + withExtension + " from root " + root, extended: true); string[] files = Directory.GetFiles(root, "*" + withExtension, SearchOption.AllDirectories); string[] array = files; foreach (string path in array) { LoadBundleAndContent(path); } } public static void LoadBundleAndContent(string path) { LoadBundle(path, (Func<AssetBundle, IEnumerator>?)null, loadContents: true); } public static void LoadBundle(string path, Action<AssetBundle> onLoaded, bool loadContents = false) { <>c__DisplayClass6_0 CS$<>8__locals0 = new <>c__DisplayClass6_0(); CS$<>8__locals0.onLoaded = onLoaded; LoadBundle(path, (Func<AssetBundle, IEnumerator>?)OnLoaded, loadContents); [IteratorStateMachine(typeof(<>c__DisplayClass6_0.<<LoadBundle>g__OnLoaded|0>d))] IEnumerator OnLoaded(AssetBundle bundle) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <>c__DisplayClass6_0.<<LoadBundle>g__OnLoaded|0>d(0) { <>4__this = CS$<>8__locals0, bundle = bundle }; } } public static void LoadBundle(string path, Func<AssetBundle, IEnumerator>? onLoaded = null, bool loadContents = false) { Logger.LogInfo("Loading bundle at " + path + "..."); _operations.Add(new LoadOperation(path, onLoaded, loadContents)); } internal static void FinishLoadOperations(MonoBehaviour behaviour) { behaviour.StartCoroutine(FinishLoadOperationsRoutine(behaviour)); } [IteratorStateMachine(typeof(<FinishLoadOperationsRoutine>d__9))] private static IEnumerator FinishLoadOperationsRoutine(MonoBehaviour behaviour) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <FinishLoadOperationsRoutine>d__9(0) { behaviour = behaviour }; } private static (TMP_Text, Action) SetupLoadingUI() { //IL_008c: 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) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) GameObject val = GameObject.Find("HUD Canvas"); Transform hud = val.transform.Find("HUD"); ((Component)hud).gameObject.SetActive(false); TMP_Text val2 = Object.FindObjectOfType<TMP_Text>(); TMP_Text text = Object.Instantiate<TMP_Text>(val2, val.transform); ((Object)((Component)text).gameObject).name = "REPOLibText"; ((Component)text).gameObject.SetActive(true); text.text = "REPOLib is loading bundles... Hang tight!"; ((Graphic)text).color = Color.white; text.alignment = (TextAlignmentOptions)514; RectTransform component = ((Component)text).GetComponent<RectTransform>(); component.anchoredPosition = Vector2.zero; component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.sizeDelta = Vector2.zero; return (text, delegate { ((Component)text).gameObject.SetActive(false); ((Component)hud).gameObject.SetActive(true); }); } [IteratorStateMachine(typeof(<FinishLoadOperation>d__11))] private static IEnumerator FinishLoadOperation(LoadOperation operation) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <FinishLoadOperation>d__11(0) { operation = operation }; } [IteratorStateMachine(typeof(<LoadBundleContent>d__12))] private static IEnumerator LoadBundleContent(LoadOperation operation, AssetBundle bundle) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <LoadBundleContent>d__12(0) { operation = operation, bundle = bundle }; } [Obsolete("Use LoadBundleAndContent instead")] public static void LoadBundle(string path, string relativePath) { LoadBundleAndContent(path); } [CompilerGenerated] internal static void <FinishLoadOperation>g__Finish|11_0(ref <>c__DisplayClass11_0 P_0) { _operations.Remove(P_0.operation); } } internal static class ConfigManager { public static ConfigFile ConfigFile { get; private set; } public static ConfigEntry<bool> ExtendedLogging { get; private set; } public static ConfigEntry<bool> DeveloperMode { get; private set; } public static ConfigEntry<bool> VanillaDeveloperMode { get; private set; } public static void Initialize(ConfigFile configFile) { ConfigFile = configFile; BindConfigs(); } private static void BindConfigs() { ExtendedLogging = ConfigFile.Bind<bool>("General", "ExtendedLogging", false, "Enable extended logging."); DeveloperMode = ConfigFile.Bind<bool>("General", "DeveloperMode", false, "Enable developer mode cheats for testing."); VanillaDeveloperMode = ConfigFile.Bind<bool>("General", "VanillaDeveloperMode", false, "Enable vanilla developer mode cheats for testing."); VanillaDeveloperMode.SettingChanged += delegate { SteamManagerPatch.UpdateDeveloperMode(); }; } } internal static class Logger { public static ManualLogSource ManualLogSource { get; private set; } public static void Initialize(ManualLogSource manualLogSource) { ManualLogSource = manualLogSource; } public static void LogDebug(object data, bool extended = true) { Log((LogLevel)32, data, extended); } public static void LogInfo(object data, bool extended = false) { Log((LogLevel)16, data, extended); } public static void LogWarning(object data, bool extended = false) { Log((LogLevel)4, data, extended); } public static void LogError(object data, bool extended = false) { Log((LogLevel)2, data, extended); } public static void LogFatal(object data, bool extended = false) { Log((LogLevel)1, data, extended); } public static void Log(LogLevel logLevel, object data, bool extended = false) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (!extended || IsExtendedLoggingEnabled()) { ManualLogSource manualLogSource = ManualLogSource; if (manualLogSource != null) { manualLogSource.Log(logLevel, data); } } } public static bool IsExtendedLoggingEnabled() { if (ConfigManager.ExtendedLogging == null) { return false; } return ConfigManager.ExtendedLogging.Value; } } [BepInPlugin("REPOLib", "REPOLib", "2.0.1")] public class Plugin : BaseUnityPlugin { private readonly Harmony _harmony = new Harmony("REPOLib"); public static Plugin Instance { get; private set; } private void Awake() { Instance = this; Logger.Initialize(Logger.CreateLogSource("REPOLib")); Logger.LogInfo("REPOLib has awoken!"); _harmony.PatchAll(typeof(RunManagerPatch)); _harmony.PatchAll(typeof(EnemyDirectorPatch)); _harmony.PatchAll(typeof(StatsManagerPatch)); _harmony.PatchAll(typeof(SemiFuncPatch)); _harmony.PatchAll(typeof(AudioManagerPatch)); _harmony.PatchAll(typeof(SteamManagerPatch)); _harmony.PatchAll(typeof(EnemyGnomeDirectorPatch)); _harmony.PatchAll(typeof(EnemyBangDirectorPatch)); ConfigManager.Initialize(((BaseUnityPlugin)this).Config); BundleLoader.LoadAllBundles(Paths.PluginPath, ".repobundle"); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "REPOLib"; public const string PLUGIN_NAME = "REPOLib"; public const string PLUGIN_VERSION = "2.0.1"; } } namespace REPOLib.Patches { [HarmonyPatch(typeof(AudioManager))] internal static class AudioManagerPatch { [HarmonyPatch("Start")] [HarmonyPostfix] private static void StartPatch() { Utilities.FixAudioMixerGroupsOnPrefabs(); } } [HarmonyPatch(typeof(EnemyBangDirector))] internal static class EnemyBangDirectorPatch { [CompilerGenerated] private sealed class <PreSetup>d__1 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public EnemyBangDirector instance; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <PreSetup>d__1(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (LevelGenerator.Instance.Generated) { <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 1; return true; } goto IL_004e; case 1: <>1__state = -1; goto IL_004e; case 2: { <>1__state = -1; return false; } IL_004e: <>2__current = instance.Setup(); <>1__state = 2; return true; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [HarmonyPatch("Awake")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> AwakeTranspiler(IEnumerable<CodeInstruction> instructions) { //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(typeof(EnemyBangDirector), "Setup", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(EnemyBangDirectorPatch), "PreSetup", (Type[])null, (Type[])null); if (methodInfo == null || methodInfo2 == null) { Logger.LogError("EnemyBangDirectorPatch: failed to find required methods for AwakeTranspiler."); return instructions; } List<CodeInstruction> list = new List<CodeInstruction>(); foreach (CodeInstruction instruction in instructions) { if ((instruction.opcode == OpCodes.Call || instruction.opcode == OpCodes.Callvirt) && instruction.operand is MethodInfo methodInfo3 && methodInfo3 == methodInfo) { list.Add(new CodeInstruction(OpCodes.Call, (object)methodInfo2)); Logger.LogDebug("EnemyBangDirectorPatch: AwakeTranspiler replaced " + methodInfo.Name + " call with " + methodInfo2.Name + "."); } else { list.Add(instruction); } } return list.AsEnumerable(); } [IteratorStateMachine(typeof(<PreSetup>d__1))] private static IEnumerator PreSetup(EnemyBangDirector instance) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <PreSetup>d__1(0) { instance = instance }; } } [HarmonyPatch(typeof(EnemyDirector))] internal static class EnemyDirectorPatch { private static bool _alreadyRegistered; [HarmonyPatch("Awake")] [HarmonyPostfix] private static void AwakePatch() { if (_alreadyRegistered) { foreach (EnemySetup registeredEnemy in Enemies.RegisteredEnemies) { EnemyDirector.instance.AddEnemy(registeredEnemy); } return; } Enemies.RegisterInitialEnemies(); _alreadyRegistered = true; } } [HarmonyPatch(typeof(EnemyGnomeDirector))] internal static class EnemyGnomeDirectorPatch { [CompilerGenerated] private sealed class <PreSetup>d__1 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public EnemyGnomeDirector instance; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <PreSetup>d__1(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (LevelGenerator.Instance.Generated) { <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 1; return true; } goto IL_004e; case 1: <>1__state = -1; goto IL_004e; case 2: { <>1__state = -1; return false; } IL_004e: <>2__current = instance.Setup(); <>1__state = 2; return true; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [HarmonyPatch("Awake")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> AwakeTranspiler(IEnumerable<CodeInstruction> instructions) { //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(typeof(EnemyGnomeDirector), "Setup", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(EnemyGnomeDirectorPatch), "PreSetup", (Type[])null, (Type[])null); if (methodInfo == null || methodInfo2 == null) { Logger.LogError("EnemyGnomeDirectorPatch: failed to find required methods for AwakeTranspiler."); return instructions; } List<CodeInstruction> list = new List<CodeInstruction>(); foreach (CodeInstruction instruction in instructions) { if ((instruction.opcode == OpCodes.Call || instruction.opcode == OpCodes.Callvirt) && instruction.operand is MethodInfo methodInfo3 && methodInfo3 == methodInfo) { list.Add(new CodeInstruction(OpCodes.Call, (object)methodInfo2)); Logger.LogDebug("EnemyGnomeDirectorPatch: AwakeTranspiler replaced " + methodInfo.Name + " call with " + methodInfo2.Name + "."); } else { list.Add(instruction); } } return list.AsEnumerable(); } [IteratorStateMachine(typeof(<PreSetup>d__1))] private static IEnumerator PreSetup(EnemyGnomeDirector instance) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <PreSetup>d__1(0) { instance = instance }; } } [HarmonyPatch(typeof(RunManager))] internal static class RunManagerPatch { private static bool _patchedAwake; [HarmonyPatch("Awake")] [HarmonyPostfix] [HarmonyPriority(0)] private static void AwakePatch(RunManager __instance) { if (!_patchedAwake) { _patchedAwake = true; NetworkPrefabs.Initialize(); NetworkingEvents.Initialize(); Levels.RegisterInitialLevels(); Valuables.RegisterInitialValuables(); BundleLoader.OnAllBundlesLoaded += CommandManager.Initialize; BundleLoader.FinishLoadOperations((MonoBehaviour)(object)__instance); } } } [HarmonyPatch(typeof(SemiFunc))] internal static class SemiFuncPatch { [HarmonyPatch("Command")] [HarmonyPrefix] private static bool CommandPatch(string _command) { if (_command.StartsWith("/")) { return Command(_command); } return true; } private static bool Command(string message) { string text = message.ToLower(); string text2 = text.Split(' ')[0].Substring(1); string text3 = ""; if (text.Length > text2.Length) { text3 = text.Substring(text2.Length + 1).Trim(); } CommandManager.CommandExecutionMethods.TryGetValue(text2, out MethodInfo value); if (value != null) { CommandExecutionAttribute customAttribute = value.GetCustomAttribute<CommandExecutionAttribute>(); if (CommandManager.CommandsEnabled.TryGetValue(customAttribute.Name, out var value2) && !value2) { return false; } if (customAttribute != null && customAttribute.RequiresDeveloperMode && !ConfigManager.DeveloperMode.Value) { Logger.LogWarning("Command " + text2 + " requires developer mode to be enabled. Enable it in REPOLib.cfg"); return false; } try { ParameterInfo[] parameters = value.GetParameters(); if (parameters.Length == 0) { value.Invoke(null, null); } else { value.Invoke(null, new object[1] { text3 }); } } catch (Exception arg) { Logger.LogError($"Error executing command: {arg}"); } return false; } return true; } [HarmonyPatch("EnemySpawn")] [HarmonyPrefix] private static bool EnemySpawnPatch(ref bool __result) { if (Enemies.SpawnNextEnemiesNotDespawned > 0) { Enemies.SpawnNextEnemiesNotDespawned--; __result = true; return false; } return true; } } [HarmonyPatch(typeof(StatsManager))] internal static class StatsManagerPatch { [HarmonyPatch("RunStartStats")] [HarmonyPostfix] private static void RunStartStatsPatch() { Items.RegisterItems(); } } [HarmonyPatch(typeof(SteamManager))] internal static class SteamManagerPatch { [HarmonyPatch("Awake")] [HarmonyPostfix] public static void AwakePatch(SteamManager __instance) { UpdateDeveloperMode(); } public static void UpdateDeveloperMode() { if (ConfigManager.VanillaDeveloperMode == null || (Object)(object)SteamManager.instance == (Object)null) { return; } bool value = ConfigManager.VanillaDeveloperMode.Value; if (SteamManager.instance.developerMode != value) { if (value) { Logger.LogInfo("Enabling vanilla developer mode."); } else { Logger.LogInfo("Disabling vanilla developer mode."); } } SteamManager.instance.developerMode = value; } } } namespace REPOLib.Objects { public class CustomPrefabPool : IPunPrefabPool { public readonly Dictionary<string, GameObject> Prefabs = new Dictionary<string, GameObject>(); private DefaultPool? _defaultPool; public DefaultPool DefaultPool { get { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown if (_defaultPool == null) { _defaultPool = new DefaultPool(); } return _defaultPool; } set { if (value != null) { _defaultPool = value; } } } public bool RegisterPrefab(string prefabId, GameObject prefab) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)prefab == (Object)null) { throw new ArgumentException("CustomPrefabPool: failed to register network prefab. Prefab is null."); } if (string.IsNullOrWhiteSpace(prefabId)) { throw new ArgumentException("CustomPrefabPool: failed to register network prefab. PrefabId is invalid."); } if (ResourcesHelper.HasPrefab(prefabId)) { Logger.LogError("CustomPrefabPool: failed to register network prefab \"" + prefabId + "\". Prefab already exists in Resources with the same prefab id."); return false; } if (Prefabs.TryGetValue(prefabId, out GameObject value, ignoreKeyCase: true)) { LogLevel logLevel = (LogLevel)(((Object)(object)value == (Object)(object)prefab) ? 4 : 2); Logger.Log(logLevel, "CustomPrefabPool: failed to register network prefab \"" + prefabId + "\". There is already a prefab registered with the same prefab id."); return false; } Prefabs[prefabId] = prefab; Logger.LogDebug("CustomPrefabPool: registered network prefab \"" + prefabId + "\""); return true; } public bool HasPrefab(GameObject prefab) { if (Prefabs.ContainsValue(prefab)) { return true; } if (ResourcesHelper.HasPrefab(prefab)) { return true; } return false; } public bool HasPrefab(string prefabId) { if (Prefabs.ContainsKey(prefabId, ignoreKeyCase: true)) { return true; } if (ResourcesHelper.HasPrefab(prefabId)) { return true; } return false; } public string? GetPrefabId(GameObject prefab) { if ((Object)(object)prefab == (Object)null) { Logger.LogError("Failed to get prefab id. GameObject is null."); return string.Empty; } return Prefabs.GetKeyOrDefault(prefab); } public GameObject? GetPrefab(string prefabId) { return Prefabs.GetValueOrDefault(prefabId, ignoreKeyCase: true); } public GameObject? Instantiate(string prefabId, Vector3 position, Quaternion rotation) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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) //IL_0086: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrWhiteSpace(prefabId)) { throw new ArgumentException("CustomPrefabPool: failed to spawn network prefab. PrefabId is null."); } GameObject val; if (!Prefabs.TryGetValue(prefabId, out GameObject value, ignoreKeyCase: true)) { val = DefaultPool.Instantiate(prefabId, position, rotation); if ((Object)(object)val == (Object)null) { Logger.LogError("CustomPrefabPool: failed to spawn network prefab \"" + prefabId + "\". GameObject is null."); } return val; } bool activeSelf = value.activeSelf; if (activeSelf) { value.SetActive(false); } val = Object.Instantiate<GameObject>(value, position, rotation); if (activeSelf) { value.SetActive(true); } Logger.LogInfo($"CustomPrefabPool: spawned network prefab \"{prefabId}\" at position {position}, rotation {((Quaternion)(ref rotation)).eulerAngles}", extended: true); return val; } public void Destroy(GameObject gameObject) { Object.Destroy((Object)(object)gameObject); } } public class UnityObjectNameComparer<T> : IEqualityComparer<T> where T : Object { public StringComparison ComparisonType { get; private set; } public UnityObjectNameComparer(StringComparison comparisonType = StringComparison.OrdinalIgnoreCase) { ComparisonType = comparisonType; } public bool Equals(T x, T y) { if ((Object)(object)x == (Object)(object)y) { return true; } if ((Object)(object)x == (Object)null || (Object)(object)y == (Object)null) { return false; } return ((Object)x).name.Equals(((Object)y).name, ComparisonType); } public int GetHashCode(T obj) { if (!((Object)(object)obj != (Object)null)) { return 0; } return ((Object)obj).name.GetHashCode(); } } } namespace REPOLib.Objects.Sdk { public abstract class Content : ScriptableObject { public abstract string Name { get; } public abstract void Initialize(Mod mod); } [CreateAssetMenu(menuName = "REPOLib/Enemy", order = 3, fileName = "New Enemy")] public class EnemyContent : Content { [SerializeField] private EnemySetup _setup; public EnemySetup Setup => _setup; public override string Name { get { EnemySetup setup = Setup; return ((setup != null) ? ((Object)setup).name : null) ?? string.Empty; } } public override void Initialize(Mod mod) { Enemies.RegisterEnemy(Setup); } } [CreateAssetMenu(menuName = "REPOLib/Item", order = 2, fileName = "New Item")] public class ItemContent : Content { [SerializeField] private ItemAttributes _prefab; public ItemAttributes Prefab => _prefab; public override string Name { get { ItemAttributes prefab = Prefab; return ((prefab != null) ? ((Object)prefab).name : null) ?? string.Empty; } } public override void Initialize(Mod mod) { _prefab.item.prefab = ((Component)_prefab).gameObject; Items.RegisterItem(Prefab.item); } } [CreateAssetMenu(menuName = "REPOLib/Level", order = 4, fileName = "New Level")] public class LevelContent : Content { [SerializeField] private Level _level; public Level Level => _level; public override string Name { get { Level level = Level; return ((level != null) ? ((Object)level).name : null) ?? string.Empty; } } public override void Initialize(Mod mod) { Levels.RegisterLevel(Level); } } [CreateAssetMenu(menuName = "REPOLib/Mod", order = 0, fileName = "New Mod")] public class Mod : ScriptableObject { [SerializeField] private string _name; [SerializeField] private string _author; [SerializeField] private string _version = "1.0.0"; [SerializeField] private string _description; [SerializeField] private string _websiteUrl; [SerializeField] private string[] _dependencies = new string[1] { "Zehs-REPOLib-2.0.1" }; [SerializeField] private Sprite _icon; [SerializeField] private TextAsset _readme; public string Name => _name; public string Author => _author; public string Version => _version; public string Description => _description; public string WebsiteUrl => _websiteUrl; public IReadOnlyList<string> Dependencies => _dependencies; public Sprite Icon => _icon; public TextAsset Readme => _readme; public string FullName => Author + "-" + Name; public string Identifier => Author + "-" + Name + "-" + Version; } [CreateAssetMenu(menuName = "REPOLib/Valuable", order = 1, fileName = "New Valuable")] public class ValuableContent : Content { [SerializeField] private ValuableObject _prefab; [SerializeField] private string[] _valuablePresets = new string[1] { "Valuables - Generic" }; public ValuableObject Prefab => _prefab; public IReadOnlyList<string> ValuablePresets => _valuablePresets; public override string Name { get { ValuableObject prefab = Prefab; return ((prefab != null) ? ((Object)prefab).name : null) ?? string.Empty; } } public override void Initialize(Mod mod) { Valuables.RegisterValuable(((Component)Prefab).gameObject, ValuablePresets.ToList()); } } } namespace REPOLib.Modules { public static class Enemies { internal static int SpawnNextEnemiesNotDespawned = 0; private static readonly List<EnemySetup> _enemiesToRegister = new List<EnemySetup>(); private static readonly List<EnemySetup> _enemiesRegistered = new List<EnemySetup>(); private static bool _initialEnemiesRegistered; public static IReadOnlyList<EnemySetup> AllEnemies => GetEnemies(); public static IReadOnlyList<EnemySetup> RegisteredEnemies => _enemiesRegistered; internal static void RegisterInitialEnemies() { if (_initialEnemiesRegistered) { return; } foreach (EnemySetup item in _enemiesToRegister) { RegisterEnemyWithGame(item); } _enemiesToRegister.Clear(); _initialEnemiesRegistered = true; } private static void RegisterEnemyWithGame(EnemySetup enemy) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) if (!_enemiesRegistered.Contains(enemy) && enemy.TryGetEnemyParent(out EnemyParent enemyParent)) { if (EnemyDirector.instance.AddEnemy(enemy)) { _enemiesRegistered.Add(enemy); Logger.LogInfo($"Added enemy \"{enemyParent.enemyName}\" to difficulty {enemyParent.difficulty}", extended: true); } else { Logger.LogWarning($"Failed to add enemy \"{enemyParent.enemyName}\" to difficulty {enemyParent.difficulty}", extended: true); } } } public static void RegisterEnemy(EnemySetup enemySetup) { if ((Object)(object)enemySetup == (Object)null || enemySetup.spawnObjects == null || enemySetup.spawnObjects.Count == 0) { throw new ArgumentException("Failed to register enemy. EnemySetup or spawnObjects list is empty."); } EnemyParent enemyParent = enemySetup.GetEnemyParent(); if ((Object)(object)enemyParent == (Object)null) { Logger.LogError("Failed to register enemy \"" + ((Object)enemySetup).name + "\". No enemy prefab found in spawnObjects list."); return; } if (ResourcesHelper.HasEnemyPrefab(enemySetup)) { Logger.LogError("Failed to register enemy \"" + enemyParent.enemyName + "\". Enemy prefab already exists in Resources with the same name."); return; } if (_enemiesToRegister.Contains(enemySetup)) { Logger.LogError("Failed to register enemy \"" + enemyParent.enemyName + "\". Enemy is already registered!"); return; } foreach (GameObject distinctSpawnObject in enemySetup.GetDistinctSpawnObjects()) { foreach (EnemySetup item in _enemiesToRegister) { if (item.AnySpawnObjectsNameEqualsThatIsNotTheSameObject(distinctSpawnObject)) { Logger.LogError("Failed to register enemy \"" + enemyParent.enemyName + "\". Enemy \"" + ((Object)item).name + "\" already has a spawn object called \"" + ((Object)distinctSpawnObject).name + "\""); return; } } } foreach (GameObject distinctSpawnObject2 in enemySetup.GetDistinctSpawnObjects()) { string enemyPrefabPath = ResourcesHelper.GetEnemyPrefabPath(distinctSpawnObject2); if (!NetworkPrefabs.HasNetworkPrefab(enemyPrefabPath)) { NetworkPrefabs.RegisterNetworkPrefab(enemyPrefabPath, distinctSpawnObject2); } Utilities.FixAudioMixerGroups(distinctSpawnObject2); } if (_initialEnemiesRegistered) { RegisterEnemyWithGame(enemySetup); } else { _enemiesToRegister.Add(enemySetup); } } public static List<EnemyParent>? SpawnEnemy(EnemySetup enemySetup, Vector3 position, Quaternion rotation, bool spawnDespawned = true) { //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)enemySetup == (Object)null) { Logger.LogError("Failed to spawn enemy. EnemySetup is null."); return null; } if (!enemySetup.TryGetEnemyParent(out EnemyParent enemyParent)) { Logger.LogError("Failed to spawn enemy. EnemyParent is null."); return null; } if ((Object)(object)LevelGenerator.Instance == (Object)null) { Logger.LogError("Failed to spawn enemy \"" + enemyParent.enemyName + "\". EnemySetup instance is null."); return null; } if ((Object)(object)RunManager.instance == (Object)null) { Logger.LogError("Failed to spawn enemy \"" + enemyParent.enemyName + "\". RunManager instance is null."); return null; } if ((Object)(object)EnemyDirector.instance == (Object)null) { Logger.LogError("Failed to spawn enemy \"" + enemyParent.enemyName + "\". EnemyDirector instance is null."); return null; } List<EnemyParent> list = new List<EnemyParent>(); EnemyParent val2 = default(EnemyParent); foreach (GameObject sortedSpawnObject in enemySetup.GetSortedSpawnObjects()) { if ((Object)(object)sortedSpawnObject == (Object)null) { Logger.LogError("Failed to spawn enemy \"" + enemyParent.enemyName + "\" spawn object. GameObject is null."); continue; } string enemyPrefabPath = ResourcesHelper.GetEnemyPrefabPath(sortedSpawnObject); GameObject val = NetworkPrefabs.SpawnNetworkPrefab(enemyPrefabPath, position, rotation, 0); if ((Object)(object)val == (Object)null) { Logger.LogError("Failed to spawn enemy \"" + enemyParent.enemyName + "\" spawn object \"" + ((Object)sortedSpawnObject).name + "\""); } else if (val.TryGetComponent<EnemyParent>(ref val2)) { list.Add(val2); if (!spawnDespawned) { SpawnNextEnemiesNotDespawned++; } val2.SetupDone = true; Enemy componentInChildren = val.GetComponentInChildren<Enemy>(); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.EnemyTeleported(position); } else { Logger.LogError("Enemy \"" + enemyParent.enemyName + "\" spawn object \"" + ((Object)sortedSpawnObject).name + "\" does not have an enemy component."); } LevelGenerator instance = LevelGenerator.Instance; instance.EnemiesSpawnTarget++; EnemyDirector.instance.FirstSpawnPointAdd(val2); } } if (list.Count == 0) { Logger.LogInfo("Failed to spawn enemy \"" + enemyParent.enemyName + "\". No spawn objects where spawned.", extended: true); return list; } Logger.LogInfo($"Spawned enemy \"{enemyParent.enemyName}\" at position {position}", extended: true); RunManager.instance.EnemiesSpawnedRemoveEnd(); return list; } public static IReadOnlyList<EnemySetup> GetEnemies() { if ((Object)(object)EnemyDirector.instance == (Object)null) { return Array.Empty<EnemySetup>(); } return EnemyDirector.instance.GetEnemies(); } public static bool TryGetEnemyByName(string name, [NotNullWhen(true)] out EnemySetup? enemySetup) { enemySetup = GetEnemyByName(name); return (Object)(object)enemySetup != (Object)null; } public static EnemySetup? GetEnemyByName(string name) { return EnemyDirector.instance?.GetEnemyByName(name); } public static bool TryGetEnemyThatContainsName(string name, [NotNullWhen(true)] out EnemySetup? enemySetup) { enemySetup = GetEnemyThatContainsName(name); return (Object)(object)enemySetup != (Object)null; } public static EnemySetup? GetEnemyThatContainsName(string name) { return EnemyDirector.instance?.GetEnemyThatContainsName(name); } } public static class Items { private static readonly List<Item> _itemsToRegister = new List<Item>(); private static readonly List<Item> _itemsRegistered = new List<Item>(); private static bool _initialItemsRegistered; public static IReadOnlyList<Item> AllItems => GetItems(); public static IReadOnlyList<Item> RegisteredItems => _itemsRegistered; internal static void RegisterItems() { if ((Object)(object)StatsManager.instance == (Object)null) { Logger.LogError("Failed to register items. StatsManager instance is null."); return; } Logger.LogInfo("Adding items."); foreach (Item item in _itemsToRegister) { RegisterItemWithGame(item); } _initialItemsRegistered = true; } private static void RegisterItemWithGame(Item item) { Utilities.FixAudioMixerGroups(item.prefab); if (StatsManager.instance.AddItem(item)) { if (!_itemsRegistered.Contains(item)) { _itemsRegistered.Add(item); } Logger.LogInfo("Added item \"" + item.itemName + "\"", extended: true); } else { Logger.LogWarning("Failed to add item \"" + item.itemName + "\"", extended: true); } } public static void RegisterItem(Item item) { Item item2 = item; if ((Object)(object)item2 == (Object)null) { throw new ArgumentException("Failed to register item. Item is null."); } if ((Object)(object)item2.prefab == (Object)null) { Logger.LogError("Failed to register item \"" + item2.itemName + "\". Item prefab is null."); return; } if (item2.itemAssetName != ((Object)item2.prefab).name) { Logger.LogError("Failed to register item \"" + item2.itemName + "\". Item itemAssetName does not match the prefab name."); return; } if (ResourcesHelper.HasItemPrefab(item2)) { Logger.LogError("Failed to register item \"" + item2.itemName + "\". Item prefab already exists in Resources with the same name."); return; } if (_itemsToRegister.Any((Item x) => x.itemAssetName == item2.itemAssetName)) { Logger.LogError("Failed to register item \"" + item2.itemName + "\". Item prefab already exists with the same name."); return; } if (_itemsToRegister.Contains(item2)) { Logger.LogError("Failed to register item \"" + item2.itemName + "\". Item is already registered!"); return; } string itemPrefabPath = ResourcesHelper.GetItemPrefabPath(item2); NetworkPrefabs.RegisterNetworkPrefab(itemPrefabPath, item2.prefab); _itemsToRegister.Add(item2); if (_initialItemsRegistered) { RegisterItemWithGame(item2); } } public static GameObject? SpawnItem(Item item, Vector3 position, Quaternion rotation) { //IL_005d: 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_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)item == (Object)null) { Logger.LogError("Failed to spawn item. Item is null."); return null; } if ((Object)(object)item.prefab == (Object)null) { Logger.LogError("Failed to spawn item. Prefab is null."); return null; } if (!SemiFunc.IsMasterClientOrSingleplayer()) { Logger.LogError("Failed to spawn item \"" + item.itemName + "\". You are not the host."); return null; } string itemPrefabPath = ResourcesHelper.GetItemPrefabPath(item); GameObject val = NetworkPrefabs.SpawnNetworkPrefab(itemPrefabPath, position, rotation, 0); if ((Object)(object)val == (Object)null) { Logger.LogError("Failed to spawn item \"" + item.itemName + "\""); return null; } Logger.LogInfo($"Spawned item \"{item.itemName}\" at position {position}, rotation: {((Quaternion)(ref rotation)).eulerAngles}", extended: true); return val; } public static IReadOnlyList<Item> GetItems() { if ((Object)(object)StatsManager.instance == (Object)null) { return Array.Empty<Item>(); } return StatsManager.instance.GetItems(); } public static bool TryGetItemByName(string name, [NotNullWhen(true)] out Item? item) { item = GetItemByName(name); return (Object)(object)item != (Object)null; } public static Item? GetItemByName(string name) { return StatsManager.instance?.GetItemByName(name); } public static bool TryGetItemThatContainsName(string name, [NotNullWhen(true)] out Item? item) { item = GetItemThatContainsName(name); return (Object)(object)item != (Object)null; } public static Item? GetItemThatContainsName(string name) { return StatsManager.instance?.GetItemThatContainsName(name); } } public static class Levels { private static readonly List<Level> _levelsToRegister = new List<Level>(); private static readonly List<Level> _levelsRegistered = new List<Level>(); private static bool _initialLevelsRegistered; public static IReadOnlyList<Level> AllLevels => GetLevels(); public static IReadOnlyList<Level> RegisteredLevels => _levelsRegistered; internal static void RegisterInitialLevels() { if (_initialLevelsRegistered) { return; } ValuablePresets.CacheValuablePresets(); Logger.LogInfo("Adding levels."); foreach (Level item in _levelsToRegister) { RegisterLevelWithGame(item); } _levelsToRegister.Clear(); _initialLevelsRegistered = true; } private static void RegisterLevelWithGame(Level level) { if (_levelsRegistered.Contains(level)) { return; } if (level.ValuablePresets.Count == 0) { Logger.LogWarning("Level \"" + ((Object)level).name + "\" does not have any valuable presets! Adding generic preset."); level.ValuablePresets.Add(ValuablePresets.GenericPreset); } for (int i = 0; i < level.ValuablePresets.Count; i++) { LevelValuables val = level.ValuablePresets[i]; if (ValuablePresets.AllValuablePresets.Values.Contains(val)) { continue; } if (ValuablePresets.AllValuablePresets.TryGetValue(((Object)val).name, out LevelValuables value)) { if (val.GetCombinedList().Count > 0) { Logger.LogWarning("Proxy preset \"" + ((Object)val).name + "\" in level \"" + ((Object)level).name + "\" contains valuables! This likely caused duplicate valuables to load!"); } level.ValuablePresets[i] = value; Logger.LogInfo("Replaced proxy preset \"" + ((Object)val).name + "\" in level \"" + ((Object)level).name + "\".", extended: true); } else { ValuablePresets.RegisterValuablePreset(val); Logger.LogInfo("Registered valuable preset \"" + ((Object)val).name + "\" from \"" + ((Object)level).name + "\".", extended: true); } } RunManager.instance.levels.Add(level); Logger.LogInfo("Added level \"" + ((Object)level).name + "\"", extended: true); _levelsRegistered.Add(level); } public static void RegisterLevel(Level level) { Level level2 = level; if ((Object)(object)level2 == (Object)null) { Logger.LogError("Failed to register level. Level is null."); return; } if (_levelsToRegister.Any((Level x) => ((Object)x).name.Equals(((Object)level2).name, StringComparison.OrdinalIgnoreCase))) { Logger.LogError("Failed to register level \"" + ((Object)level2).name + "\". Level already exists with the same name."); return; } if (_levelsToRegister.Contains(level2)) { Logger.LogWarning("Failed to register level \"" + ((Object)level2).name + "\". Level is already registered!"); return; } List<(GameObject, ResourcesHelper.LevelPrefabType)> list2 = (from prefab in new List<GameObject>[12] { level2.ModulesExtraction1, level2.ModulesExtraction2, level2.ModulesExtraction3, level2.ModulesNormal1, level2.ModulesNormal2, level2.ModulesNormal3, level2.ModulesPassage1, level2.ModulesPassage2, level2.ModulesPassage3, level2.ModulesDeadEnd1, level2.ModulesDeadEnd2, level2.ModulesDeadEnd3 }.SelectMany((List<GameObject> list) => list) select (prefab, ResourcesHelper.LevelPrefabType.Module)).ToList(); foreach (GameObject startRoom in level2.StartRooms) { list2.Add((startRoom, ResourcesHelper.LevelPrefabType.StartRoom)); } if ((Object)(object)level2.ConnectObject != (Object)null) { list2.Add((level2.ConnectObject, ResourcesHelper.LevelPrefabType.Other)); } if ((Object)(object)level2.BlockObject != (Object)null) { list2.Add((level2.BlockObject, ResourcesHelper.LevelPrefabType.Other)); } foreach (var item3 in list2) { GameObject item = item3.Item1; ResourcesHelper.LevelPrefabType item2 = item3.Item2; string levelPrefabPath = ResourcesHelper.GetLevelPrefabPath(level2, item, item2); if (!ResourcesHelper.HasPrefab(levelPrefabPath)) { NetworkPrefabs.RegisterNetworkPrefab(levelPrefabPath, item); Utilities.FixAudioMixerGroups(item); } } if (_initialLevelsRegistered) { RegisterLevelWithGame(level2); } else { _levelsToRegister.Add(level2); } } public static IReadOnlyList<Level> GetLevels() { if ((Object)(object)RunManager.instance == (Object)null) { return Array.Empty<Level>(); } return RunManager.instance.levels; } public static bool TryGetLevelByName(string name, [NotNullWhen(true)] out Level? level) { level = GetLevelByName(name); return (Object)(object)level != (Object)null; } public static Level? GetLevelByName(string name) { foreach (Level level in GetLevels()) { if (((Object)level).name.EqualsAny(new <>z__ReadOnlyArray<string>(new string[2] { name, "Level - " + name }), StringComparison.OrdinalIgnoreCase)) { return level; } } return null; } public static bool TryGetLevelThatContainsName(string name, [NotNullWhen(true)] out Level? level) { level = GetLevelThatContainsName(name); return (Object)(object)level != (Object)null; } public static Level? GetLevelThatContainsName(string name) { foreach (Level level in GetLevels()) { if (((Object)level).name.Contains(name, StringComparison.OrdinalIgnoreCase)) { return level; } } return null; } } public static class NetworkingEvents { public static readonly byte[] ReservedEventCodes = new byte[3] { 0, 1, 2 }; private static readonly List<NetworkedEvent> _customEvents = new List<NetworkedEvent>(); public static readonly RaiseEventOptions RaiseAll = new RaiseEventOptions { Receivers = (ReceiverGroup)1 }; public static readonly RaiseEventOptions RaiseOthers = new RaiseEventOptions { Receivers = (ReceiverGroup)0 }; public static readonly RaiseEventOptions RaiseMasterClient = new RaiseEventOptions { Receivers = (ReceiverGroup)2 }; public static IReadOnlyList<NetworkedEvent> CustomEvents => _customEvents; internal static void Initialize() { PhotonNetwork.NetworkingClient.EventReceived += OnEvent; Application.quitting += delegate { PhotonNetwork.NetworkingClient.EventReceived -= OnEvent; }; } internal static void AddCustomEvent(NetworkedEvent networkedEvent) { if (!_customEvents.Contains(networkedEvent)) { _customEvents.Add(networkedEvent); } } private static void OnEvent(EventData photonEvent) { EventData photonEvent2 = photonEvent; _customEvents.FirstOrDefault((NetworkedEvent e) => e.EventCode == photonEvent2.Code)?.EventAction?.Invoke(photonEvent2); } internal static bool TryGetUniqueEventCode(out byte eventCode) { eventCode = 0; while (IsEventCodeTaken(eventCode) && eventCode < 200) { eventCode++; } if (eventCode > 200 || (eventCode == 200 && IsEventCodeTaken(eventCode))) { eventCode = 0; return false; } return true; } public static bool IsEventCodeTaken(byte eventCode) { if (ReservedEventCodes.Any((byte x) => x == eventCode)) { return true; } if (_customEvents.Any((NetworkedEvent x) => x.EventCode == eventCode)) { return true; } return false; } } public class NetworkedEvent { public string Name { get; private set; } public byte EventCode { get; private set; } public Action<EventData> EventAction { get; private set; } public NetworkedEvent(string name, Action<EventData> eventAction) { Name = name; EventAction = eventAction; if (NetworkingEvents.TryGetUniqueEventCode(out var eventCode)) { EventCode = eventCode; NetworkingEvents.AddCustomEvent(this); Logger.LogInfo($"Registered NetworkedEvent \"{Name}\" with event code: {EventCode}", extended: true); } else { Logger.LogError("Failed to register NetworkedEvent \"" + Name + "\". Could not get unique event code."); } } public void RaiseEvent(object eventContent, RaiseEventOptions raiseEventOptions, SendOptions sendOptions) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (SemiFunc.IsMultiplayer()) { PhotonNetwork.RaiseEvent(EventCode, eventContent, raiseEventOptions, sendOptions); } else if ((int)raiseEventOptions.Receivers != 0) { RaiseEventSingleplayer(eventContent); } } private void RaiseEventSingleplayer(object eventContent) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown if (!SemiFunc.IsMultiplayer()) { EventData val = new EventData { Code = EventCode }; val.Parameters[val.CustomDataKey] = eventContent; val.Parameters[val.SenderKey] = 1; EventAction?.Invoke(val); } } } public static class NetworkPrefabs { private static CustomPrefabPool? _customPrefabPool; internal static CustomPrefabPool CustomPrefabPool { get { if (_customPrefabPool == null) { _customPrefabPool = new CustomPrefabPool(); } return _customPrefabPool; } private set { _customPrefabPool = value; } } internal static void Initialize() { if (PhotonNetwork.PrefabPool is CustomPrefabPool) { Logger.LogWarning("NetworkPrefabs failed to initialize. PhotonNetwork.PrefabPool is already a CustomPrefabPool."); return; } Logger.LogInfo("Initializing NetworkPrefabs."); Logger.LogDebug($"PhotonNetwork.PrefabPool = {((object)PhotonNetwork.PrefabPool).GetType()}"); IPunPrefabPool prefabPool = PhotonNetwork.PrefabPool; DefaultPool val = (DefaultPool)(object)((prefabPool is DefaultPool) ? prefabPool : null); if (val != null) { CustomPrefabPool.DefaultPool = val; } else if (!(PhotonNetwork.PrefabPool is CustomPrefabPool)) { Logger.LogWarning($"PhotonNetwork has an unknown prefab pool assigned. PhotonNetwork.PrefabPool = {((object)PhotonNetwork.PrefabPool).GetType()}"); } PhotonNetwork.PrefabPool = (IPunPrefabPool)(object)CustomPrefabPool; Logger.LogInfo("Replaced PhotonNetwork.PrefabPool with CustomPrefabPool."); Logger.LogDebug($"PhotonNetwork.PrefabPool = {((object)PhotonNetwork.PrefabPool).GetType()}"); Logger.LogInfo("Finished initializing NetworkPrefabs."); } public static void RegisterNetworkPrefab(GameObject prefab) { RegisterNetworkPrefab((prefab != null) ? ((Object)prefab).name : null, prefab); } public static void RegisterNetworkPrefab(string prefabId, GameObject prefab) { CustomPrefabPool.RegisterPrefab(prefabId, prefab); } public static bool HasNetworkPrefab(string prefabId) { return CustomPrefabPool.HasPrefab(prefabId); } public static GameObject? SpawnNetworkPrefab(string prefabId, Vector3 position, Quaternion rotation, byte group = 0, object[]? data = null) { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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_005d: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrWhiteSpace(prefabId)) { Logger.LogError("Failed to spawn network prefab. PrefabId is null."); return null; } if (!HasNetworkPrefab(prefabId)) { Logger.LogError("Failed to spawn network prefab \"" + prefabId + "\". PrefabId is not registered as a network prefab."); return null; } if (!SemiFunc.IsMasterClientOrSingleplayer()) { Logger.LogError("Failed to spawn network prefab \"" + prefabId + "\". You are not the host."); return null; } if (SemiFunc.IsMultiplayer()) { return PhotonNetwork.InstantiateRoomObject(prefabId, position, rotation, group, data); } return Object.Instantiate<GameObject>(CustomPrefabPool.GetPrefab(prefabId), position, rotation); } } public static class ResourcesHelper { public enum LevelPrefabType { Module, Other, StartRoom } public static string GetValuablesFolderPath(Type volumeType) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected I4, but got Unknown return "Valuables/" + (int)volumeType switch { 0 => "01 Tiny", 1 => "02 Small", 2 => "03 Medium", 3 => "04 Big", 4 => "05 Wide", 5 => "06 Tall", 6 => "07 Very Tall", _ => string.Empty, }; } public static string GetItemsFolderPath() { return "Items"; } public static string GetEnemiesFolderPath() { return "Enemies"; } public static string GetLevelPrefabsFolderPath(Level level, LevelPrefabType type) { string text = type switch { LevelPrefabType.Module => "Modules", LevelPrefabType.Other => "Other", LevelPrefabType.StartRoom => "Start Room", _ => string.Empty, }; return "Level/" + level.ResourcePath + "/" + text; } public static string GetValuablePrefabPath(ValuableObject valuableObject) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)valuableObject == (Object)null) { return string.Empty; } string valuablesFolderPath = GetValuablesFolderPath(valuableObject.volumeType); return valuablesFolderPath + "/" + ((Object)((Component)valuableObject).gameObject).name; } public static string GetValuablePrefabPath(GameObject prefab) { if ((Object)(object)prefab == (Object)null) { return string.Empty; } ValuableObject valuableObject = default(ValuableObject); if (prefab.TryGetComponent<ValuableObject>(ref valuableObject)) { return GetValuablePrefabPath(valuableObject); } return string.Empty; } public static string GetItemPrefabPath(Item item) { if ((Object)(object)item == (Object)null) { return string.Empty; } return GetItemPrefabPath(item.prefab); } public static string GetItemPrefabPath(GameObject prefab) { if ((Object)(object)prefab == (Object)null) { return string.Empty; } string itemsFolderPath = GetItemsFolderPath(); return itemsFolderPath + "/" + ((Object)prefab).name; } public static string GetEnemyPrefabPath(EnemySetup enemySetup) { if ((Object)(object)enemySetup == (Object)null || enemySetup.spawnObjects == null) { return string.Empty; } GameObject mainSpawnObject = enemySetup.GetMainSpawnObject(); if ((Object)(object)mainSpawnObject == (Object)null) { return string.Empty; } string enemiesFolderPath = GetEnemiesFolderPath(); return enemiesFolderPath + "/" + ((Object)mainSpawnObject).name; } public static string GetEnemyPrefabPath(GameObject prefab) { if ((Object)(object)prefab == (Object)null) { return string.Empty; } string enemiesFolderPath = GetEnemiesFolderPath(); return enemiesFolderPath + "/" + ((Object)prefab).name; } public static string GetLevelPrefabPath(Level level, GameObject prefab, LevelPrefabType type) { if ((Object)(object)prefab == (Object)null) { return string.Empty; } string levelPrefabsFolderPath = GetLevelPrefabsFolderPath(level, type); return levelPrefabsFolderPath + "/" + ((Object)prefab).name; } public static bool HasValuablePrefab(ValuableObject valuableObject) { if ((Object)(object)valuableObject == (Object)null) { return false; } string valuablePrefabPath = GetValuablePrefabPath(valuableObject); return (Object)(object)Resources.Load<GameObject>(valuablePrefabPath) != (Object)null; } public static bool HasItemPrefab(Item item) { if ((Object)(object)item == (Object)null) { return false; } string itemPrefabPath = GetItemPrefabPath(item); return (Object)(object)Resources.Load<GameObject>(itemPrefabPath) != (Object)null; } public static bool HasEnemyPrefab(EnemySetup enemySetup) { if ((Object)(object)enemySetup == (Object)null) { return false; } foreach (GameObject distinctSpawnObject in enemySetup.GetDistinctSpawnObjects()) { string enemyPrefabPath = GetEnemyPrefabPath(distinctSpawnObject); if ((Object)(object)Resources.Load<GameObject>(enemyPrefabPath) != (Object)null) { return true; } } return false; } public static bool HasPrefab(GameObject prefab) { return (Object)(object)Resources.Load<GameObject>((prefab != null) ? ((Object)prefab).name : null) != (Object)null; } public static bool HasPrefab(string prefabId) { return (Object)(object)Resources.Load<GameObject>(prefabId) != (Object)null; } } public static class Utilities { private static readonly List<GameObject> _prefabsToFix = new List<GameObject>(); private static readonly List<GameObject> _fixedPrefabs = new List<GameObject>(); internal static void FixAudioMixerGroupsOnPrefabs() { foreach (GameObject item in _prefabsToFix) { item.FixAudioMixerGroups(); _fixedPrefabs.Add(item); } _prefabsToFix.Clear(); } public static void FixAudioMixerGroups(GameObject prefab) { if (!((Object)(object)prefab == (Object)null) && !_prefabsToFix.Contains(prefab) && !_fixedPrefabs.Contains(prefab)) { if ((Object)(object)AudioManager.instance == (Object)null) { _prefabsToFix.Add(prefab); return; } prefab.FixAudioMixerGroups(); _fixedPrefabs.Add(prefab); } } internal static void SafeInvokeEvent(Action? action) { try { action?.Invoke(); } catch (Exception arg) { Logger.LogError($"Exception occured while invoking event: {arg}"); } } } public static class ValuablePresets { private static readonly Dictionary<string, LevelValuables> _valuablePresets = new Dictionary<string, LevelValuables>(); public const string GenericValuablePresetName = "Valuables - Generic"; public static IReadOnlyDictionary<string, LevelValuables> AllValuablePresets => _valuablePresets; public static LevelValuables GenericPreset => AllValuablePresets["Valuables - Generic"]; public static void CacheValuablePresets() { if ((Object)(object)RunManager.instance == (Object)null) { Logger.LogError("Failed to cache LevelValuables. RunManager instance is null."); return; } foreach (Level level in RunManager.instance.levels) { foreach (LevelValuables valuablePreset in level.ValuablePresets) { _valuablePresets.TryAdd(((Object)valuablePreset).name, valuablePreset); } } } internal static void RegisterValuablePreset(LevelValuables valuablePreset) { _valuablePresets.Add(((Object)valuablePreset).name, valuablePreset); } } public static class Valuables { private static readonly Dictionary<GameObject, List<string>> _valuablesToRegister = new Dictionary<GameObject, List<string>>(); private static readonly List<GameObject> _valuablesRegistered = new List<GameObject>(); private static bool _initialValuablesRegistered; public static IReadOnlyList<GameObject> AllValuables => GetValuables(); public static IReadOnlyList<GameObject> RegisteredValuables => _valuablesRegistered; private static IEnumerable<GameObject> PendingAndRegisteredValuables => _valuablesToRegister.Keys.Concat(_valuablesRegistered); internal static void RegisterInitialValuables() { if (_initialValuablesRegistered) { return; } Logger.LogInfo("Adding valuables to valuable presets."); foreach (GameObject key in _valuablesToRegister.Keys) { RegisterValuableWithGame(key); } _valuablesToRegister.Clear(); _initialValuablesRegistered = true; } private static void RegisterValuableWithGame(GameObject valuable) { if (_valuablesRegistered.Contains(valuable)) { return; } List<string> list = _valuablesToRegister[valuable]; if (!list.Any((string x) => ValuablePresets.AllValuablePresets.Keys.Any((string y) => x == y))) { Logger.LogWarning("Valuable \"" + ((Object)valuable).name + "\" does not have any valid valuable preset names set. Adding generic valuable preset name."); list.Add("Valuables - Generic"); } foreach (string item in list) { if (item == null || !ValuablePresets.AllValuablePresets.ContainsKey(item)) { Logger.LogWarning("Failed to add valuable \"" + ((Object)valuable).name + "\" to valuable preset \"" + item + "\". The valuable preset does not exist."); } else if (ValuablePresets.AllValuablePresets[item].AddValuable(valuable)) { _valuablesRegistered.Add(valuable); Logger.LogDebug("Added valuable \"" + ((Object)valuable).name + "\" to valuable preset \"" + item + "\""); } else { Logger.LogWarning("Failed to add valuable \"" + ((Object)valuable).name + "\" to valuable preset \"" + item + "\"", extended: true); } } } public static void RegisterValuable(GameObject prefab) { RegisterValuable(prefab, new List<string>()); } public static void RegisterValuable(GameObject prefab, List<LevelValuables> presets) { RegisterValuable(prefab, presets.Select((LevelValuables preset) => ((Object)preset).name).ToList()); } public static void RegisterValuable(GameObject prefab, List<string> presetNames) { ValuableObject valuableObject = default(ValuableObject); if ((Object)(object)prefab == (Object)null) { Logger.LogError("Failed to register valuable. Prefab is null."); } else if (!prefab.TryGetComponent<ValuableObject>(ref valuableObject)) { Logger.LogError("Failed to register valuable. Prefab does not have a ValuableObject component."); } else { RegisterValuable(valuableObject, presetNames); } } public static void RegisterValuable(ValuableObject valuableObject) { RegisterValuable(valuableObject, new List<string>()); } public static void RegisterValuable(ValuableObject valuableObject, List<LevelValuables> presets) { RegisterValuable(valuableObject, presets.Select((LevelValuables preset) => ((Object)preset).name).ToList()); } public static void RegisterValuable(ValuableObject valuableObject, List<string> presetNames) { if ((Object)(object)valuableObject == (Object)null) { Logger.LogError("Failed to register valuable. ValuableObject is null."); return; } GameObject prefab = ((Component)valuableObject).gameObject; if (presetNames == null || presetNames.Count == 0) { Logger.LogWarning("Valuable \"" + ((Object)valuableObject).name + "\" does not have any valid valuable preset names set. Adding generic valuable preset name.", extended: true); presetNames = new List<string>(1) { "Valuables - Generic" }; } if (ResourcesHelper.HasValuablePrefab(valuableObject)) { Logger.LogError("Failed to register valuable \"" + ((Object)prefab).name + "\". Valuable prefab already exists in Resources with the same name."); return; } if (PendingAndRegisteredValuables.Any((GameObject x) => ((Object)x).name.Equals(((Object)prefab).name, StringComparison.OrdinalIgnoreCase))) { Logger.LogError("Failed to register valuable \"" + ((Object)prefab).name + "\". Valuable prefab already exists with the same name."); return; } if (PendingAndRegisteredValuables.Contains(prefab)) { Logger.LogWarning("Failed to register valuable \"" + ((Object)prefab).name + "\". Valuable is already registered!"); return; } string valuablePrefabPath = ResourcesHelper.GetValuablePrefabPath(valuableObject); NetworkPrefabs.RegisterNetworkPrefab(valuablePrefabPath, prefab); Utilities.FixAudioMixerGroups(prefab); _valuablesToRegister.Add(prefab, presetNames); if (_initialValuablesRegistered) { RegisterValuableWithGame(((Component)valuableObject).gameObject); } } public static GameObject? SpawnValuable(ValuableObject valuableObject, Vector3 position, Quaternion rotation) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)valuableObject == (Object)null) { Logger.LogError("Failed to spawn valuable. ValuableObject is null."); return null; } if (!SemiFunc.IsMasterClientOrSingleplayer()) { Logger.LogError("Failed to spawn valuable \"" + ((Object)((Component)valuableObject).gameObject).name + "\". You are not the host."); return null; } string valuablePrefabPath = ResourcesHelper.GetValuablePrefabPath(valuableObject); GameObject val = NetworkPrefabs.SpawnNetworkPrefab(valuablePrefabPath, position, rotation, 0); if ((Object)(object)val == (Object)null) { Logger.LogError("Failed to spawn valuable \"" + ((Object)((Component)valuableObject).gameObject).name + "\""); return null; } Logger.LogInfo($"Spawned valuable \"{((Object)val).name}\" at position {position}, rotation: {((Quaternion)(ref rotation)).eulerAngles}", extended: true); return val; } public static IReadOnlyList<GameObject> GetValuables() { if ((Object)(object)RunManager.instance == (Object)null) { return Array.Empty<GameObject>(); } return ValuablePresets.AllValuablePresets.Values.Select((LevelValuables levelValuables) => levelValuables.GetCombinedList()).SelectMany((List<GameObject> list) => list).Distinct() .ToList(); } public static bool TryGetValuableByName(string name, [NotNullWhen(true)] out ValuableObject? valuableObject) { valuableObject = GetValuableByName(name); return (Object)(object)valuableObject != (Object)null; } public static ValuableObject? GetValuableByName(string name) { ValuableObject result = default(ValuableObject); foreach (GameObject valuable in GetValuables()) { if (valuable.TryGetComponent<ValuableObject>(ref result) && ((Object)valuable).name.EqualsAny(new <>z__ReadOnlyArray<string>(new string[2] { name, "Valuable " + name }), StringComparison.OrdinalIgnoreCase)) { return result; } } return null; } public static bool TryGetValuableThatContainsName(string name, [NotNullWhen(true)] out ValuableObject? valuableObject) { valuableObject = GetValuableThatContainsName(name); return (Object)(object)valuableObject != (Object)null; } public static ValuableObject? GetValuableThatContainsName(string name) { ValuableObject result = default(ValuableObject); foreach (GameObject valuable in GetValuables()) { if (valuable.TryGetComponent<ValuableObject>(ref result) && ((Object)valuable).name.Contains(name, StringComparison.OrdinalIgnoreCase)) { return result; } } return null; } [Obsolete("prefabId is no longer supported", true)] public static void RegisterValuable(string prefabId, GameObject prefab) { RegisterValuable(prefab); } [Obsolete("prefabId is no longer supported", true)] public static void RegisterValuable(string prefabId, GameObject prefab, List<LevelValuables> presets) { RegisterValuable(prefab, presets); } [Obsolete("prefabId is no longer supported", true)] public static void RegisterValuable(string prefabId, GameObject prefab, List<string> presetNames) { RegisterValuable(prefab, presetNames); } } } namespace REPOLib.Extensions { public static class AudioSourceExtensions { public static void FixAudioMixerGroup(this AudioSource audioSource) { audioSource.FixAudioMixerGroup(((Component)audioSource).gameObject); } public static void FixAudioMixerGroup(this AudioSource audioSource, GameObject parentObject) { if ((Object)(object)audioSource == (Object)null) { return; } string text = ((!((Object)(object)parentObject == (Object)(object)((Component)audioSource).gameObject)) ? (((Object)parentObject).name + "/" + ((Object)((Component)audioSource).gameObject).name) : ((Object)((Component)audioSource).gameObject).name); if ((Object)(object)AudioManager.instance == (Object)null) { Logger.LogWarning("Failed to fix AudioMixerGroup on GameObject \"" + text + "\". AudioManager instance is null."); return; } if ((Object)(object)audioSource.outputAudioMixerGroup == (Object)null) { Logger.LogWarning("Failed to fix AudioMixerGroup on GameObject \"" + text + "\". No AudioMixerGroup is assigned."); return; } AudioMixer val = (AudioMixer)(((Object)audioSource.outputAudioMixerGroup.audioMixer).name switch { "Master" => AudioManager.instance.MasterMixer, "Music" => AudioManager.instance.MusicMasterGroup.audioMixer, "Sound" => AudioManager.instance.SoundMasterGroup.audioMixer, "Spectate" => AudioManager.instance.MicrophoneSpectateGroup.audioMixer, _ => AudioManager.instance.SoundMasterGroup.audioMixer, }); AudioMixerGroup[] array = val.FindMatchingGroups(((Object)audioSource.outputAudioMixerGroup).name); AudioMixerGroup val2; if (array.Length >= 1) { val2 = array[0]; } else { val = AudioManager.instance.SoundMasterGroup.audioMixer; val2 = val.FindMatchingGroups("Sound Effects")[0]; Logger.LogWarning("Could not find matching AudioMixerGroup for GameObject \"" + text + "\". Using default AudioMixerGroup \"" + ((Object)val).name + "/" + ((Object)val2).name + "\"", extended: true); } audioSource.outputAudioMixerGroup = val2; Logger.LogDebug("Fixed AudioMixerGroup on GameObject \"" + text + "\". AudioMixerGroup \"" + ((Object)val).name + "/" + ((Object)val2).name + "\""); } } public static class DictionaryExtensions { public static bool TryGetKey<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TValue value, [NotNullWhen(true)] out TKey? key) { foreach (KeyValuePair<TKey, TValue> item in dictionary) { if (object.Equals(item.Value, value)) { key = item.Key; return true; } } key = default(TKey); return false; } public static TKey? GetKeyOrDefault<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TValue value) { if (dictionary.TryGetKey(value, out TKey key)) { return key; } return default(TKey); } public static TKey? GetKeyOrDefault<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TValue value, TKey defaultKey) { if (dictionary.TryGetKey(value, out TKey key)) { return key; } return defaultKey; } public static bool ContainsKey<T>(this Dictionary<string, T> dictionary, string key, bool ignoreKeyCase) { if (!ignoreKeyCase) { return dictionary.ContainsKey(key); } foreach (KeyValuePair<string, T> item in dictionary) { if (string.Equals(item.Key, key, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } public static bool TryGetValue<T>(this Dictionary<string, T> dictionary, string key, [NotNullWhen(true)] out T? value, bool ignoreKeyCase) { if (!ignoreKeyCase) { return dictionary.TryGetValue(key, out value); } foreach (KeyValuePair<string, T> item in dictionary) { if (string.Equals(item.Key, key, StringComparison.OrdinalIgnoreCase)) { value = item.Value; return true; } } value = default(T); return false; } public static T? GetValueOrDefault<T>(this Dictionary<string, T> dictionary, string key, bool ignoreKeyCase) { if (dictionary.TryGetValue(key, out T value, ignoreKeyCase)) { return value; } return default(T); } public static T? GetValueOrDefault<T>(this Dictionary<string, T> dictionary, string key, T defaultValue, bool ignoreKeyCase) { if (dictionary.TryGetValue(key, out T value, ignoreKeyCase)) { return value; } return defaultValue; } } public static class EnemyDirectorExtensions { public static bool HasEnemy(this EnemyDirector enemyDirector, EnemySetup enemySetup) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)enemySetup == (Object)null || enemySetup.spawnObjects.Count == 0) { return false; } EnemyParent val = default(EnemyParent); foreach (GameObject spawnObject in enemySetup.spawnObjects) { if (spawnObject.TryGetComponent<EnemyParent>(ref val) && enemyDirector.TryGetList(val.difficulty, out List<EnemySetup> list)) { return list.Contains(enemySetup); } } return false; } internal static bool AddEnemy(this EnemyDirector enemyDirector, EnemySetup enemySetup) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)enemySetup == (Object)null) { return false; } EnemyParent val = default(EnemyParent); foreach (GameObject spawnObject in enemySetup.spawnObjects) { if (spawnObject.TryGetComponent<EnemyParent>(ref val) && enemyDirector.TryGetList(val.difficulty, out List<EnemySetup> list) && !list.Contains(enemySetup)) { list.Add(enemySetup); return true; } } return false; } public static bool TryGetList(this EnemyDirector enemyDirector, Difficulty difficultyType, [NotNullWhen(true)] out List<EnemySetup>? list) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected I4, but got Unknown list = (int)difficultyType switch { 0 => enemyDirector.enemiesDifficulty1, 1 => enemyDirector.enemiesDifficulty2, 2 => enemyDirector.enemiesDifficulty3, _ => null, }; return list != null; } public static List<EnemySetup> GetEnemies(this EnemyDirector enemyDirector) { List<EnemySetup> enemiesDifficulty = enemyDirector.enemiesDifficulty1; List<EnemySetup> enemiesDifficulty2 = enemyDirector.enemiesDifficulty2; List<EnemySetup> enemiesDifficulty3 = enemyDirector.enemiesDifficulty3; List<EnemySetup> list = new List<EnemySetup>(enemiesDifficulty.Count + enemiesDifficulty2.Count + enemiesDifficulty3.Count); list.AddRange(enemiesDifficulty); list.AddRange(enemiesDifficulty2); list.AddRange(enemiesDifficulty3); return list; } public static bool TryGetEnemyByName(this EnemyDirector enemyDirector, string name, [NotNullWhen(true)] out EnemySetup? enemySetup) { enemySetup = enemyDirector.GetEnemyByName(name); return (Object)(object)enemySetup != (Object)null; } public static EnemySetup? GetEnemyByName(this EnemyDirector enemyDirector, string name) { string name2 = name; return ((IEnumerable<EnemySetup>)enemyDirector.GetEnemies()).FirstOrDefault((Func<EnemySetup, bool>)((EnemySetup x) => x.NameEquals(name2))); } public static bool TryGetEnemyThatContainsName(this EnemyDirector enemyDirector, string name, out EnemySetup enemySetup) { enemySetup = enemyDirector.GetEnemyThatContainsName(name); return (Object)(object)enemySetup != (Object)null; } public static EnemySetup GetEnemyThatContainsName(this EnemyDirector enemyDirector, string name) { string name2 = name; return ((IEnumerable<EnemySetup>)enemyDirector.GetEnemies()).FirstOrDefault((Func<EnemySetup, bool>)((EnemySetup x) => x.NameContains(name2))); } } public static class EnemySetupExtensions { public static List<GameObject> GetDistinctSpawnObjects(this EnemySetup enemySetup) { if ((Object)(object)enemySetup == (Object)null || enemySetup.spawnObjects == null) { return new List<GameObject>(); } return enemySetup.spawnObjects.Where((GameObject x) => (Object)(object)x != (Object)null).Distinct(new UnityObjectNameComparer<GameObject>()).ToList(); } public static List<GameObject> GetSortedSpawnObjects(this EnemySetup enemySetup) { if ((Object)(object)enemySetup == (Object)null || enemySetup.spawnObjects == null) { return new List<GameObject>(); } EnemyParent val = default(EnemyParent); return (from x in enemySetup.spawnObjects where (Object)(object)x != (Object)null orderby x.TryGetComponent<EnemyParent>(ref val) descending select x).ToList(); } public static GameObject? GetMainSpawnObject(this EnemySetup enemySetup) { EnemyParent? enemyParent = enemySetup.GetEnemyParent(); if (enemyParent == null) { return null; } return ((Component)enemyParent).gameObject; } public static EnemyParent? GetEnemyParent(this EnemySetup enemySetup) { EnemyParent result = default(EnemyParent); foreach (GameObject distinctSpawnObject in enemySetup.GetDistinctSpawnObjects()) { if (distinctSpawnObject.TryGetComponent<EnemyParent>(ref result)) { return result; } } return null; } public static bool TryGetEnemyParent(this EnemySetup enemySetup, [NotNullWhen(true)] out EnemyParent? enemyParent) { enemyParent = enemySetup.GetEnemyParent(); return (Object)(object)enemyParent != (Object)null; } public static bool AnySpawnObjectsNameEquals(this EnemySetup enemySetup, string name) { string name2 = name; if ((Object)(object)enemySetup == (Object)null) { return false; } return enemySetup.GetDistinctSpawnObjects().Any((GameObject x) => ((Object)x).name.Equals(name2, StringComparison.OrdinalIgnoreCase)); } public static bool AnySpawnObjectsNameEqualsThatIsNotTheSameObject(this EnemySetup enemySetup, GameObject gameObject) { GameObject gameObject2 = gameObject; if ((Object)(object)enemySetup == (Object)null || (Object)(object)gameObject2 == (Object)null) { return false; } return enemySetup.GetDistinctSpawnObjects().Any((GameObject x) => ((Object)x).name.Equals(((Object)gameObject2).name, StringComparison.OrdinalIgnoreCase) && (Object)(object)x != (Object)(object)gameObject2); } public static bool NameEquals(this EnemySetup enemySetup, string name) { if ((Object)(object)enemySetup == (Object)null) { return false; } if (((Object)enemySetup).name.EqualsAny(new <>z__ReadOnlyArray<string>(new string[2] { name, "Enemy - " + name }), StringComparison.OrdinalIgnoreCase)) { return true; } if (enemySetup.TryGetEnemyParent(out EnemyParent enemyParent)) { if (enemyParent.enemyName.Equals(name, StringComparison.OrdinalIgnoreCase)) { return true; } if (((Object)((Component)enemyParent).gameObject).name.EqualsAny(new <>z__ReadOnlyArray<string>(new string[2] { name, "Enemy - " + name }), StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } public static bool NameContains(this EnemySetup enemySetup, string name) { if ((Object)(object)enemySetup == (Object)null) { return false; } if (((Object)enemySetup).name.Contains(name, StringComparison.OrdinalIgnoreCase)) { return true; } if (enemySetup.TryGetEnemyParent(out EnemyParent enemyParent)) { if (enemyParent.enemyName.Contains(name, StringComparison.OrdinalIgnoreCase)) { return true; } if (((Object)((Component)enemyParent).gameObject).name.Contains(name, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } } public static class GameObjectExtensions { public static void FixAudioMixerGroups(this GameObject gameObject) { if ((Object)(object)gameObject == (Object)null) { return; } if ((Object)(object)AudioManager.instance == (Object)null) { Logger.LogWarning("Failed to fix audio mixer groups on GameObject \"" + ((Object)gameObject).name + "\". AudioManager instance is null."); return; } AudioSource[] componentsInChildren = gameObject.GetComponentsInChildren<AudioSource>(); foreach (AudioSource audioSource in componentsInChildren) { audioSource.FixAudioMixerGroup(gameObject); } } } internal static class ItemExtensions { public static bool NameEquals(this Item item, string name) { if ((Object)(object)item == (Object)null) { return false; } if (((Object)item).name.EqualsAny(new <>z__ReadOnlyArray<string>(new string[2] { name, "Item " + name }), StringComparison.OrdinalIgnoreCase)) { return true; } if (item.itemAssetName.EqualsAny(new <>z__ReadOnlyArray<string>(new string[2] { name, "Item " + name }), StringComparison.OrdinalIgnoreCase)) { return true; } if (item.itemName.Equals(name, StringComparison.OrdinalIgnoreCase)) { return true; } return false; } public static bool NameContains(this Item item, string name) { if ((Object)(object)item == (Object)null) { return false; } if (((Object)item).name.Contains(name, StringComparison.OrdinalIgnoreCase)) { return true; } if (item.itemAssetName.Contains(name, StringComparison.OrdinalIgnoreCase)) { return true; } if (item.itemName.Contains(name, StringComparison.OrdinalIgnoreCase)) { return true; } return false; } } public static class LevelValuablesExtensions { public static bool HasValuable(this LevelValuables levelValuables, GameObject prefab) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) ValuableObject val = default(ValuableObject); if (!prefab.TryGetComponent<ValuableObject>(ref val)) { return false; } if (!levelValuables.TryGetList(val.volumeType, out List<GameObject> list)) { return false; } return list.Contains(prefab); } internal static bool AddValuable(this LevelValuables levelValuables, GameObject prefab) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) ValuableObject val = default(ValuableObject); if (!prefab.TryGetComponent<ValuableObject>(ref val)) { return false; } if (!levelValuables.TryGetList(val.volumeType, out List<GameObject> list)) { return false; } if (list.Contains(prefab)) { return false; } list.Add(prefab); return true; } public static bool TryGetList(this LevelValuables levelValuables, Type volumeType, [NotNullWhen(true)] out List<GameObject>? list) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected I4, but got Unknown list = (int)volumeType switch { 0 => levelValuables.tiny, 1 => levelValuables.small, 2 => levelValuables.medium, 3 => levelValuables.big, 4 => levelValuables.wide, 5 => levelValuables.tall, 6 => levelValuables.veryTall, _ => null, }; return list != null; } public static bool TryGetCombinedList(this LevelValuables levelValuables, out List<GameObject> list) { List<List<GameObject>> source = new List<List<GameObject>> { levelValuables.tiny, levelValuables.small, levelValuables.medium, levelValuables.big, levelValuables.wide, levelValuables.tall, levelValuables.veryTall }; list = (from x in source.SelectMany((List<GameObject> valuables) => valuables) where (Object)(object)x != (Object)null select x).Distinct().ToList(); return list != null; } public static List<GameObject> GetCombinedList(this LevelValuables levelValuables) { if (levelValuables.TryGetCombinedList(out List<GameObject> list)) { return list; } return new List<GameObject>(); } } internal static class ReflectionExtensions { public static IEnumerable<MethodInfo> SafeGetMethods(this Type type) { try { return type.GetMethods(); } catch { return Array.Empty<MethodInfo>(); } } public static T? SafeGetCustomAttribute<T>(this MethodInfo method) where T : Attribute { try { return method.GetCustomAttribute<T>(); } catch { return null; } } public static bool HasCustomAttribute<T>(this MethodInfo method) where T : Attribute { try { return method.GetCustomAttribute<T>() != null; } catch { return false; } } } public static class StatsManagerExtensions { public static bool HasItem(this StatsManager statsManager, Item item) { if ((Object)(object)item == (Object)null) { return false; } return statsManager.itemDictionary.ContainsKey(item.itemAssetName); } internal static bool AddItem(this StatsManager statsManager, Item item) { if (!statsManager.itemDictionary.ContainsKey(item.itemAssetName)) { statsManager.itemDictionary.Add(item.itemAssetName, item); } foreach (Dictionary<string, int> item2 in statsManager.AllDictionariesWithPrefix("item")) { item2[item.itemAssetName] = 0; } return true; } public static List<Item> GetItems(this StatsManager statsManager) { return statsManager.itemDictionary.Values.ToList(); } public static bool TryGetItemByName(this StatsManager statsManager, string name, out Item item) { item = statsManager.GetItemByName(name); return (Object)(object)item != (Object)null; } public static Item GetItemByName(this StatsManager statsManager, string name) { string name2 = name; return ((IEnumerable<Item>)statsManager.GetItems()).FirstOrDefault((Func<Item, bool>)((Item x) => x.NameEquals(name2))); } public static bool TryGetItemThatContainsName(this StatsManager statsManager, string name, out Item item) { item = statsManager.GetItemThatContainsName(name); return (Object)(object)item != (Object)null; } public static Item GetItemThatContainsName(this StatsManager statsManager, string name) { string name2 = name; return ((IEnumerable<Item>)statsManager.GetItems()).FirstOrDefault((Func<Item, bool>)((Item x) => x.NameContains(name2))); } } public static class StringExtensions { public static bool EqualsAny(this string value, IReadOnlyCollection<string> inputs, StringComparison comparisonType = StringComparison.Ordinal) { if (value == null || inputs == null) { return false; } return inputs.Contains<string>(value, StringComparer.FromComparison(comparisonType)); } } } namespace REPOLib.Commands { [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)] public class CommandExecutionAttribute : Attribute { public bool RequiresDeveloperMode { get; private set; } public bool EnabledByDefault { get; private set; } public string Name { get; private set; } public string Description { get; private set; } public CommandExecutionAttribute(string? name = null, string? description = null, bool enabledByDefault = true, bool requiresDeveloperMode = false) { RequiresDeveloperMode = requiresDeveloperMode; EnabledByDefault = enabledByDefault; Name = name ?? ""; Description = description ?? ""; } } [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)] public class CommandInitializerAttribute : Attribute { } [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = true)] public class CommandAliasAttribute : Attribute { public string Alias { get; private set; } public CommandAliasAttribute(string alias) { Alias = alias; } } internal static class CommandManager { private static List<MethodInfo> _commandExecutionMethodCache = new List<MethodInfo>(); public static Dictionary<string, MethodInfo> CommandExecutionMethods { get; private set; } = new Dictionary<string, MethodInfo>(); public static List<MethodInfo> CommandInitializerMethods { get; private set; } = new List<MethodInfo>(); public static Dictionary<string, bool> CommandsEnabled { get; private set; } = new Dictionary<string, bool>(); public static void Initialize() { Logger.LogInfo("CommandManager initializing.", extended: true); CommandInitializerMethods = (from method in AccessTools.AllTypes().SelectMany((Type type) => type.SafeGetMethods()) where method.HasCustomAttribute<CommandInitializerAttribute>() select method).ToList(); foreach (MethodInfo commandInitializerMethod in CommandInitializerMethods) { try { Logger.LogDebug($"Initializing command initializer on method {commandInitializerMethod.DeclaringType}.{commandInitializerMethod.Name}"); if (!commandInitializerMethod.IsStatic) { Logger.LogWarning($"Command initializer {commandInitializerMethod.DeclaringType}.{commandInitializerMethod.Name} is not static!"); } commandInitializerMethod.Invoke(null, null); } catch (Exception arg) { Logger.LogError($"Failed to initialize command: {arg}"); } } FindAllCommandMethods(); foreach (KeyValuePair<string, MethodInfo> commandExecutionMethod in CommandExecutionMethods) { if (!commandExecutionMethod.Value.IsStatic) { Logger.LogWarning("Command execution method for command \"" + commandExecutionMethod.Key + "\" is not static!"); } } BindConfigs(); Logger.LogInfo("Finished initializing custom commands."); } public static void FindAllCommandMethods() { _commandExecutionMethodCache = (from method in AccessTools.AllTypes().SelectMany((Type type) => type.SafeGetMethods()) where method.HasCustomAttribute<CommandExecutionAttribute>() select method).ToList(); foreach (MethodInfo item in _commandExecutionMethodCache) { ParameterInfo[] parameters = item.GetParameters(); if (parameters.Length > 1) { Logger.LogError("Command \"" + item.GetCustomAttribute<CommandExecutionAttribute>().Name + "\" execution method \"" + item.Name + "\" has too many parameters! Should only have 1 string parameter or none."); break; } if (parameters.Length == 1 && parameters[0].ParameterType != typeof(string)) { Logger.LogError("Command \"" + item.GetCustomAttribute<CommandExecutionAttribute>().Name + "\" execution method \"" + item.Name + "\" has parameter of the wrong type! Should be string."); break; } IEnumerable<CommandAliasAttribute> customAttributes = item.GetCustomAttributes<CommandAliasAttribute>(); bool flag = false; if (customAttributes == null || customAttributes.Count() == 0) { Logger.LogWarning("Command " + item.Name + " has no alias attributes!"); continue; } foreach (CommandAliasAttribute item2 in customAttributes) { if (CommandExecutionMethods.TryAdd(item2.Alias, item)) { Logger.LogDebug($"Registered command alias \"{item2.Alias}\" for method \"{item.DeclaringType}.{item.Name}\"."); flag = true; } } if (!flag) { Logger.LogWarning("Failed to add any command aliases for method \"" + item.Name + "\"."); } } } public static void BindConfigs() { foreach (MethodInfo item in _commandExecutionMethodCache) { CommandExecutionAttribute customAttribute = item.GetCustomAttribute<CommandExecutionAttribute>(); BepInPlugin customAttribute2 = ((MemberInfo)(from type in AccessTools.GetTypesFromAssembly(item.Module.Assembly) where ((MemberInfo)type).GetCustomAttribute<BepInPlugin>() != null select type).ToList()[0]).GetCustomAttribute<BepInPlugin>(); string text = ((customAttribute2 != null) ? customAttribute2.GUID : null) ?? "Unknown"; string text2 = item.DeclaringType.ToString() ?? "Unknown"; List<string> list = new List<string>(); foreach (CommandAliasAttribute customAttribute3 in item.GetCustomAttributes<CommandAliasAttribute>()) {