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 HostInteriorSelector v0.1.3
plugins/HostInteriorSelector.dll
Decompiled an hour agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using Unity.Netcode; using UnityEngine; using UnityEngine.Events; 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("HostInteriorSelector")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.3.0")] [assembly: AssemblyInformationalVersion("0.1.3")] [assembly: AssemblyProduct("HostInteriorSelector")] [assembly: AssemblyTitle("HostInteriorSelector")] [assembly: AssemblyVersion("0.1.3.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace HostInteriorSelector { [HarmonyPatch(typeof(RoundManager), "GenerateNewFloor")] internal static class InteriorFilterPatch { private enum VanillaInterior { Unknown, Factory, Mansion, Mineshaft } internal sealed class FilterState { internal SelectableLevel? Level; internal IntWithRarity[]? Original; } [HarmonyPrefix] private static void Prefix(RoundManager __instance, out FilterState __state) { __state = new FilterState(); try { if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsHost || (Plugin.FactoryEnabled.Value && Plugin.MansionEnabled.Value && Plugin.MineshaftEnabled.Value)) { return; } SelectableLevel currentLevel = __instance.currentLevel; IntWithRarity[] array = currentLevel?.dungeonFlowTypes; if ((Object)(object)currentLevel == (Object)null || array == null || array.Length == 0) { Plugin.Log.LogWarning((object)"Interior filtering skipped: the current level has no dungeon-flow choices."); return; } Dictionary<int, VanillaInterior> discovered = new Dictionary<int, VanillaInterior>(); for (int i = 0; i < __instance.dungeonFlowTypes.Length; i++) { string displayName; VanillaInterior vanillaInterior = Identify(__instance.dungeonFlowTypes[i], i, out displayName); discovered[i] = vanillaInterior; Plugin.Log.LogInfo((object)$"Interior definition [{i}] '{displayName}' classified as {vanillaInterior}."); } IntWithRarity[] array2 = array.Where((IntWithRarity entry) => IsAllowed(entry, discovered)).ToArray(); if (array2.Length == array.Length) { Plugin.Log.LogInfo((object)"Host interior settings did not remove any choices for this level."); return; } if (array2.Length == 0) { array2 = CreateFallbackChoices(discovered); if (array2.Length == 0) { Plugin.Log.LogWarning((object)"Interior settings left no valid choice and no enabled vanilla definition could be found; using the game's unmodified list for safe generation."); return; } Plugin.Log.LogInfo((object)$"This moon offered none of the enabled vanilla interiors; supplied {array2.Length} enabled global choice(s) to generation."); } __state.Level = currentLevel; __state.Original = array; currentLevel.dungeonFlowTypes = array2; Plugin.Log.LogInfo((object)$"Host filtered interior choices from {array.Length} to {array2.Length}; unknown/custom interiors were preserved."); } catch (Exception arg) { Restore(__state); Plugin.Log.LogError((object)$"Interior filtering failed safely; vanilla selection will be used. {arg}"); } } [HarmonyFinalizer] private static Exception? Finalizer(Exception? __exception, RoundManager __instance, FilterState __state) { if (__state.Original != null && __instance.currentDungeonType >= 0 && __instance.currentDungeonType < __instance.dungeonFlowTypes.Length) { string displayName; VanillaInterior vanillaInterior = Identify(__instance.dungeonFlowTypes[__instance.currentDungeonType], __instance.currentDungeonType, out displayName); Plugin.Log.LogInfo((object)$"Host selected interior [{__instance.currentDungeonType}] '{displayName}' classified as {vanillaInterior}."); if (!IsKindEnabled(vanillaInterior)) { Plugin.Log.LogWarning((object)$"The game selected disabled interior {vanillaInterior}; please report the surrounding Interior Selector log lines."); } } Restore(__state); return __exception; } private static bool IsAllowed(IntWithRarity entry, Dictionary<int, VanillaInterior> discovered) { if (!discovered.TryGetValue(entry.id, out var value)) { return true; } return IsKindEnabled(value); } private static IntWithRarity[] CreateFallbackChoices(Dictionary<int, VanillaInterior> discovered) { return (from pair in discovered where pair.Value != VanillaInterior.Unknown && IsKindEnabled(pair.Value) group pair by pair.Value).Select((Func<IGrouping<VanillaInterior, KeyValuePair<int, VanillaInterior>>, IntWithRarity>)((IGrouping<VanillaInterior, KeyValuePair<int, VanillaInterior>> group) => new IntWithRarity(group.First().Key, 1, (LevelAmbienceLibrary)null))).ToArray(); } private static bool IsKindEnabled(VanillaInterior kind) { return kind switch { VanillaInterior.Factory => Plugin.FactoryEnabled.Value, VanillaInterior.Mansion => Plugin.MansionEnabled.Value, VanillaInterior.Mineshaft => Plugin.MineshaftEnabled.Value, _ => true, }; } private static VanillaInterior Identify(IndoorMapType map, int index, out string displayName) { object obj = ((object)map)?.GetType().GetField("dungeonFlow", BindingFlags.Instance | BindingFlags.Public)?.GetValue(map); Object val = (Object)((obj is Object) ? obj : null); displayName = ((val != null) ? val.name : (obj?.ToString() ?? "<null>")); string text = new string(displayName.Where(char.IsLetterOrDigit).Select(char.ToLowerInvariant).ToArray()); if (text.Contains("mine") || text.Contains("cave")) { return VanillaInterior.Mineshaft; } if (text.Contains("mansion") || text.Contains("manor")) { return VanillaInterior.Mansion; } if (text.Contains("factory") || text.Contains("facility")) { return VanillaInterior.Factory; } if (text.StartsWith("level1flow", StringComparison.Ordinal)) { return VanillaInterior.Factory; } if (text.StartsWith("level2flow", StringComparison.Ordinal)) { return VanillaInterior.Mansion; } if (text.StartsWith("level3flow", StringComparison.Ordinal) || text.StartsWith("level4flow", StringComparison.Ordinal)) { return VanillaInterior.Mineshaft; } switch (index) { case 0: case 2: case 3: return VanillaInterior.Factory; case 1: return VanillaInterior.Mansion; case 4: return VanillaInterior.Mineshaft; default: return VanillaInterior.Unknown; } } private static void Restore(FilterState? state) { if ((Object)(object)state?.Level != (Object)null && state.Original != null) { state.Level.dungeonFlowTypes = state.Original; state.Level = null; state.Original = null; } } } [HarmonyPatch(typeof(MenuManager), "Start")] internal static class MenuPatch { [HarmonyPostfix] private static void Postfix(MenuManager __instance) { if (!((Object)(object)__instance == (Object)null) && !__instance.isInitScene && !((Object)(object)((Component)__instance).GetComponent<InteriorSelectorMenu>() != (Object)null)) { Transform val = (((Object)(object)__instance.menuButtons != (Object)null) ? __instance.menuButtons.transform.parent : null); if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)"Main-menu canvas was not found; Interior Selector UI was not created."); } else { ((Component)__instance).gameObject.AddComponent<InteriorSelectorMenu>().Build(val, __instance.versionNumberText); } } } } internal sealed class InteriorSelectorMenu : MonoBehaviour { private GameObject _panel; private Toggle _factory; private Toggle _mansion; private Toggle _mineshaft; private TextMeshProUGUI _validationText; private TMP_FontAsset? _font; internal void Build(Transform menuRoot, TextMeshProUGUI fontSource) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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) //IL_0067: Expected O, but got Unknown //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: 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_012e: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Expected O, but got Unknown _font = (((Object)(object)fontSource != (Object)null) ? ((TMP_Text)fontSource).font : null); ((UnityEvent)CreateButton(menuRoot, "Interior Selector", new Vector2(0.5f, 0f), new Vector2(0f, 72f), new Vector2(260f, 48f)).onClick).AddListener(new UnityAction(Open)); _panel = CreateRect("InteriorSelectorPanel", menuRoot, new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(460f, 410f)); _panel.transform.SetAsLastSibling(); ((Graphic)_panel.AddComponent<Image>()).color = new Color(0.035f, 0.055f, 0.045f, 0.97f); CreateText(_panel.transform, "Interior Selector", new Vector2(0f, 150f), new Vector2(400f, 55f), 30f, (TextAlignmentOptions)514); CreateText(_panel.transform, "Used only when you host", new Vector2(0f, 112f), new Vector2(400f, 35f), 17f, (TextAlignmentOptions)514); _factory = CreateToggle(_panel.transform, "Factory", 55f); _mansion = CreateToggle(_panel.transform, "Mansion", 0f); _mineshaft = CreateToggle(_panel.transform, "Mineshaft", -55f); _validationText = CreateText(_panel.transform, string.Empty, new Vector2(0f, -98f), new Vector2(400f, 32f), 16f, (TextAlignmentOptions)514); ((Graphic)_validationText).color = new Color(1f, 0.45f, 0.4f, 1f); ((UnityEvent)CreateButton(_panel.transform, "Save & Close", new Vector2(0.5f, 0.5f), new Vector2(0f, -140f), new Vector2(220f, 48f)).onClick).AddListener(new UnityAction(SaveAndClose)); _panel.SetActive(false); Plugin.Log.LogInfo((object)"Interior Selector button added to the current main menu."); } private void Open() { _factory.isOn = Plugin.FactoryEnabled.Value; _mansion.isOn = Plugin.MansionEnabled.Value; _mineshaft.isOn = Plugin.MineshaftEnabled.Value; ((TMP_Text)_validationText).text = string.Empty; _panel.SetActive(true); } private void SaveAndClose() { if (!_factory.isOn && !_mansion.isOn && !_mineshaft.isOn) { ((TMP_Text)_validationText).text = "Select at least one interior."; Plugin.Log.LogWarning((object)"Interior settings were not saved because every option was disabled."); return; } Plugin.FactoryEnabled.Value = _factory.isOn; Plugin.MansionEnabled.Value = _mansion.isOn; Plugin.MineshaftEnabled.Value = _mineshaft.isOn; Plugin.Settings.Save(); _panel.SetActive(false); Plugin.Log.LogInfo((object)$"Saved interior settings: Factory={_factory.isOn}, Mansion={_mansion.isOn}, Mineshaft={_mineshaft.isOn}."); } private Toggle CreateToggle(Transform parent, string label, float y) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) GameObject val = CreateRect(label + "Toggle", parent, new Vector2(0.5f, 0.5f), new Vector2(0f, y), new Vector2(310f, 44f)); Toggle obj = val.AddComponent<Toggle>(); GameObject val2 = CreateRect("Box", val.transform, new Vector2(0f, 0.5f), new Vector2(22f, 0f), new Vector2(32f, 32f)); Image val3 = val2.AddComponent<Image>(); ((Graphic)val3).color = new Color(0.16f, 0.2f, 0.17f, 1f); Image val4 = CreateRect("Checkmark", val2.transform, new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(22f, 22f)).AddComponent<Image>(); ((Graphic)val4).color = new Color(0.42f, 0.85f, 0.5f, 1f); ((Selectable)obj).targetGraphic = (Graphic)(object)val3; obj.graphic = (Graphic)(object)val4; CreateText(val.transform, label, new Vector2(48f, 0f), new Vector2(250f, 44f), 23f, (TextAlignmentOptions)513); return obj; } private Button CreateButton(Transform parent, string label, Vector2 anchor, Vector2 position, Vector2 size) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0081: 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) //IL_0094: Unknown result type (might be due to invalid IL or missing references) GameObject val = CreateRect(label.Replace(" ", "") + "Button", parent, anchor, position, size); Image val2 = val.AddComponent<Image>(); ((Graphic)val2).color = new Color(0.12f, 0.24f, 0.16f, 0.98f); Button obj = val.AddComponent<Button>(); ((Selectable)obj).targetGraphic = (Graphic)(object)val2; ColorBlock colors = ((Selectable)obj).colors; ((ColorBlock)(ref colors)).highlightedColor = new Color(0.2f, 0.42f, 0.25f, 1f); ((Selectable)obj).colors = colors; CreateText(val.transform, label, Vector2.zero, size, 21f, (TextAlignmentOptions)514); return obj; } private TextMeshProUGUI CreateText(Transform parent, string value, Vector2 position, Vector2 size, float fontSize, TextAlignmentOptions alignment) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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_0050: Unknown result type (might be due to invalid IL or missing references) TextMeshProUGUI val = CreateRect(value.Replace(" ", "") + "Text", parent, new Vector2(0.5f, 0.5f), position, size).AddComponent<TextMeshProUGUI>(); ((TMP_Text)val).text = value; ((TMP_Text)val).fontSize = fontSize; ((TMP_Text)val).alignment = alignment; ((Graphic)val).color = Color.white; ((Graphic)val).raycastTarget = false; if ((Object)(object)_font != (Object)null) { ((TMP_Text)val).font = _font; } return val; } private static GameObject CreateRect(string name, Transform parent, Vector2 anchor, Vector2 position, Vector2 size) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) }); RectTransform val2 = (RectTransform)val.transform; ((Transform)val2).SetParent(parent, false); val2.anchorMin = anchor; val2.anchorMax = anchor; val2.pivot = new Vector2(0.5f, 0.5f); val2.anchoredPosition = position; val2.sizeDelta = size; return val; } } [BepInPlugin("com.hostinteriorselector.mod", "Host Interior Selector", "0.1.3")] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "com.hostinteriorselector.mod"; public const string PluginName = "Host Interior Selector"; public const string PluginVersion = "0.1.3"; private Harmony? _harmony; internal static ManualLogSource Log { get; private set; } internal static ConfigEntry<bool> FactoryEnabled { get; private set; } internal static ConfigEntry<bool> MansionEnabled { get; private set; } internal static ConfigEntry<bool> MineshaftEnabled { get; private set; } internal static ConfigFile Settings { get; private set; } private void Awake() { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Settings = ((BaseUnityPlugin)this).Config; FactoryEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Interiors", "Factory", true, "Allow the vanilla Factory interior when you are host."); MansionEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Interiors", "Mansion", true, "Allow the vanilla Mansion interior when you are host."); MineshaftEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Interiors", "Mineshaft", true, "Allow the vanilla Mineshaft interior when you are host."); _harmony = new Harmony("com.hostinteriorselector.mod"); _harmony.PatchAll(); Log.LogInfo((object)"Host Interior Selector 0.1.3 loaded. Interior filtering is host-only; local menu settings never affect a remote host."); } } }