using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("NoEnforcerFootprints")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+ea1649261c0fab9ed9de9ec6167599568b30696a")]
[assembly: AssemblyProduct("NoEnforcerFootprints")]
[assembly: AssemblyTitle("NoEnforcerFootprints")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[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 NoEnforcerFootprints
{
internal static class EnforcerLookup
{
private static readonly Dictionary<int, bool> Cache = new Dictionary<int, bool>();
internal static bool IsEnforcer(Human human)
{
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Expected O, but got Unknown
if ((Object)(object)human == (Object)null)
{
return false;
}
try
{
if (!((Actor)human).isEnforcer)
{
return false;
}
return !IsExemptMurdererID(human.humanID);
}
catch (Exception ex)
{
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(47, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[NoEnforcerFootprints] isEnforcer check threw: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
}
logger.LogWarning(val);
return false;
}
}
internal static bool IsEnforcerID(int humanID)
{
//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
//IL_00bf: Expected O, but got Unknown
if (Cache.TryGetValue(humanID, out var value))
{
if (!value)
{
return false;
}
return !IsExemptMurdererID(humanID);
}
CityData instance = CityData.Instance;
if ((Object)(object)instance == (Object)null)
{
return false;
}
try
{
Human val = default(Human);
if (!instance.GetHuman(humanID, ref val, true) || (Object)(object)val == (Object)null)
{
return false;
}
bool isEnforcer = ((Actor)val).isEnforcer;
Cache[humanID] = isEnforcer;
if (!isEnforcer)
{
return false;
}
return !IsExemptMurdererID(humanID);
}
catch (Exception ex)
{
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(41, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[NoEnforcerFootprints] GetHuman(");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(humanID);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(") threw: ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
}
logger.LogWarning(val2);
return false;
}
}
internal static bool IsExemptMurdererID(int humanID)
{
if (!Plugin.ExemptCurrentMurderer.Value)
{
return false;
}
try
{
MurderController instance = MurderController.Instance;
Human val = ((instance != null) ? instance.currentMurderer : null);
return (Object)(object)val != (Object)null && val.humanID == humanID;
}
catch
{
return false;
}
}
}
[HarmonyPatch(typeof(NewAIController), "SimulateFootprints")]
internal static class NewAIController_SimulateFootprints_Patch
{
internal static int Seen;
internal static int Blocked;
internal static int UnreadableHuman;
[HarmonyPrefix]
private static bool Prefix(NewAIController __instance)
{
//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
//IL_00cd: Expected O, but got Unknown
if (!Plugin.Enabled.Value || !Plugin.BlockNewFootprints.Value)
{
return true;
}
if ((Object)(object)__instance == (Object)null)
{
return true;
}
Seen++;
Human human;
try
{
human = __instance.human;
}
catch
{
UnreadableHuman++;
return true;
}
if ((Object)(object)human == (Object)null)
{
UnreadableHuman++;
return true;
}
if (!EnforcerLookup.IsEnforcer(human))
{
return true;
}
Blocked++;
if (Plugin.VerboseLogging.Value)
{
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(64, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[NoEnforcerFootprints] Blocked footprint for enforcer ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(human.humanID);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" (total ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(Blocked);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(").");
}
logger.LogInfo(val);
}
return false;
}
}
[HarmonyPatch(typeof(NewRoom), "UpdateFootprints")]
internal static class NewRoom_UpdateFootprints_Patch
{
[HarmonyPrefix]
private static void Prefix(NewRoom __instance)
{
//IL_012a: Unknown result type (might be due to invalid IL or missing references)
//IL_0131: Expected O, but got Unknown
//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
//IL_00ca: Expected O, but got Unknown
if (!Plugin.Enabled.Value || !Plugin.PurgeExistingFootprints.Value || (Object)(object)__instance == (Object)null)
{
return;
}
GameplayController instance = GameplayController.Instance;
Dictionary<NewRoom, List<Footprint>> val = ((instance != null) ? instance.activeFootprints : null);
if (val == null)
{
return;
}
bool flag = default(bool);
try
{
List<Footprint> val2 = default(List<Footprint>);
if (!val.TryGetValue(__instance, ref val2) || val2 == null)
{
return;
}
int budget = Mathf.Max(1, Plugin.MaxRemovalsPerSweep.Value);
int num = FootprintPurger.ScanRange(val2, val2.Count - 1, 0, ref budget, null);
if (num > 0 && Plugin.VerboseLogging.Value)
{
ManualLogSource logger = Plugin.Logger;
BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(87, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("[NoEnforcerFootprints] Stripped ");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(num);
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" enforcer print(s) from room ");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(__instance.roomID);
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" during its decal rebuild.");
}
logger.LogInfo(val3);
}
}
catch (Exception ex)
{
ManualLogSource logger2 = Plugin.Logger;
BepInExWarningLogInterpolatedStringHandler val4 = new BepInExWarningLogInterpolatedStringHandler(52, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("[NoEnforcerFootprints] Room purge failed for room ");
((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<int>(__instance.roomID);
((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(": ");
((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<Exception>(ex);
}
logger2.LogWarning(val4);
}
}
}
[HarmonyPatch(typeof(CitizenBehaviour), "Update")]
internal static class CitizenBehaviour_Update_Patch
{
private static float nextTickTime;
[HarmonyPostfix]
private static void Postfix()
{
if (Plugin.Enabled.Value && Plugin.PurgeExistingFootprints.Value)
{
float time = Time.time;
if (!(time < nextTickTime))
{
nextTickTime = time + Mathf.Max(1f, Plugin.PurgeIntervalSeconds.Value);
FootprintPurger.Tick(time);
}
}
}
}
internal static class FootprintPurger
{
private const int MaxLeakIDsLogged = 8;
private static int fullPassCursor = -1;
private static bool fullPassArmed = true;
private static float fullPassRearmTime;
private static int fullPassIndex;
private static int fullPassRemoved;
private static int totalRemoved;
private static bool loggedIdle;
private static readonly Dictionary<int, int> TailLeakTally = new Dictionary<int, int>();
private static readonly HashSet<int> TouchedRooms = new HashSet<int>();
internal static int ScanRange(List<Footprint> list, int from, int to, ref int budget, Dictionary<int, int> tally, HashSet<int> touchedRoomIDs = null)
{
if (list == null || budget <= 0)
{
return 0;
}
int count = list.Count;
if (from > count - 1)
{
from = count - 1;
}
if (to < 0)
{
to = 0;
}
if (from < to)
{
return 0;
}
int num = 0;
for (int num2 = from; num2 >= to && budget > 0; num2--)
{
int hID;
int rID;
try
{
Footprint val = list[num2];
if (val == null)
{
continue;
}
hID = val.hID;
rID = val.rID;
goto IL_008c;
}
catch
{
}
continue;
IL_008c:
if (EnforcerLookup.IsEnforcerID(hID))
{
try
{
list.RemoveAt(num2);
}
catch
{
continue;
}
num++;
budget--;
touchedRoomIDs?.Add(rID);
if (tally != null)
{
tally.TryGetValue(hID, out var value);
tally[hID] = value + 1;
}
}
}
return num;
}
private static int RefreshRooms(GameplayController gc, HashSet<int> roomIDs, out int roomsRefreshed)
{
//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
//IL_00f0: Expected O, but got Unknown
roomsRefreshed = 0;
if (roomIDs == null || roomIDs.Count == 0)
{
return 0;
}
CityData instance = CityData.Instance;
Dictionary<NewRoom, List<Footprint>> val = ((gc != null) ? gc.activeFootprints : null);
if ((Object)(object)instance == (Object)null)
{
return 0;
}
int num = 0;
NewRoom val2 = default(NewRoom);
List<Footprint> val3 = default(List<Footprint>);
bool flag = default(bool);
foreach (int roomID in roomIDs)
{
try
{
if (instance.roomDictionary.TryGetValue(roomID, ref val2) && !((Object)(object)val2 == (Object)null))
{
if (val != null && val.TryGetValue(val2, ref val3) && val3 != null)
{
int budget = val3.Count;
num += ScanRange(val3, val3.Count - 1, 0, ref budget, null);
}
val2.QueueFootprintUpdate();
roomsRefreshed++;
}
}
catch (Exception ex)
{
ManualLogSource logger = Plugin.Logger;
BepInExWarningLogInterpolatedStringHandler val4 = new BepInExWarningLogInterpolatedStringHandler(48, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("[NoEnforcerFootprints] Failed refreshing room ");
((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<int>(roomID);
((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(": ");
((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(ex.Message);
}
logger.LogWarning(val4);
}
}
return num;
}
internal static void Tick(float now)
{
//IL_0214: Unknown result type (might be due to invalid IL or missing references)
//IL_021b: Expected O, but got Unknown
GameplayController instance = GameplayController.Instance;
if ((Object)(object)instance == (Object)null || (Object)(object)CityData.Instance == (Object)null)
{
return;
}
List<Footprint> footprintsList = instance.footprintsList;
if (footprintsList == null)
{
return;
}
int count = footprintsList.Count;
if (count == 0)
{
return;
}
if (!fullPassArmed && now >= fullPassRearmTime)
{
fullPassArmed = true;
fullPassCursor = -1;
}
int budget = Mathf.Max(1, Plugin.MaxRemovalsPerSweep.Value);
TailLeakTally.Clear();
TouchedRooms.Clear();
int num = Mathf.Clamp(Plugin.TailScanSize.Value, 0, count);
int num2 = ((num > 0) ? ScanRange(footprintsList, count - 1, count - num, ref budget, TailLeakTally, TouchedRooms) : 0);
int num3 = 0;
bool flag = false;
if (fullPassArmed)
{
if (fullPassCursor < 0)
{
fullPassCursor = footprintsList.Count - 1;
fullPassRemoved = 0;
}
int num4 = Mathf.Min(fullPassCursor, footprintsList.Count - 1);
int num5 = Mathf.Max(1, Plugin.FullPassSliceSize.Value);
int num6 = Mathf.Max(0, num4 - num5 + 1);
num3 = ScanRange(footprintsList, num4, num6, ref budget, null, TouchedRooms);
fullPassRemoved += num3;
fullPassCursor = num6 - 1;
if (fullPassCursor < 0)
{
flag = true;
}
}
int roomsRefreshed;
int roomRemoved = RefreshRooms(instance, TouchedRooms, out roomsRefreshed);
totalRemoved += num2 + num3;
if (num2 > 0)
{
ReportLeak(num2, roomRemoved, roomsRefreshed);
loggedIdle = false;
}
if (flag)
{
CompleteFullPass(now, footprintsList.Count);
loggedIdle = false;
}
if (num2 == 0 && num3 == 0 && !flag && !loggedIdle)
{
loggedIdle = true;
ManualLogSource logger = Plugin.Logger;
bool flag2 = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(124, 3, ref flag2);
if (flag2)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[NoEnforcerFootprints] Clean. World list ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(footprintsList.Count);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" print(s), no enforcer prints found. ");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Cumulative removed this session: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(totalRemoved);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(". ");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Full walk ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(fullPassArmed ? "armed" : "idle until re-arm");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
}
logger.LogInfo(val);
}
}
private static void ReportLeak(int tailRemoved, int roomRemoved, int roomsRefreshed)
{
//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
//IL_00be: Expected O, but got Unknown
StringBuilder stringBuilder = new StringBuilder();
int num = 0;
foreach (KeyValuePair<int, int> item in TailLeakTally)
{
if (num >= 8)
{
stringBuilder.Append(", ...");
break;
}
if (num > 0)
{
stringBuilder.Append(", ");
}
stringBuilder.Append(item.Key).Append('x').Append(item.Value);
num++;
}
string text = ((NewAIController_SimulateFootprints_Patch.UnreadableHuman > 0) ? "some SimulateFootprints calls could not read their human — that is the likely source" : "every SimulateFootprints call read its human fine — these prints come from a different code path");
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(202, 8, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[NoEnforcerFootprints] LEAK: removed ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(tailRemoved);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" enforcer print(s) that were created after the block was active ");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("(plus ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(roomRemoved);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" from ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(roomsRefreshed);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" room list(s)). ");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Humans: [");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<StringBuilder>(stringBuilder);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("]. ");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Block counters: seen=");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(NewAIController_SimulateFootprints_Patch.Seen);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("blocked=");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(NewAIController_SimulateFootprints_Patch.Blocked);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("unreadableHuman=");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(NewAIController_SimulateFootprints_Patch.UnreadableHuman);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(". ");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Diagnosis: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
}
logger.LogWarning(val);
}
private static void CompleteFullPass(float now, int listCount)
{
//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
//IL_00f1: Expected O, but got Unknown
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Expected O, but got Unknown
fullPassIndex++;
fullPassCursor = -1;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val;
if (fullPassRemoved > 0)
{
ManualLogSource logger = Plugin.Logger;
val = new BepInExInfoLogInterpolatedStringHandler(140, 4, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[NoEnforcerFootprints] Full walk #");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(fullPassIndex);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" removed ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(fullPassRemoved);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" older enforcer print(s). ");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("World list now ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(listCount);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(". Walking again — backlog not yet drained. Cumulative: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(totalRemoved);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
}
logger.LogInfo(val);
return;
}
fullPassArmed = false;
fullPassRearmTime = now + Mathf.Max(30f, Plugin.FullPassIntervalSeconds.Value);
ManualLogSource logger2 = Plugin.Logger;
val = new BepInExInfoLogInterpolatedStringHandler(224, 7, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[NoEnforcerFootprints] Full walk #");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(fullPassIndex);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" found nothing — world list (");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(listCount);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" print(s)) is free of enforcer prints. ");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Standing down to tail-scan only for ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(Mathf.Max(30f, Plugin.FullPassIntervalSeconds.Value), "0");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("s. ");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Cumulative removed this session: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(totalRemoved);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(". ");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Block counters: seen=");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(NewAIController_SimulateFootprints_Patch.Seen);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("blocked=");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(NewAIController_SimulateFootprints_Patch.Blocked);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("unreadableHuman=");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(NewAIController_SimulateFootprints_Patch.UnreadableHuman);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
}
logger2.LogInfo(val);
}
}
[BepInPlugin("CalebScott.NoEnforcerFootprints", "No Enforcer Footprints", "1.1.2")]
public class Plugin : BasePlugin
{
public const string PLUGIN_GUID = "CalebScott.NoEnforcerFootprints";
internal static ManualLogSource Logger;
internal static ConfigEntry<bool> Enabled;
internal static ConfigEntry<bool> BlockNewFootprints;
internal static ConfigEntry<bool> PurgeExistingFootprints;
internal static ConfigEntry<bool> ExemptCurrentMurderer;
internal static ConfigEntry<float> PurgeIntervalSeconds;
internal static ConfigEntry<int> TailScanSize;
internal static ConfigEntry<int> FullPassSliceSize;
internal static ConfigEntry<float> FullPassIntervalSeconds;
internal static ConfigEntry<int> MaxRemovalsPerSweep;
internal static ConfigEntry<bool> VerboseLogging;
public override void Load()
{
//IL_0165: Unknown result type (might be due to invalid IL or missing references)
//IL_016b: Expected O, but got Unknown
//IL_017d: Unknown result type (might be due to invalid IL or missing references)
//IL_0183: Expected O, but got Unknown
Logger = ((BasePlugin)this).Log;
Enabled = ((BasePlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master switch. When true, enforcers never leave footprints, so crime scenes only carry prints that actually mean something.");
BlockNewFootprints = ((BasePlugin)this).Config.Bind<bool>("General", "BlockNewFootprints", true, "Stop enforcers laying down new footprints as they walk. This is the main effect.");
ExemptCurrentMurderer = ((BasePlugin)this).Config.Bind<bool>("General", "ExemptCurrentMurderer", true, "When true, the active case's murderer still leaves and keeps footprints even if they are an enforcer. Turn this off and an enforcer killer's case can become unsolvable by print evidence.");
PurgeExistingFootprints = ((BasePlugin)this).Config.Bind<bool>("Cleanup", "PurgeExistingFootprints", true, "Delete enforcer footprints that already exist in the save (from before this mod, or from any creation path the walk-time block misses).");
PurgeIntervalSeconds = ((BasePlugin)this).Config.Bind<float>("Cleanup", "PurgeIntervalSeconds", 5f, "How often (in real seconds) the cleanup ticks. Each tick scans the newest footprints, which is where anything that slipped past the walk-time block shows up. Minimum 1.");
TailScanSize = ((BasePlugin)this).Config.Bind<int>("Cleanup", "TailScanSize", 2000, "How many of the newest footprints to check on every tick. New prints are appended to the end of the world list, so this is the part that matters for a live crime scene. Keep it well under the total list size; that is what keeps the mod cheap.");
FullPassSliceSize = ((BasePlugin)this).Config.Bind<int>("Cleanup", "FullPassSliceSize", 4000, "How many older footprints to check per tick while walking the whole world list. The full list is covered a slice at a time so no single frame pays for all of it.");
FullPassIntervalSeconds = ((BasePlugin)this).Config.Bind<float>("Cleanup", "FullPassIntervalSeconds", 600f, "Once a complete walk of the world list comes back clean, wait this long (real seconds) before walking it again. Between full passes only the tail scan runs.");
MaxRemovalsPerSweep = ((BasePlugin)this).Config.Bind<int>("Cleanup", "MaxRemovalsPerSweep", 250, "Hard cap on footprints removed in a single tick, so a huge backlog is drained over several ticks instead of stalling a frame.");
VerboseLogging = ((BasePlugin)this).Config.Bind<bool>("Debug", "VerboseLogging", false, "Log every blocked footprint and every per-room strip. Noisy; only for diagnosing.");
Harmony val = new Harmony("CalebScott.NoEnforcerFootprints");
val.PatchAll();
ManualLogSource logger = Logger;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(80, 8, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("CalebScott.NoEnforcerFootprints");
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("] Loaded. enabled=");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(Enabled.Value);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" blockNew=");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(BlockNewFootprints.Value);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" ");
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("purgeExisting=");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(PurgeExistingFootprints.Value);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" exemptMurderer=");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(ExemptCurrentMurderer.Value);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" ");
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("tick=");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(PurgeIntervalSeconds.Value);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("s tail=");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(TailScanSize.Value);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" slice=");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(FullPassSliceSize.Value);
}
logger.LogInfo(val2);
}
}
internal static class PluginInfo
{
internal const string Guid = "CalebScott.NoEnforcerFootprints";
internal const string Name = "No Enforcer Footprints";
internal const string Version = "1.1.2";
}
}