using 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";
}
}