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 LethalContentFilter v1.0.0
LethalContentFilter.dll
Decompiled 8 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("LethalContentFilter")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("LethalContentFilter")] [assembly: AssemblyTitle("LethalContentFilter")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.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.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace LethalContentFilter { [HarmonyPatch(typeof(RoundManager))] internal class RoundManagerPatches { private static IntWithRarity[] _originalDungeonFlows; [HarmonyPatch("GenerateNewFloor")] [HarmonyPrefix] [HarmonyPriority(600)] private static void FilterInteriors_Prefix(RoundManager __instance) { HashSet<string> excludedSet = Plugin.GetExcludedSet(Plugin.ExcludedInteriors); if (excludedSet.Count == 0) { return; } excludedSet = Plugin.GetNormalizedInteriorNames(excludedSet); SelectableLevel currentLevel = __instance.currentLevel; if (currentLevel?.dungeonFlowTypes == null || currentLevel.dungeonFlowTypes.Length == 0) { Plugin.Log.LogDebug((object)"No dungeon flow types found for current level."); return; } _originalDungeonFlows = currentLevel.dungeonFlowTypes.ToArray(); List<IntWithRarity> list = new List<IntWithRarity>(); for (int i = 0; i < currentLevel.dungeonFlowTypes.Length; i++) { IntWithRarity val = currentLevel.dungeonFlowTypes[i]; string dungeonFlowName = GetDungeonFlowName(val.id); if (string.IsNullOrEmpty(dungeonFlowName)) { list.Add(val); Plugin.Log.LogDebug((object)$"Could not determine name for dungeon flow id {val.id}, keeping it."); } else if (excludedSet.Contains(dungeonFlowName.ToLowerInvariant())) { Plugin.Log.LogInfo((object)$"Filtering out interior: {dungeonFlowName} (id: {val.id})"); } else { list.Add(val); } } if (list.Count > 0) { currentLevel.dungeonFlowTypes = list.ToArray(); Plugin.Log.LogDebug((object)$"Interior pool: {list.Count}/{_originalDungeonFlows.Length} options remaining."); } else { Plugin.Log.LogWarning((object)"All interiors were filtered! Keeping original list to prevent crash."); } } [HarmonyPatch("GenerateNewFloor")] [HarmonyPostfix] private static void FilterInteriors_Postfix(RoundManager __instance) { if (_originalDungeonFlows != null && (Object)(object)__instance.currentLevel != (Object)null) { __instance.currentLevel.dungeonFlowTypes = _originalDungeonFlows; _originalDungeonFlows = null; } } private static string GetDungeonFlowName(int flowId) { return flowId switch { 0 => "Level1Flow", 1 => "HauntedMansionFlow", 2 => "Level3Flow", _ => $"UnknownFlow_{flowId}", }; } } [HarmonyPatch(typeof(StartOfRound))] internal class StartOfRoundPatches { [HarmonyPatch("SetPlanetsWeather")] [HarmonyPostfix] private static void FilterWeather_Postfix(StartOfRound __instance) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) HashSet<string> excludedSet = Plugin.GetExcludedSet(Plugin.ExcludedWeather); if (excludedSet.Count == 0) { return; } SelectableLevel[] levels = __instance.levels; foreach (SelectableLevel val in levels) { if (!((Object)(object)val == (Object)null)) { string item = ((object)(LevelWeatherType)(ref val.currentWeather)).ToString().ToLowerInvariant(); if (excludedSet.Contains(item)) { Plugin.Log.LogInfo((object)$"Changing weather on {val.PlanetName} from {val.currentWeather} to None"); val.currentWeather = (LevelWeatherType)(-1); } } } } [HarmonyPatch("ChangeLevelServerRpc")] [HarmonyPrefix] private static bool PreventExcludedMoonTravel_Prefix(int levelID, StartOfRound __instance) { HashSet<string> excludedSet = Plugin.GetExcludedSet(Plugin.ExcludedMoons); if (excludedSet.Count == 0) { return true; } if (levelID < 0 || levelID >= __instance.levels.Length) { return true; } SelectableLevel val = __instance.levels[levelID]; if ((Object)(object)val == (Object)null) { return true; } string item = NormalizeMoonName(val.PlanetName); if (excludedSet.Contains(item)) { Plugin.Log.LogInfo((object)("Blocked travel to excluded moon: " + val.PlanetName)); if ((Object)(object)HUDManager.Instance != (Object)null) { HUDManager.Instance.DisplayTip("Moon Restricted", val.PlanetName + " has been disabled by Lethal Content Filter.", true, false, "LC_Tip1"); } return false; } return true; } private static string NormalizeMoonName(string planetName) { if (string.IsNullOrEmpty(planetName)) { return ""; } return Regex.Replace(planetName, "^\\d+\\s*", "").Trim().ToLowerInvariant(); } } [BepInPlugin("com.yourname.lethalcontentfilter", "Lethal Content Filter", "1.0.0")] public class Plugin : BaseUnityPlugin { public const string ModGUID = "com.yourname.lethalcontentfilter"; public const string ModName = "Lethal Content Filter"; public const string ModVersion = "1.0.0"; internal static ManualLogSource Log; private readonly Harmony _harmony = new Harmony("com.yourname.lethalcontentfilter"); public static ConfigEntry<string> ExcludedInteriors; public static ConfigEntry<string> ExcludedMoons; public static ConfigEntry<string> ExcludedWeather; public static Plugin Instance { get; private set; } private void Awake() { Instance = this; Log = ((BaseUnityPlugin)this).Logger; InitConfig(); _harmony.PatchAll(typeof(RoundManagerPatches)); _harmony.PatchAll(typeof(StartOfRoundPatches)); Log.LogInfo((object)"Lethal Content Filter v1.0.0 loaded!"); LogCurrentConfig(); } private void InitConfig() { ExcludedInteriors = ((BaseUnityPlugin)this).Config.Bind<string>("Filtering", "ExcludedInteriors", "Mineshaft", "Comma-separated list of interior names to exclude.\nValid vanilla names: Mineshaft, Level3Flow, Manor, HauntedMansionFlow, Factory, Level1Flow\nFor modded interiors, use their DungeonFlow name."); ExcludedMoons = ((BaseUnityPlugin)this).Config.Bind<string>("Filtering", "ExcludedMoons", "", "Comma-separated list of moon names to exclude (e.g., 'Dine,Rend,Titan').\nUse the moon name without the number prefix."); ExcludedWeather = ((BaseUnityPlugin)this).Config.Bind<string>("Filtering", "ExcludedWeather", "", "Comma-separated list of weather types to exclude.\nValid types: None, Rainy, Stormy, Foggy, Flooded, Eclipsed, DustClouds"); } private void LogCurrentConfig() { HashSet<string> excludedSet = GetExcludedSet(ExcludedInteriors); HashSet<string> excludedSet2 = GetExcludedSet(ExcludedMoons); HashSet<string> excludedSet3 = GetExcludedSet(ExcludedWeather); if (excludedSet.Count > 0) { Log.LogInfo((object)("Excluded interiors: " + string.Join(", ", excludedSet))); } if (excludedSet2.Count > 0) { Log.LogInfo((object)("Excluded moons: " + string.Join(", ", excludedSet2))); } if (excludedSet3.Count > 0) { Log.LogInfo((object)("Excluded weather: " + string.Join(", ", excludedSet3))); } } public static HashSet<string> GetExcludedSet(ConfigEntry<string> config) { if (string.IsNullOrWhiteSpace(config.Value)) { return new HashSet<string>(); } return (from s in config.Value.Split(',') select s.Trim().ToLowerInvariant() into s where !string.IsNullOrEmpty(s) select s).ToHashSet(); } public static HashSet<string> GetNormalizedInteriorNames(HashSet<string> userInput) { HashSet<string> hashSet = new HashSet<string>(); foreach (string item in userInput) { hashSet.Add(item); switch (item) { case "cave": case "mine": case "mineshaft": hashSet.Add("level3flow"); hashSet.Add("mineshaft"); break; case "mansion": case "manor": hashSet.Add("hauntedmansionflow"); hashSet.Add("manor"); break; case "factory": case "facility": hashSet.Add("level1flow"); hashSet.Add("factory"); break; } } return hashSet; } } public static class MyPluginInfo { public const string PLUGIN_GUID = "LethalContentFilter"; public const string PLUGIN_NAME = "LethalContentFilter"; public const string PLUGIN_VERSION = "1.0.0"; } }