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 InterestingLevels v1.3.0
InterestingLevels.dll
Decompiled 2 hours 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.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using InterestingLevels.Planning; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using UnityEngine; using UnityEngine.AI; [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("InterestingLevels")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.3.0.0")] [assembly: AssemblyInformationalVersion("1.3.0")] [assembly: AssemblyProduct("InterestingLevels")] [assembly: AssemblyTitle("InterestingLevels")] [assembly: AssemblyVersion("1.3.0.0")] [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 InterestingLevels { [BepInPlugin("interestinglevels.repo", "InterestingLevels", "1.3.0")] public sealed class Plugin : BaseUnityPlugin { public const string Guid = "interestinglevels.repo"; public const string Name = "InterestingLevels"; public const string Version = "1.3.0"; internal static ManualLogSource Log; private Harmony _harmony; private void Awake() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; BindConfig(); Health.Verify(); _harmony = new Harmony("interestinglevels.repo"); int num = 0; int num2 = 0; Type[] types = typeof(Plugin).Assembly.GetTypes(); foreach (Type type in types) { if (type.GetCustomAttributes(typeof(HarmonyPatch), inherit: false).Length != 0) { try { _harmony.CreateClassProcessor(type).Patch(); num++; } catch (Exception ex) { num2++; Log.LogWarning((object)("[startup] " + type.Name + " could not be applied; that part of the mod is off: " + ex.Message)); } } } try { NetWatcher.Create(); } catch (Exception ex2) { Log.LogInfo((object)("[startup] map checksum watcher not started: " + ex2.Message)); } Log.LogInfo((object)string.Format("{0} {1} loaded ({2} patch classes{3}; {4}). Only the host needs this mod.", "InterestingLevels", "1.3.0", num, (num2 > 0) ? (", " + num2 + " failed") : "", Health.Summary())); } private void BindConfig() { try { Cfg.Bind(((BaseUnityPlugin)this).Config); return; } catch (Exception ex) { Log.LogWarning((object)("[config] the config file couldn't be read (" + ex.Message + "); it was set aside and recreated with defaults.")); } try { string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath; if (File.Exists(configFilePath)) { string text = configFilePath + ".bad"; if (File.Exists(text)) { File.Delete(text); } File.Move(configFilePath, text); } ((BaseUnityPlugin)this).Config.Clear(); ((BaseUnityPlugin)this).Config.Reload(); } catch { } Cfg.Bind(((BaseUnityPlugin)this).Config); } } internal static class Acc { internal static readonly FieldRef<LevelGenerator, int> ModuleAmount = Ref<LevelGenerator, int>("ModuleAmount"); internal static readonly FieldRef<LevelGenerator, int> DeadEndAmount = Ref<LevelGenerator, int>("DeadEndAmount"); internal static readonly FieldRef<LevelGenerator, int> ExtractionAmount = Ref<LevelGenerator, int>("ExtractionAmount"); internal static readonly FieldRef<LevelGenerator, int> SpecialAmount = Ref<LevelGenerator, int>("SpecialAmount"); internal static readonly FieldRef<LevelGenerator, Tile[,]> LevelGrid = Ref<LevelGenerator, Tile[,]>("LevelGrid"); internal static readonly FieldRef<LevelGenerator, List<MegaTile>> MegaTiles = Ref<LevelGenerator, List<MegaTile>>("MegaTiles"); internal static readonly FieldRef<LevelGenerator, bool> Waiting = Ref<LevelGenerator, bool>("waitingForSubCoroutine"); internal static readonly FieldRef<LevelGenerator, float> Rarity1 = Ref<LevelGenerator, float>("ModuleRarity1"); internal static readonly FieldRef<LevelGenerator, float> Rarity2 = Ref<LevelGenerator, float>("ModuleRarity2"); internal static readonly FieldRef<LevelGenerator, float> Rarity3 = Ref<LevelGenerator, float>("ModuleRarity3"); internal static readonly FieldRef<LevelGenerator, bool> DebugNormal = Ref<LevelGenerator, bool>("DebugNormal"); internal static readonly FieldRef<LevelGenerator, bool> DebugPassage = Ref<LevelGenerator, bool>("DebugPassage"); internal static readonly FieldRef<LevelGenerator, bool> DebugDeadEnd = Ref<LevelGenerator, bool>("DebugDeadEnd"); internal static readonly FieldRef<LevelGenerator, bool> DebugExtraction = Ref<LevelGenerator, bool>("DebugExtraction"); internal static readonly FieldRef<LevelGenerator, bool> DebugMega = Ref<LevelGenerator, bool>("DebugMega"); internal static readonly FieldRef<LevelGenerator, int> DebugAmount = Ref<LevelGenerator, int>("DebugAmount"); internal static readonly FieldRef<LevelGenerator, float> DebugLevelSize = Ref<LevelGenerator, float>("DebugLevelSize"); internal static readonly FieldRef<LevelGenerator, PrefabRef> DebugModule = Ref<LevelGenerator, PrefabRef>("DebugModule"); internal static readonly FieldInfo ModuleSpawns = Field(typeof(LevelGenerator), "moduleSpawns"); internal static readonly FieldRef<Module, int> GridX = Ref<Module, int>("GridX"); internal static readonly FieldRef<Module, int> GridY = Ref<Module, int>("GridY"); internal static readonly FieldRef<Module, bool> StartRoom = Ref<Module, bool>("StartRoom"); internal static readonly FieldRef<ValuableDirector, int> TotalMaxAmount = Ref<ValuableDirector, int>("totalMaxAmount"); internal static readonly FieldRef<ValuableDirector, float> TotalMaxValue = Ref<ValuableDirector, float>("totalMaxValue"); internal static readonly string[] SizeNames = new string[7] { "tiny", "small", "medium", "big", "wide", "tall", "veryTall" }; internal static readonly FieldRef<RoundDirector, int> HaulGoal = Ref<RoundDirector, int>("haulGoal"); internal static readonly FieldRef<RoundDirector, List<GameObject>> ExtractionPointList = Ref<RoundDirector, List<GameObject>>("extractionPointList"); internal static readonly FieldRef<ValuableObject, float> DollarValueCurrent = Ref<ValuableObject, float>("dollarValueCurrent"); internal static float TileSize => StaticFloat(typeof(LevelGenerator), "TileSize", 5f); internal static float ModuleWidth => StaticFloat(typeof(LevelGenerator), "ModuleWidth", 3f); internal static float ModuleHeight => StaticFloat(typeof(LevelGenerator), "ModuleHeight", 1f); internal static FieldRef<T, F> Ref<T, F>(string name) { try { FieldInfo fieldInfo = AccessTools.Field(typeof(T), name); if (fieldInfo == null || fieldInfo.IsStatic || fieldInfo.FieldType != typeof(F)) { Plugin.Log.LogInfo((object)("[access] " + typeof(T).Name + "." + name + " not found (or changed type) - the part of the mod using it is off.")); return null; } return AccessTools.FieldRefAccess<T, F>(fieldInfo); } catch (Exception ex) { Plugin.Log.LogInfo((object)("[access] " + typeof(T).Name + "." + name + ": " + ex.Message)); return null; } } internal static FieldInfo Field(Type t, string name) { try { return AccessTools.Field(t, name); } catch { return null; } } internal static float StaticFloat(Type t, string name, float fallback) { try { FieldInfo fieldInfo = AccessTools.Field(t, name); if (fieldInfo != null && fieldInfo.IsStatic && fieldInfo.FieldType == typeof(float)) { return (float)fieldInfo.GetValue(null); } } catch { } return fallback; } internal static List<PrefabRef> ShuffledList(LevelGenerator lg, string type, int tier) { return Field(typeof(LevelGenerator), "Modules" + type + "Shuffled_" + tier)?.GetValue(lg) as List<PrefabRef>; } internal static List<PrefabRef> LevelList(Level level, string type, int tier) { return Field(typeof(Level), "Modules" + type + tier)?.GetValue(level) as List<PrefabRef>; } internal static int LevelSpecialAmount(Level level) { FieldInfo fieldInfo = Field(typeof(Level), "ModulesSpecialAmount"); if (!(fieldInfo != null) || !(fieldInfo.FieldType == typeof(int))) { return 0; } return (int)fieldInfo.GetValue(level); } internal static bool LastModuleSpawn(LevelGenerator lg, out PrefabRef prefab, out int x, out int y) { prefab = null; x = (y = -1); if (ModuleSpawns == null) { return false; } if (!(ModuleSpawns.GetValue(lg) is IList { Count: not 0 } list)) { return false; } object obj = list[list.Count - 1]; if (obj == null) { return false; } Traverse val = Traverse.Create(obj); object value = val.Field("prefab").GetValue(); prefab = (PrefabRef)((value is PrefabRef) ? value : null); x = val.Field("x").GetValue<int>(); y = val.Field("y").GetValue<int>(); return prefab != null; } internal static List<PrefabRef> DirectorValuables(ValuableDirector vd, int size) { return Field(typeof(ValuableDirector), SizeNames[size] + "Valuables")?.GetValue(vd) as List<PrefabRef>; } internal static int SizeIndex(Type t) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Expected I4, but got Unknown int num = (int)t; if (num < 0 || num >= SizeNames.Length) { return -1; } return num; } internal static IEnumerable<LevelValuables> Presets(Level level) { if ((Object)(object)level == (Object)null || level.ValuablePresets == null) { yield break; } foreach (LevelValuables valuablePreset in level.ValuablePresets) { if ((Object)(object)valuablePreset != (Object)null) { yield return valuablePreset; } } } internal static List<PrefabRef> PresetList(LevelValuables lv, int size) { return size switch { 0 => lv.tiny, 1 => lv.small, 2 => lv.medium, 3 => lv.big, 4 => lv.wide, 5 => lv.tall, 6 => lv.veryTall, _ => null, }; } } internal sealed class CatalogEntry { public string Key = ""; public string Name = ""; public string Source = "vanilla"; public int Size; public readonly HashSet<string> Levels = new HashSet<string>(); public bool Checked; public bool Broken; public string Reason = ""; public float ValueMin; public float ValueMax; public float Fragility; public float Durability; public float AvgValue => (ValueMin + ValueMax) * 0.5f; } internal static class Catalog { private static readonly Dictionary<string, CatalogEntry> Entries = new Dictionary<string, CatalogEntry>(); private static readonly Dictionary<PrefabRef, CatalogEntry> ByRef = new Dictionary<PrefabRef, CatalogEntry>(); private static bool _summaryLogged; private static Dictionary<string, string> _bundleOf; private static readonly float[] MaxSide = new float[7] { 1.2f, 1.6f, 2.6f, 3.6f, 5.5f, 5f, 8f }; internal static readonly string[] SizeLabels = new string[7] { "Tiny", "Small", "Medium", "Big", "Wide", "Tall", "Very Tall" }; private static HashSet<PrefabRef> _repoLib; internal static string KeyOf(PrefabRef r) { if (r == null) { return ""; } string text = null; try { text = ((PrefabRef<GameObject>)(object)r).ResourcePath; } catch { } if (string.IsNullOrEmpty(text)) { try { text = ((PrefabRef<GameObject>)(object)r).PrefabName; } catch { } } return text ?? ""; } internal static void Refresh() { List<Level> list = new List<Level>(); if ((Object)(object)RunManager.instance != (Object)null) { if (RunManager.instance.levels != null) { list.AddRange(RunManager.instance.levels.Where((Level l) => (Object)(object)l != (Object)null)); } if ((Object)(object)RunManager.instance.levelCurrent != (Object)null && !list.Contains(RunManager.instance.levelCurrent)) { list.Add(RunManager.instance.levelCurrent); } } List<CatalogEntry> list2 = new List<CatalogEntry>(); foreach (Level item in list) { foreach (LevelValuables item2 in Acc.Presets(item)) { for (int num = 0; num < 7; num++) { List<PrefabRef> list3 = Acc.PresetList(item2, num); if (list3 == null) { continue; } foreach (PrefabRef item3 in list3) { if (item3 != null) { bool isNew; CatalogEntry catalogEntry = Get(item3, num, out isNew); catalogEntry.Levels.Add(((Object)item).name); if (isNew) { list2.Add(catalogEntry); } } } } } } if (!_summaryLogged) { _summaryLogged = true; LogTable("[catalog] valuables found", Entries.Values.ToList()); } else if (list2.Count > 0) { LogTable("[catalog] new valuables", list2); } } internal static CatalogEntry Get(PrefabRef r) { bool isNew; return Get(r, -1, out isNew); } private static CatalogEntry Get(PrefabRef r, int size, out bool isNew) { isNew = false; if (ByRef.TryGetValue(r, out var value)) { return value; } string text = KeyOf(r); if (!Entries.TryGetValue(text, out var value2)) { isNew = true; value2 = new CatalogEntry { Key = text, Size = size }; try { value2.Name = ((PrefabRef<GameObject>)(object)r).PrefabName ?? text; } catch { value2.Name = text; } value2.Source = SourceOf(r, value2.Name); if (string.IsNullOrEmpty(text) || !SafeIsValid(r)) { value2.Broken = true; value2.Checked = true; value2.Reason = "no prefab path"; } Entries[text] = value2; } if (value2.Size < 0 && size >= 0) { value2.Size = size; } ByRef[r] = value2; return value2; } private static bool SafeIsValid(PrefabRef r) { try { return ((PrefabRef<GameObject>)(object)r).IsValid(); } catch { return false; } } private static string SourceOf(PrefabRef r, string name) { try { AssetBundle bundle = ((PrefabRef<GameObject>)(object)r).Bundle; if ((Object)(object)bundle != (Object)null) { return Clean(((Object)bundle).name); } } catch { } string key = (name ?? "").ToLowerInvariant(); string text = KeyOf(r); if (text.StartsWith("Valuables/", StringComparison.OrdinalIgnoreCase)) { key = text.Substring("Valuables/".Length).ToLowerInvariant(); } if (_bundleOf == null) { IndexBundles(); } if (_bundleOf.TryGetValue(key, out var value)) { return value; } if (IsRepoLibRegistered(r)) { return "REPOLib (mod unknown)"; } return "vanilla"; } private static void IndexBundles() { _bundleOf = new Dictionary<string, string>(); try { foreach (AssetBundle allLoadedAssetBundle in AssetBundle.GetAllLoadedAssetBundles()) { if ((Object)(object)allLoadedAssetBundle == (Object)null || allLoadedAssetBundle.isStreamedSceneAssetBundle) { continue; } string[] allAssetNames; try { allAssetNames = allLoadedAssetBundle.GetAllAssetNames(); } catch { continue; } string[] array = allAssetNames; foreach (string text in array) { if (text.EndsWith(".prefab")) { int num = text.LastIndexOf('/'); string key = text.Substring(num + 1, text.Length - num - 1 - ".prefab".Length); if (!_bundleOf.ContainsKey(key)) { _bundleOf[key] = Clean(((Object)allLoadedAssetBundle).name); } } } } } catch (Exception ex) { Plugin.Log.LogInfo((object)("[catalog] could not index asset bundles: " + ex.Message)); } } private static string Clean(string bundle) { if (string.IsNullOrEmpty(bundle)) { return "mod"; } int num = bundle.LastIndexOf('.'); if (num <= 0) { return bundle; } return bundle.Substring(0, num); } private static bool IsRepoLibRegistered(PrefabRef r) { if (_repoLib == null) { _repoLib = new HashSet<PrefabRef>(); try { Type type = AccessTools.TypeByName("REPOLib.Modules.Valuables"); if (((type != null) ? AccessTools.Property(type, "RegisteredValuables") : null)?.GetValue(null) is IEnumerable enumerable) { foreach (object item in enumerable) { PrefabRef val = (PrefabRef)((item is PrefabRef) ? item : null); if (val != null) { _repoLib.Add(val); } } } } catch { } } return _repoLib.Contains(r); } internal static void Check(PrefabRef r, CatalogEntry e, int listSize) { //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Expected I4, but got Unknown if (e.Checked) { return; } e.Checked = true; try { GameObject val = null; try { val = ((PrefabRef<GameObject>)(object)r).Prefab; } catch (Exception ex) { e.Reason = "prefab failed to load (" + ex.Message + ")"; } if ((Object)(object)val == (Object)null) { Break(e, (e.Reason.Length > 0) ? e.Reason : "prefab missing"); return; } ValuableObject component = val.GetComponent<ValuableObject>(); if ((Object)(object)component == (Object)null) { Break(e, "no ValuableObject on the prefab"); return; } if ((Object)(object)component.valuePreset == (Object)null) { Break(e, "no value preset"); return; } e.ValueMin = component.valuePreset.valueMin; e.ValueMax = component.valuePreset.valueMax; if (float.IsNaN(e.ValueMin) || float.IsNaN(e.ValueMax) || e.ValueMax <= 0f || e.ValueMin < 0f || e.ValueMin > e.ValueMax) { Break(e, $"bad value range {e.ValueMin}-{e.ValueMax}"); return; } if ((Object)(object)component.durabilityPreset != (Object)null) { e.Fragility = component.durabilityPreset.fragility; e.Durability = component.durabilityPreset.durability; } int num = Acc.SizeIndex(component.volumeType); if (num < 0) { Break(e, "invalid size type " + (int)component.volumeType); return; } float num2 = BiggestSide(val); int num3 = ((listSize >= 0) ? listSize : num); if (num2 > MaxSide[num3] * 2f) { Break(e, $"{num2:0.0} m across, far too big for a {SizeLabels[num3]} spot"); } else if (listSize >= 0 && num != listSize && Cfg.DebugLogging.Value) { Plugin.Log.LogInfo((object)("[catalog] note: " + e.Name + " is listed as " + SizeLabels[listSize] + " but its own size is " + SizeLabels[num] + ".")); } } catch (Exception ex2) { Break(e, "check failed: " + ex2.Message); } } private static void Break(CatalogEntry e, string reason) { e.Broken = true; e.Reason = reason; Plugin.Log.LogWarning((object)("[catalog] skipping valuable '" + e.Name + "' (" + e.Source + "): " + reason + ".")); } private static float BiggestSide(GameObject prefab) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: 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_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) float num = 0f; Collider[] componentsInChildren = prefab.GetComponentsInChildren<Collider>(true); Vector3 val7 = default(Vector3); foreach (Collider val in componentsInChildren) { if ((Object)(object)val == (Object)null || val.isTrigger) { continue; } BoxCollider val2 = (BoxCollider)(object)((val is BoxCollider) ? val : null); if (val2 == null) { SphereCollider val3 = (SphereCollider)(object)((val is SphereCollider) ? val : null); if (val3 == null) { CapsuleCollider val4 = (CapsuleCollider)(object)((val is CapsuleCollider) ? val : null); if (val4 == null) { MeshCollider val5 = (MeshCollider)(object)((val is MeshCollider) ? val : null); if (val5 == null) { continue; } Vector3 val6; if (!((Object)(object)val5.sharedMesh != (Object)null)) { val6 = Vector3.zero; } else { Bounds bounds = val5.sharedMesh.bounds; val6 = ((Bounds)(ref bounds)).size; } val7 = val6; } else { ((Vector3)(ref val7))..ctor(val4.radius * 2f, val4.height, val4.radius * 2f); } } else { val7 = Vector3.one * val3.radius * 2f; } } else { val7 = val2.size; } Vector3 val8 = Vector3.Scale(val7, ((Component)val).transform.lossyScale); num = Mathf.Max(new float[4] { num, Mathf.Abs(val8.x), Mathf.Abs(val8.y), Mathf.Abs(val8.z) }); } return num; } private static void LogTable(string title, List<CatalogEntry> list) { List<IGrouping<string, CatalogEntry>> list2 = (from x in list group x by x.Source into grp orderby (!(grp.Key == "vanilla")) ? grp.Key : "" select grp).ToList(); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(title).Append(": ").Append(list.Count) .Append(" from ") .Append(list2.Count) .Append(" source(s)\n"); foreach (IGrouping<string, CatalogEntry> item in list2) { int[] array = new int[7]; foreach (CatalogEntry item2 in item) { if (item2.Size >= 0 && item2.Size < 7) { array[item2.Size]++; } } stringBuilder.Append(" ").Append(item.Key).Append(": ") .Append(item.Count()) .Append(" ("); for (int num = 0; num < 7; num++) { if (num > 0) { stringBuilder.Append(", "); } stringBuilder.Append(SizeLabels[num]).Append(' ').Append(array[num]); } stringBuilder.Append(")\n"); foreach (CatalogEntry item3 in from x in item orderby x.Size, x.Name select x) { stringBuilder.Append(" ").Append((item3.Size >= 0) ? SizeLabels[item3.Size] : "?").Append(" | ") .Append(item3.Name) .Append(" | levels: ") .Append(string.Join(", ", item3.Levels.OrderBy((string lv) => lv))) .Append(item3.Broken ? (" | BROKEN: " + item3.Reason) : "") .Append('\n'); } } stringBuilder.Append(" (value ranges and fragility are filled in as each level loads its valuables)"); Plugin.Log.LogInfo((object)stringBuilder.ToString()); } } internal static class Cfg { internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<bool> DebugLogging; internal static ConfigEntry<int> FixedSeed; internal static ConfigEntry<bool> LayoutVariety; internal static ConfigEntry<int> WeightWinding; internal static ConfigEntry<int> WeightHub; internal static ConfigEntry<int> WeightCompact; internal static ConfigEntry<int> WeightClassic; internal static ConfigEntry<float> LoopFrequency; internal static ConfigEntry<float> BranchFrequency; internal static ConfigEntry<float> DepthGradient; internal static ConfigEntry<float> VerticalityBias; internal static ConfigEntry<string> LevelDenylist; internal static ConfigEntry<bool> SpecialRooms; internal static ConfigEntry<float> VaultChance; internal static ConfigEntry<float> HiddenChance; internal static ConfigEntry<float> HazardChance; internal static ConfigEntry<float> QuietChance; internal static ConfigEntry<int> MaxSpecialRooms; internal static ConfigEntry<bool> ThemedRooms; internal static ConfigEntry<bool> Centerpieces; internal static ConfigEntry<bool> CenterpieceGuarantee; internal static ConfigEntry<bool> Shortcuts; internal static ConfigEntry<float> ThemedRoomChance; internal static ConfigEntry<float> CenterpieceChance; internal static ConfigEntry<float> ShortcutChance; internal static ConfigEntry<int> MaxThemedRooms; internal static ConfigEntry<int> WeightFragileGallery; internal static ConfigEntry<int> WeightHeavyStorage; internal static ConfigEntry<int> WeightJunkRoom; internal static ConfigEntry<bool> Modifiers; internal static ConfigEntry<bool> AnnounceModifier; internal static ConfigEntry<float> ModifierChance; internal static ConfigEntry<int> WeightSprawling; internal static ConfigEntry<int> WeightLabyrinth; internal static ConfigEntry<int> WeightTreasurePocket; internal static ConfigEntry<int> WeightGoldRush; internal static ConfigEntry<int> WeightLongHaul; internal static ConfigEntry<int> WeightCrowded; internal static ConfigEntry<int> WeightScavengerHunt; internal static ConfigEntry<bool> TruckScreenModifier; internal static ConfigEntry<bool> ValuableBalancing; internal static ConfigEntry<bool> AddSpawnVolumes; internal static ConfigEntry<float> MaxSharePerMod; internal static ConfigEntry<float> HaulGoalSafety; internal static ConfigEntry<bool> ExtractionPacing; internal static ConfigEntry<bool> StandDownForGoalMods; internal static ConfigEntry<float> PacingUnevenness; internal static ConfigEntry<float> SimilarityThreshold; internal static ConfigEntry<float> FreshnessStrength; internal static ConfigEntry<float> SurpriseChance; internal static ConfigEntry<int> HistoryLength; internal static ConfigEntry<int> MaxRegenerations; internal static ConfigEntry<bool> ClutterCleanup; internal static ConfigEntry<int> PropDensityLimit; internal static ConfigEntry<int> CleanupBudgetMs; internal static ConfigEntry<int> PlanBudgetMs; internal static ConfigEntry<int> ConfigVersion; internal static ConfigEntry<string> ForceFailure; internal const int CurrentConfigVersion = 3; internal static ConfigEntry<bool> StandDownForOtherLayoutMods; internal static void Bind(ConfigFile c) { //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Expected O, but got Unknown //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Expected O, but got Unknown //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Expected O, but got Unknown //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Expected O, but got Unknown //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Expected O, but got Unknown //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Expected O, but got Unknown //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Expected O, but got Unknown //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Expected O, but got Unknown //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Expected O, but got Unknown //IL_02ba: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Expected O, but got Unknown //IL_02f2: Unknown result type (might be due to invalid IL or missing references) //IL_02fc: Expected O, but got Unknown //IL_032a: Unknown result type (might be due to invalid IL or missing references) //IL_0334: Expected O, but got Unknown //IL_0356: Unknown result type (might be due to invalid IL or missing references) //IL_0360: Expected O, but got Unknown //IL_03a9: Unknown result type (might be due to invalid IL or missing references) //IL_03b3: Expected O, but got Unknown //IL_03d5: Unknown result type (might be due to invalid IL or missing references) //IL_03df: Expected O, but got Unknown //IL_0402: Unknown result type (might be due to invalid IL or missing references) //IL_040c: Expected O, but got Unknown //IL_042f: Unknown result type (might be due to invalid IL or missing references) //IL_0439: Expected O, but got Unknown //IL_045c: Unknown result type (might be due to invalid IL or missing references) //IL_0466: Expected O, but got Unknown //IL_04af: Unknown result type (might be due to invalid IL or missing references) //IL_04b9: Expected O, but got Unknown //IL_051d: Unknown result type (might be due to invalid IL or missing references) //IL_0527: Expected O, but got Unknown //IL_0570: Unknown result type (might be due to invalid IL or missing references) //IL_057a: Expected O, but got Unknown //IL_059d: Unknown result type (might be due to invalid IL or missing references) //IL_05a7: Expected O, but got Unknown //IL_05ca: Unknown result type (might be due to invalid IL or missing references) //IL_05d4: Expected O, but got Unknown //IL_05f7: Unknown result type (might be due to invalid IL or missing references) //IL_0601: Expected O, but got Unknown //IL_0624: Unknown result type (might be due to invalid IL or missing references) //IL_062e: Expected O, but got Unknown //IL_0651: Unknown result type (might be due to invalid IL or missing references) //IL_065b: Expected O, but got Unknown //IL_067e: Unknown result type (might be due to invalid IL or missing references) //IL_0688: Expected O, but got Unknown //IL_06ab: Unknown result type (might be due to invalid IL or missing references) //IL_06b5: Expected O, but got Unknown //IL_074f: Unknown result type (might be due to invalid IL or missing references) //IL_0759: Expected O, but got Unknown //IL_0787: Unknown result type (might be due to invalid IL or missing references) //IL_0791: Expected O, but got Unknown //IL_07da: Unknown result type (might be due to invalid IL or missing references) //IL_07e4: Expected O, but got Unknown //IL_082d: Unknown result type (might be due to invalid IL or missing references) //IL_0837: Expected O, but got Unknown //IL_085b: Unknown result type (might be due to invalid IL or missing references) //IL_0865: Expected O, but got Unknown //IL_0888: Unknown result type (might be due to invalid IL or missing references) //IL_0892: Expected O, but got Unknown //IL_08c0: Unknown result type (might be due to invalid IL or missing references) //IL_08ca: Expected O, but got Unknown //IL_08f8: Unknown result type (might be due to invalid IL or missing references) //IL_0902: Expected O, but got Unknown //IL_0941: Unknown result type (might be due to invalid IL or missing references) //IL_094b: Expected O, but got Unknown //IL_0972: Unknown result type (might be due to invalid IL or missing references) //IL_097c: Expected O, but got Unknown //IL_09a7: Unknown result type (might be due to invalid IL or missing references) //IL_09b1: Expected O, but got Unknown //IL_0a99: Unknown result type (might be due to invalid IL or missing references) //IL_0aa3: Expected O, but got Unknown ConfigVersion = c.Bind<int>("0. Info", "Config version", 3, "Set by the mod; don't change. New options are added without touching your settings."); Enabled = c.Bind<bool>("1. General", "Enabled", true, "Master switch for the whole mod."); DebugLogging = c.Bind<bool>("1. General", "Debug logging", false, "Log every map as a text picture, plus extra detail."); FixedSeed = c.Bind<int>("1. General", "Fixed seed", 0, "0 = random. Any other number makes the mod's layout choices repeat for the same level number (for testing and bug reports)."); LayoutVariety = c.Bind<bool>("2. Layout", "Layout variety", true, "Use the mod's map shapes, loops and branches. Off = the game's own layout (depth gradient and special rooms still work)."); WeightWinding = c.Bind<int>("2. Layout", "Shape weight: winding", 25, new ConfigDescription("Long winding maps.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); WeightHub = c.Bind<int>("2. Layout", "Shape weight: hub", 25, new ConfigDescription("A wide central hub with spokes.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); WeightCompact = c.Bind<int>("2. Layout", "Shape weight: compact", 20, new ConfigDescription("Compact, dense maps.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); WeightClassic = c.Bind<int>("2. Layout", "Shape weight: classic", 30, new ConfigDescription("The game's own random walk.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); LoopFrequency = c.Bind<float>("2. Layout", "Loop frequency", 0.5f, new ConfigDescription("How often maps get a second route between areas (0 = never).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); BranchFrequency = c.Bind<float>("2. Layout", "Branch frequency", 0.5f, new ConfigDescription("How often side branches with dead ends appear (0 = never).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); DepthGradient = c.Bind<float>("2. Layout", "Depth gradient", 0.5f, new ConfigDescription("How much harder rooms and better loot get the farther they are from the truck (0 = off).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); VerticalityBias = c.Bind<float>("2. Layout", "Verticality bias", 1f, new ConfigDescription("Prefer rooms with stairs, upper floors and drops (learned as you play; 0 = off).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>())); LevelDenylist = c.Bind<string>("2. Layout", "Leave these levels alone", "", "Comma-separated level names (as shown in the log) that keep the game's own layout."); SpecialRooms = c.Bind<bool>("3. Special rooms", "Special rooms", true, "Vaults, hidden rooms, hazard rooms and quiet rooms (a few per map at most)."); VaultChance = c.Bind<float>("3. Special rooms", "Vault chance", 0.3f, new ConfigDescription("Per map.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); HiddenChance = c.Bind<float>("3. Special rooms", "Hidden room chance", 0.4f, new ConfigDescription("Per map.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); HazardChance = c.Bind<float>("3. Special rooms", "Hazard room chance", 0.3f, new ConfigDescription("Per map.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); QuietChance = c.Bind<float>("3. Special rooms", "Quiet room chance", 0.5f, new ConfigDescription("Per map.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); MaxSpecialRooms = c.Bind<int>("3. Special rooms", "Max special rooms per map", 3, new ConfigDescription("", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 4), Array.Empty<object>())); ThemedRooms = c.Bind<bool>("3. Special rooms", "Themed loot rooms", true, "Now and then a room gets a loot theme: Fragile Gallery (breakable, high-value loot), Heavy Storage (big and wide loot only) or Junk Room (lots of tiny, cheap loot)."); ThemedRoomChance = c.Bind<float>("3. Special rooms", "Themed room chance", 0.35f, new ConfigDescription("Chance per map of a themed room.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); MaxThemedRooms = c.Bind<int>("3. Special rooms", "Max themed rooms per map", 2, new ConfigDescription("", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 2), Array.Empty<object>())); WeightFragileGallery = c.Bind<int>("3. Special rooms", "Theme weight: Fragile Gallery", 1, new ConfigDescription("", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10), Array.Empty<object>())); WeightHeavyStorage = c.Bind<int>("3. Special rooms", "Theme weight: Heavy Storage", 1, new ConfigDescription("", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10), Array.Empty<object>())); WeightJunkRoom = c.Bind<int>("3. Special rooms", "Theme weight: Junk Room", 1, new ConfigDescription("", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10), Array.Empty<object>())); Centerpieces = c.Bind<bool>("3. Special rooms", "Centerpiece rooms", true, "Some maps keep a 2x2 space for one of the level's big mega rooms in a meaningful spot (the middle of a hub, or where routes meet). Levels without mega rooms are skipped."); CenterpieceChance = c.Bind<float>("3. Special rooms", "Centerpiece chance", 0.25f, new ConfigDescription("Chance per map.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); CenterpieceGuarantee = c.Bind<bool>("3. Special rooms", "Centerpiece: make the game place it", true, "On a centerpiece map, the game's own mega-room roll is made a sure thing for that space (it still keeps its own rule of at most one mega room every third level). Off = the game rolls its usual small chance."); Shortcuts = c.Bind<bool>("3. Special rooms", "Risky shortcuts", true, "Some maps get two ways into the deep part: a short route through a chain of hazard rooms (hardest rooms, fragile loot) and a longer, calmer way round."); ShortcutChance = c.Bind<float>("3. Special rooms", "Risky shortcut chance", 0.25f, new ConfigDescription("Chance per map.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); Modifiers = c.Bind<bool>("4. Map modifiers", "Map modifiers", true, "Rare level-wide twists (at most one per level)."); ModifierChance = c.Bind<float>("4. Map modifiers", "Modifier chance", 0.15f, new ConfigDescription("Chance per level.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); WeightSprawling = c.Bind<int>("4. Map modifiers", "Weight: Sprawling", 1, new ConfigDescription("Bigger map, more loot.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10), Array.Empty<object>())); WeightLabyrinth = c.Bind<int>("4. Map modifiers", "Weight: Labyrinth", 1, new ConfigDescription("More loops and turns.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10), Array.Empty<object>())); WeightTreasurePocket = c.Bind<int>("4. Map modifiers", "Weight: Treasure Pocket", 1, new ConfigDescription("One vault guaranteed.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10), Array.Empty<object>())); WeightGoldRush = c.Bind<int>("4. Map modifiers", "Weight: Gold Rush", 1, new ConfigDescription("Fewer valuables, all from the top of the value range.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10), Array.Empty<object>())); WeightLongHaul = c.Bind<int>("4. Map modifiers", "Weight: Long Haul", 1, new ConfigDescription("Every extraction point deep in the map.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10), Array.Empty<object>())); WeightCrowded = c.Bind<int>("4. Map modifiers", "Weight: Crowded", 1, new ConfigDescription("More monsters and more loot.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10), Array.Empty<object>())); WeightScavengerHunt = c.Bind<int>("4. Map modifiers", "Weight: Scavenger Hunt", 1, new ConfigDescription("Lots of tiny valuables in hidden rooms and the spots where valuables replace props.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10), Array.Empty<object>())); AnnounceModifier = c.Bind<bool>("4. Map modifiers", "Announce modifier", true, "Show the active modifier on the host's screen when the level starts."); TruckScreenModifier = c.Bind<bool>("4. Map modifiers", "Show modifier on the truck screen", true, "Post the active modifier on the truck screen, which everyone in the lobby sees (no mod needed on their side)."); ValuableBalancing = c.Bind<bool>("5. Valuables", "Valuable balancing", true, "Balance which valuables spawn (mix of mods, sizes and values; better loot deeper and in special rooms)."); AddSpawnVolumes = c.Bind<bool>("5. Valuables", "Add spawn spots", true, "Add spawn spots for valuable sizes a level is short of (e.g. big modded valuables)."); MaxSharePerMod = c.Bind<float>("5. Valuables", "Max share per mod", 0.35f, new ConfigDescription("Most of a map's valuables any one valuable mod may fill (the base game is exempt).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 1f), Array.Empty<object>())); HaulGoalSafety = c.Bind<float>("5. Valuables", "Haul goal safety", 0.8f, new ConfigDescription("The haul goal is never more than this share of the value players can actually reach.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.3f, 1f), Array.Empty<object>())); ExtractionPacing = c.Bind<bool>("5. Valuables", "Extraction pacing", true, "Split the haul goal unevenly: a small first extraction near the truck, rising goals after, a big final one deep in. The total stays what the game (or RepoRPG) set."); PacingUnevenness = c.Bind<float>("5. Valuables", "Pacing unevenness", 0.5f, new ConfigDescription("0 = the game's even split, 1 = the deepest point's goal is about four times the nearest one's.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); StandDownForGoalMods = c.Bind<bool>("5. Valuables", "Stand down for other goal mods", true, "If ExtractionGoalSetter (or another mod changing extraction goals) is installed, leave the split to it."); SimilarityThreshold = c.Bind<float>("6. Freshness", "Similarity threshold", 0.7f, new ConfigDescription("A new map this similar (0-1) to a recent map of the same level type is regenerated with a new seed.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.3f, 1f), Array.Empty<object>())); HistoryLength = c.Bind<int>("6. Freshness", "History length", 25, new ConfigDescription("Recent maps remembered per level type (kept between sessions).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(5, 60), Array.Empty<object>())); MaxRegenerations = c.Bind<int>("6. Freshness", "Max regenerations", 6, new ConfigDescription("Tries per level before keeping the most different map found.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 12), Array.Empty<object>())); FreshnessStrength = c.Bind<float>("6. Freshness", "Freshness strength", 0.7f, new ConfigDescription("How strongly recent shapes, modifiers, special rooms, start rooms, room picks and valuable spots are avoided (0 = off).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); SurpriseChance = c.Bind<float>("6. Freshness", "Surprise chance", 0.08f, new ConfigDescription("Chance per level of a rare feature: a vault behind a long route, a grand hub, or a long drop.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.5f), Array.Empty<object>())); ClutterCleanup = c.Bind<bool>("7. Clutter", "Clutter cleanup", true, "Check valuable spawn spots and clean up loose objects after generation (stuck, blocking doors or extraction points, stacked, unreachable, over-full rooms)."); PropDensityLimit = c.Bind<int>("7. Clutter", "Room density limit", 14, new ConfigDescription("Most valuables and loose props one room may hold.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(4, 60), Array.Empty<object>())); CleanupBudgetMs = c.Bind<int>("7. Clutter", "Cleanup time budget (ms)", 30, new ConfigDescription("If the cleanup runs over, it finishes the most important fixes (blocked paths, stuck valuables) and logs the rest.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(5, 500), Array.Empty<object>())); PlanBudgetMs = c.Bind<int>("8. Advanced", "Layout time budget (ms)", 250, new ConfigDescription("If the layout takes longer, the level uses the game's layout instead.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(20, 2000), Array.Empty<object>())); ForceFailure = c.Bind<string>("9. Testing", "Force a failure in", "None", new ConfigDescription("For testing only: makes one step fail on purpose, to check that the level still loads with the game's own behaviour for that step. SlowLayout makes the layout run over its time budget.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[22] { "None", "Layout", "Modifiers", "Similarity", "SpecialRooms", "ModuleTiers", "Freshness", "StartRooms", "Verticality", "Valuables", "SpawnSpots", "Clutter", "HaulGoal", "History", "Checksum", "Themes", "Pacing", "Centerpiece", "Shortcuts", "ModifierEffects", "SlowLayout", "All" }), Array.Empty<object>())); StandDownForOtherLayoutMods = c.Bind<bool>("8. Advanced", "Stand down for other layout mods", true, "If another mod also replaces the tile layout, keep the game's layout so the two don't fight."); if (ConfigVersion.Value != 3) { Plugin.Log.LogInfo((object)$"[config] updated from version {ConfigVersion.Value} to {3}; your settings were kept."); ConfigVersion.Value = 3; } } } internal static class Validation { internal static int LastIssues; internal static void Run(LevelGenerator lg) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Expected O, but got Unknown List<string> list = new List<string>(); try { Vector3 val = Vector3.zero; bool num = (Object)(object)lg.LevelPathTruck != (Object)null; if (!num) { list.Add("no truck spawn point"); } else { val = ((Component)lg.LevelPathTruck).transform.position; } NavMeshHit val2 = default(NavMeshHit); bool flag = num && NavMesh.SamplePosition(val, ref val2, 4f, -1); if (num && !flag) { list.Add("truck area not on the navmesh"); } Module[] array = Object.FindObjectsByType<Module>((FindObjectsSortMode)0); if (array.Length == 0) { list.Add("no rooms spawned"); } if (Acc.StartRoom != null && !array.Any((Module m) => (Object)(object)m != (Object)null && Acc.StartRoom.Invoke(m))) { list.Add("no start room"); } if (MapState.Plan != null && MapState.FromLayout && !MapState.Plan.AllConnected()) { list.Add("map grid not connected"); } ExtractionPoint[] array2 = Object.FindObjectsByType<ExtractionPoint>((FindObjectsSortMode)0); if (((Acc.ExtractionAmount != null && Acc.ExtractionAmount.Invoke(lg) != 0) ? 1 : 0) > (false ? 1 : 0) && array2.Length == 0) { list.Add("no extraction points"); } if (flag) { NavMeshHit from = default(NavMeshHit); NavMesh.SamplePosition(val, ref from, 4f, -1); NavMeshPath path = new NavMeshPath(); int num2 = array2.Count((ExtractionPoint p) => (Object)(object)p != (Object)null && !Reachable(((NavMeshHit)(ref from)).position, ((Component)p).transform.position, path)); if (num2 > 0) { list.Add($"{num2} extraction point(s) look unreachable on the navmesh"); } } } catch (Exception ex) { list.Add("check failed: " + ex.Message); } LastIssues = list.Count; if (list.Count == 0) { if (Cfg.DebugLogging.Value) { Plugin.Log.LogInfo((object)"[check] map OK: start room, truck, rooms connected, extraction points reachable."); } } else { Plugin.Log.LogWarning((object)(string.Format("[check] level '{0}' (seed {1}, {2}): {3}. ", MapState.LevelName, MapState.Seed, MapState.FromLayout ? "mod layout" : "game layout", string.Join("; ", list)) + "The level stays playable; please report this with the log.")); } } internal static bool Reachable(Vector3 from, Vector3 target, NavMeshPath path) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0026: 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_0036: Invalid comparison between Unknown and I4 //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_0062: Unknown result type (might be due to invalid IL or missing references) NavMeshHit val = default(NavMeshHit); if (!NavMesh.SamplePosition(target, ref val, 4f, -1)) { return false; } if (!NavMesh.CalculatePath(from, ((NavMeshHit)(ref val)).position, -1, path)) { return false; } if ((int)path.status == 0) { return true; } if ((int)path.status == 1 && path.corners.Length != 0) { Vector3 val2 = path.corners[path.corners.Length - 1] - ((NavMeshHit)(ref val)).position; return ((Vector3)(ref val2)).sqrMagnitude < 16f; } return false; } } internal static class MapChecksum { internal const string RoomKey = "IL.map"; internal const string CheckKey = "IL.chk"; internal const string VersionKey = "IL.ver"; private static string _pendingKey; private static string _pendingHash; private static int _pendingCount; private static float _pendingUntil; private static float _hostReportAt; private static string _hostKey; internal static string LevelKey() { RunManager instance = RunManager.instance; return (((Object)(object)instance != (Object)null) ? instance.levelsCompleted : (-1)) + ":" + (((Object)(object)instance != (Object)null && (Object)(object)instance.levelCurrent != (Object)null) ? ((Object)instance.levelCurrent).name : "?"); } internal static string Compute(out int count) { //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_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Expected I4, but got Unknown List<string> list = new List<string>(); Module[] array = Object.FindObjectsByType<Module>((FindObjectsSortMode)0); foreach (Module val in array) { if (!((Object)(object)val == (Object)null)) { Vector3 position = ((Component)val).transform.position; int num = Mathf.RoundToInt(((Component)val).transform.eulerAngles.y / 90f) & 3; list.Add($"{Mathf.RoundToInt(position.x * 2f)},{Mathf.RoundToInt(position.y * 2f)},{Mathf.RoundToInt(position.z * 2f)},{num},{(int)val.type}"); } } list.Sort(StringComparer.Ordinal); count = list.Count; ulong num2 = 14695981039346656037uL; foreach (string item in list) { foreach (char c in item) { num2 ^= c; num2 *= 1099511628211L; } num2 ^= 0x7C; num2 *= 1099511628211L; } return num2.ToString("x16"); } internal static void HostLevelDone(LevelGenerator lg) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown int count; string text = Compute(out count); _hostKey = LevelKey(); if (Cfg.DebugLogging.Value) { Plugin.Log.LogInfo((object)$"[checksum] map {text} ({count} rooms)."); } if (SemiFunc.IsMultiplayer() && PhotonNetwork.InRoom) { Room currentRoom = PhotonNetwork.CurrentRoom; Hashtable val = new Hashtable(); ((Dictionary<object, object>)(object)val).Add((object)"IL.map", (object)(_hostKey + "|" + text + "|" + count)); currentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); _hostReportAt = Time.realtimeSinceStartup + 40f; } } internal static void ClientLevelDone(LevelGenerator lg) { _pendingHash = Compute(out _pendingCount); _pendingKey = LevelKey(); _pendingUntil = Time.realtimeSinceStartup + 30f; } internal static void Tick() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown //IL_005a: Expected O, but got Unknown //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Expected O, but got Unknown //IL_0392: Unknown result type (might be due to invalid IL or missing references) //IL_03a6: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) if (!PhotonNetwork.InRoom) { _pendingKey = null; return; } Player localPlayer = PhotonNetwork.LocalPlayer; if (localPlayer != null && (!((Dictionary<object, object>)(object)localPlayer.CustomProperties).TryGetValue((object)"IL.ver", out object value) || !(value as string == "1.3.0"))) { Hashtable val = new Hashtable(); ((Dictionary<object, object>)val).Add((object)"IL.ver", (object)"1.3.0"); localPlayer.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); } if (_pendingKey != null) { object value2; if (Time.realtimeSinceStartup > _pendingUntil) { if (Cfg.DebugLogging.Value) { Plugin.Log.LogInfo((object)"[checksum] the host didn't publish a map checksum (the host may not have the mod)."); } _pendingKey = null; } else if (((Dictionary<object, object>)(object)((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties).TryGetValue((object)"IL.map", out value2) && value2 is string text) { string[] array = text.Split('|'); if (array.Length == 3 && array[0] == _pendingKey) { bool flag = array[1] == _pendingHash; if (localPlayer != null) { Hashtable val2 = new Hashtable(); ((Dictionary<object, object>)(object)val2).Add((object)"IL.chk", (object)(_pendingKey + "|" + (flag ? "1" : "0") + "|" + _pendingHash + "|" + _pendingCount)); localPlayer.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null); } if (flag) { if (Cfg.DebugLogging.Value) { Plugin.Log.LogInfo((object)"[checksum] map matches the host's."); } } else { Plugin.Log.LogWarning((object)($"[checksum] this map differs from the host's (host {array[1]} with {array[2]} rooms, here {_pendingHash} with {_pendingCount} rooms). " + "This comes from the game's networking, not from a different map plan. Rejoining or restarting the level fixes it.")); try { SemiFunc.UIFocusText("Map check: your rooms differ from the host's. Rejoin if things look wrong.", Color.white, new Color(1f, 0.5f, 0.3f), 8f); } catch { } } _pendingKey = null; } } } if (_hostKey == null || !(_hostReportAt > 0f) || !(Time.realtimeSinceStartup > _hostReportAt)) { return; } _hostReportAt = 0f; int num = 0; int num2 = 0; List<string> list = new List<string>(); List<string> list2 = new List<string>(); Player[] playerList = PhotonNetwork.PlayerList; foreach (Player val3 in playerList) { if (val3 == null || val3.IsLocal) { continue; } if (!((Dictionary<object, object>)(object)val3.CustomProperties).TryGetValue((object)"IL.ver", out object value3)) { num2++; continue; } if (value3 as string != "1.3.0") { list2.Add($"{val3.NickName} {value3}"); } if (!((Dictionary<object, object>)(object)val3.CustomProperties).TryGetValue((object)"IL.chk", out object value4) || !(value4 is string text2)) { continue; } string[] array2 = text2.Split('|'); if (array2.Length >= 2 && array2[0] == _hostKey) { if (array2[1] == "1") { num++; } else { list.Add(val3.NickName); } } } if (list.Count > 0) { Plugin.Log.LogWarning((object)string.Format("[checksum] {0} player(s) got different rooms than the host: {1}. They should rejoin.", list.Count, string.Join(", ", list))); try { SemiFunc.UIFocusText("Map check: " + string.Join(", ", list) + " got different rooms. Ask them to rejoin.", Color.white, new Color(1f, 0.5f, 0.3f), 8f); } catch { } } else if (Cfg.DebugLogging.Value || list2.Count > 0) { Plugin.Log.LogInfo((object)($"[checksum] {num} player(s) with the mod matched the host's map; {num2} without it (fine: only the host needs it)" + ((list2.Count > 0) ? ("; other versions (harmless): " + string.Join(", ", list2)) : "") + ".")); } _hostKey = null; } } internal sealed class NetWatcher : MonoBehaviour { private float _next; internal static void Create() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown GameObject val = new GameObject("InterestingLevels.NetWatcher") { hideFlags = (HideFlags)61 }; Object.DontDestroyOnLoad((Object)val); val.AddComponent<NetWatcher>(); } private void Update() { if (Time.realtimeSinceStartup < _next) { return; } _next = Time.realtimeSinceStartup + 1f; if (!Cfg.Enabled.Value) { return; } try { Announce.Tick(); } catch (Exception ex) { if (Cfg.DebugLogging.Value) { Plugin.Log.LogInfo((object)("[announce] " + ex.Message)); } } if (!Health.Patchable(Feature.Checksum)) { return; } try { MapChecksum.Tick(); } catch (Exception ex2) { if (Cfg.DebugLogging.Value) { Plugin.Log.LogInfo((object)("[checksum] " + ex2.Message)); } } } } internal static class Soak { private static int _levels; private static float _levelStart; private static double _firstMemory; internal static void LevelStarted() { _levelStart = Time.realtimeSinceStartup; } internal static void LevelDone(LevelGenerator lg) { _levels++; double num = (double)GC.GetTotalMemory(forceFullCollection: false) / 1048576.0; if (_firstMemory <= 0.0) { _firstMemory = num; } float num2 = ((_levelStart > 0f) ? (Time.realtimeSinceStartup - _levelStart) : 0f); string text = $"[level {_levels}] '{MapState.LevelName}' built in {num2:0.0} s; mod work {Perf.Describe()}; " + $"memory {num:0} MB (first level {_firstMemory:0} MB); objects {Object.FindObjectsByType<PhysGrabObject>((FindObjectsSortMode)0).Length}; " + string.Format("history {0} maps; {1}; {2}", HistoryStore.MapCount, (Health.FailuresThisLevel > 0) ? (Health.FailuresThisLevel + " step(s) skipped") : "no steps skipped", Health.Summary()); Plugin.Log.LogInfo((object)text); _levelStart = 0f; } } internal static class Clutter { private struct Zone { public Vector3 P; public float R; public string Kind; } private sealed class Obj { public PhysGrabObject G; public ValuableObject V; public bool Loose; public Module Room; public Vector3 Pos; public float Value; } private static readonly List<Zone> Zones = new List<Zone>(); private static readonly List<Vector3> Placed = new List<Vector3>(); private static bool _zonesBuilt; internal static int PreSwapped; internal static int PreSkipped; private static int _cleanedLevel; private static readonly int Mask = -5; private const int MaxObjects = 800; private const int MaxFixes = 120; internal static bool On { get { if (Cfg.ClutterCleanup.Value) { return Health.On(Feature.Clutter); } return false; } } internal static void BeginLevel() { Zones.Clear(); Placed.Clear(); _zonesBuilt = false; PreSwapped = (PreSkipped = 0); } internal static void BuildZones() { //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) Zones.Clear(); _zonesBuilt = true; Dictionary<(int, int), Module> dictionary = new Dictionary<(int, int), Module>(); Module[] array = Object.FindObjectsByType<Module>((FindObjectsSortMode)0); foreach (Module val in array) { if ((Object)(object)val != (Object)null && Acc.GridX != null && Acc.GridY != null) { dictionary[(Acc.GridX.Invoke(val), Acc.GridY.Invoke(val))] = val; } } foreach (KeyValuePair<(int, int), Module> item in dictionary) { (int, int)[] array2 = new(int, int)[2] { (1, 0), (0, 1) }; for (int i = 0; i < array2.Length; i++) { (int, int) tuple = array2[i]; if (dictionary.TryGetValue((item.Key.Item1 + tuple.Item1, item.Key.Item2 + tuple.Item2), out var value) && !((Object)(object)value == (Object)(object)item.Value)) { Zones.Add(new Zone { P = (((Component)item.Value).transform.position + ((Component)value).transform.position) * 0.5f, R = 1.3f, Kind = "doorway" }); } } } ExtractionPoint[] array3 = Object.FindObjectsByType<ExtractionPoint>((FindObjectsSortMode)0); foreach (ExtractionPoint val2 in array3) { if ((Object)(object)val2 != (Object)null) { Zones.Add(new Zone { P = ((Component)val2).transform.position, R = 2.8f, Kind = "extraction point" }); } } LevelGenerator instance = LevelGenerator.Instance; if ((Object)(object)instance != (Object)null && (Object)(object)instance.LevelPathTruck != (Object)null) { Zones.Add(new Zone { P = ((Component)instance.LevelPathTruck).transform.position, R = 3.5f, Kind = "truck" }); } } internal static bool InZone(Vector3 p, out string kind) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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_0025: Unknown result type (might be due to invalid IL or missing references) kind = null; foreach (Zone zone in Zones) { Vector3 val = p - zone.P; if (!(Mathf.Abs(val.y) > 3f)) { val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude < zone.R * zone.R) { kind = zone.Kind; return true; } } } return false; } internal static bool SpotOk(ValuableVolume v, int size, out string reason) { //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_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0059: 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_0087: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0118: 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_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0128: 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) reason = null; if ((Object)(object)v == (Object)null) { reason = "missing"; return false; } if (!_zonesBuilt) { BuildZones(); } Vector3 position = ((Component)v).transform.position; if (InZone(position, out var kind)) { reason = "in a " + kind; return false; } Vector3 val = VolumeSupply.Box[Mathf.Clamp(size, 0, 6)]; float num = Mathf.Max(val.x, val.z) * 0.5f + 0.25f; foreach (Vector3 item in Placed) { Vector3 val2 = item - position; if (((Vector3)(ref val2)).sqrMagnitude < num * num) { reason = "on top of another valuable"; return false; } } ValuablePropSwitch componentInParent = ((Component)v).GetComponentInParent<ValuablePropSwitch>(); Transform val3 = (((Object)(object)componentInParent != (Object)null && (Object)(object)componentInParent.PropParent != (Object)null) ? componentInParent.PropParent.transform : null); Collider[] array = Physics.OverlapBox(position + ((Component)v).transform.up * (val.y * 0.5f + 0.05f), val * 0.3f, ((Component)v).transform.rotation, Mask, (QueryTriggerInteraction)1); foreach (Collider val4 in array) { if (!((Object)(object)val4 == (Object)null) && (!((Object)(object)val3 != (Object)null) || !((Component)val4).transform.IsChildOf(val3)) && !((Component)val4).transform.IsChildOf(((Component)v).transform)) { reason = (((Object)(object)val4.attachedRigidbody != (Object)null) ? "inside another object" : "inside a wall or prop"); return false; } } return true; } internal static ValuableVolume Alternative(ValuableDirector vd, ValuableVolume bad, int size) { if (!(Acc.Field(typeof(ValuableDirector), Acc.SizeNames[size] + "Volumes")?.GetValue(vd) is List<ValuableVolume> list)) { return null; } int num = list.IndexOf(bad); if (num < 0) { return null; } for (int i = num + 1; i < list.Count; i++) { if (SpotOk(list[i], size, out var _)) { ValuableVolume val = list[i]; list[i] = list[num]; list[num] = val; return val; } } return null; } internal static void OnPlaced(Vector3 p) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) Placed.Add(p); } private static int LimitFor(Module m, int limit) { if (ThemedRooms.Of(m) != LootTheme.JunkRoom) { return limit; } return limit * 2; } internal static void Cleanup(LevelGenerator lg) { //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_03f4: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_0566: Unknown result type (might be due to invalid IL or missing references) //IL_09da: Unknown result type (might be due to invalid IL or missing references) int instanceID = ((Object)lg).GetInstanceID(); if (_cleanedLevel == instanceID) { return; } _cleanedLevel = instanceID; Stopwatch stopwatch = Stopwatch.StartNew(); long num = Cfg.CleanupBudgetMs.Value; if (!_zonesBuilt) { BuildZones(); } List<Module> list = (from m in Object.FindObjectsByType<Module>((FindObjectsSortMode)0) where (Object)(object)m != (Object)null select m).ToList(); if (list.Count == 0) { return; } float num2 = list.Min((Module m) => ((Component)m).transform.position.y) - 8f; int limit = Cfg.PropDensityLimit.Value; List<Obj> list2 = new List<Obj>(); int num3 = 0; int num4 = 0; int num5 = 0; int num6 = 0; int num7 = 0; List<string> list3 = new List<string>(); PhysGrabObject[] array = Object.FindObjectsByType<PhysGrabObject>((FindObjectsSortMode)0); foreach (PhysGrabObject val in array) { if ((Object)(object)val == (Object)null) { continue; } if (list2.Count >= 800) { list3.Add("object cap reached"); break; } ValuableObject component = ((Component)val).GetComponent<ValuableObject>(); bool flag = (Object)(object)component == (Object)null && (Object)(object)((Component)val).GetComponent<NotValuableObject>() != (Object)null; if (((Object)(object)component == (Object)null && !flag) || (Object)(object)((Component)val).GetComponent<ItemAttributes>() != (Object)null || (Object)(object)((Component)val).GetComponent<PhysGrabHinge>() != (Object)null || (Object)(object)((Component)val).GetComponent<PhysGrabCart>() != (Object)null || (Object)(object)((Component)val).GetComponent<CosmeticWorldObject>() != (Object)null || (Object)(object)((Component)val).GetComponentInParent<PlayerAvatar>() != (Object)null || (Object)(object)((Component)val).GetComponentInParent<EnemyRigidbody>() != (Object)null || (Object)(object)((Component)val).GetComponentInParent<ExtractionPoint>() != (Object)null) { continue; } Obj obj = new Obj { G = val, V = component, Loose = flag, Pos = Center(val) }; obj.Value = (((Object)(object)component != (Object)null && Acc.DollarValueCurrent != null) ? Acc.DollarValueCurrent.Invoke(component) : 0f); obj.Room = Nearest(list, obj.Pos); if ((Object)(object)val.rb == (Object)null || !HasSolidCollider(val) || ((Object)(object)component != (Object)null && (Object)(object)component.valuePreset == (Object)null)) { if (Remove(val)) { num3++; num7++; } } else { list2.Add(obj); } } List<ValuableVolume> spots = (from v in Object.FindObjectsByType<ValuableVolume>((FindObjectsSortMode)0) where (Object)(object)v != (Object)null select v).ToList(); List<Vector3> occupied = (from obj2 in list2 where !obj2.Loose select obj2.Pos).ToList(); Dictionary<Module, int> perRoom = new Dictionary<Module, int>(); foreach (Obj item in list2) { if ((Object)(object)item.Room != (Object)null) { perRoom[item.Room] = (perRoom.TryGetValue(item.Room, out var value) ? value : 0) + 1; } } foreach (Obj item2 in list2) { if (stopwatch.ElapsedMilliseconds > num * 4 || num3 + num5 + num4 >= 120) { list3.Add("hard limit reached during the important fixes"); break; } string text = null; string kind; if (item2.Pos.y < num2) { text = "fell out of the level"; } else if (InZone(item2.Pos, out kind)) { text = "blocking a " + kind; } else if (!item2.Loose && Stuck(item2.G)) { text = "stuck in a wall or prop"; } if (text == null) { continue; } if (item2.Loose) { if (text.StartsWith("blocking") && Nudge(item2, list)) { num4++; } else if (Remove(item2.G)) { num3++; item2.G = null; } } else if (Replace(item2, null)) { num5++; } else { num6++; } if (Cfg.DebugLogging.Value) { list3.Add(Name(item2) + ": " + text); } } list2.RemoveAll((Obj obj2) => (Object)(object)obj2.G == (Object)null); bool flag2 = false; List<Obj> list4 = new List<Obj>(); NavMeshHit val2 = default(NavMeshHit); foreach (Obj o in list2) { if (stopwatch.ElapsedMilliseconds > num || num3 + num5 + num4 >= 120) { flag2 = true; break; } if (o.Loose) { continue; } string text2 = null; if (!NavMesh.SamplePosition(o.Pos, ref val2, 4f, -1)) { text2 = "out of reach"; } else if (list4.Any(delegate(Obj s) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) Vector3 val3 = s.Pos - o.Pos; return ((Vector3)(ref val3)).sqrMagnitude < 0.20249999f; })) { text2 = "on top of another valuable"; } if (text2 == null) { list4.Add(o); continue; } if (Replace(o, null)) { num5++; if (Cfg.DebugLogging.Value) { list3.Add(Name(o) + ": " + text2); } } else { num6++; } list4.Add(o); } if (!flag2) { foreach (IGrouping<string, Obj> item3 in from obj2 in list2 where obj2.Loose && (Object)(object)obj2.G != (Object)null group obj2 by BaseName(((Object)obj2.G).name)) { List<Obj> list5 = item3.ToList(); int i; for (i = 0; i < list5.Count; i++) { if ((Object)(object)list5[i].G == (Object)null) { continue; } List<Obj> list6 = list5.Where(delegate(Obj obj2) { //IL_000f: 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_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) if ((Object)(object)obj2.G != (Object)null) { Vector3 val3 = obj2.Pos - list5[i].Pos; return ((Vector3)(ref val3)).sqrMagnitude < 0.25f; } return false; }).ToList(); if (list6.Count < 3) { continue; } foreach (Obj item4 in list6.Skip(1)) { if (Remove(item4.G)) { num3++; item4.G = null; } } if (Cfg.DebugLogging.Value) { list3.Add($"pile of {list6.Count} '{item3.Key}' cleared"); } } } list2.RemoveAll((Obj obj2) => (Object)(object)obj2.G == (Object)null); } if (!flag2 && stopwatch.ElapsedMilliseconds <= num) { foreach (Module room in (from kv in perRoom where kv.Value > LimitFor(kv.Key, limit) select kv.Key).ToList()) { List<Obj> list7 = (from obj2 in list2 where (Object)(object)obj2.Room == (Object)(object)room orderby (!obj2.Loose) ? 1 : 0, obj2.Value select obj2).ToList(); int num9 = perRoom[room] - LimitFor(room, limit); foreach (Obj item5 in list7) { if (num9 <= 0 || stopwatch.ElapsedMilliseconds > num) { break; } if (item5.Loose) { if (Remove(item5.G)) { num3++; num9--; perRoom[room]--; } } else if (Replace(item5, room)) { num5++; num9--; } } if (Cfg.DebugLogging.Value) { list3.Add($"room at {((Component)room).transform.position} had {perRoom[room] + num9} objects (limit {limit})"); } } } else { flag2 = true; } stopwatch.Stop(); bool flag3 = num3 + num4 + num5 + num6 + PreSwapped + PreSkipped > 0; if (Cfg.DebugLogging.Value || flag3) { Plugin.Log.LogInfo((object)($"[clutter] spawn spots swapped {PreSwapped}, left for cleanup {PreSkipped}; after build: valuables re-placed {num5}, props moved {num4}, removed {num3}" + ((num7 > 0) ? (" (" + num7 + " broken)") : "") + ((num6 > 0) ? (", could not fix " + num6) : "") + string.Format("{0} ({1:0.0} ms)", flag2 ? ", time budget reached (the rest is left as the game placed it)" : "", stopwatch.Elapsed.TotalMilliseconds) + ((Cfg.DebugLogging.Value && list3.Count > 0) ? ("\n " + string.Join("\n ", list3.Take(40))) : ""))); } bool Replace(Obj obj2, Module avoid) { //IL_0006: 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_0051: 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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_02ca: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_02e7: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) int num10 = Acc.SizeIndex(obj2.V.volumeType); if (num10 < 0) { return false; } List<(ValuableVolume, Module)> list8 = new List<(ValuableVolume, Module)>(); NavMeshHit val5 = default(NavMeshHit); foreach (ValuableVolume item6 in spots) { if (Acc.SizeIndex(item6.VolumeType) == num10) { Vector3 position = ((Component)item6).transform.position; if (!InZone(position, out var _)) { bool flag4 = false; foreach (Vector3 item7 in occupied) { Vector3 val3 = item7 - position; if (((Vector3)(ref val3)).sqrMagnitude < 0.64000005f) { flag4 = true; break; } } if (!flag4) { Module val4 = (((Object)(object)item6.Module != (Object)null) ? item6.Module : ((Component)item6).GetComponentInParent<Module>()); if (!((Object)(object)val4 == (Object)null) && !((Object)(object)val4 == (Object)(object)avoid) && (!perRoom.TryGetValue(val4, out var value2) || value2 < LimitFor(val4, limit)) && ThemedRooms.Of(val4) == LootTheme.None && NavMesh.SamplePosition(position, ref val5, 2.5f, -1)) { Vector3 val6 = VolumeSupply.Box[num10]; if (!Physics.CheckBox(position + ((Component)item6).transform.up * (val6.y * 0.5f + 0.05f), val6 * 0.3f, ((Component)item6).transform.rotation, Mask, (QueryTriggerInteraction)1)) { list8.Add((item6, val4)); if (list8.Count >= 24) { break; } } } } } } } if (list8.Count == 0) { return false; } List<double> weights = list8.Select<(ValuableVolume, Module), double>(((ValuableVolume v, Module m) t) => 1.0 + (double)Cfg.DepthGradient.Value * 2.0 * MapState.DepthOf(t.m)).ToList(); (ValuableVolume, Module) tuple = list8[Math.Max(0, MapState.Rng.PickWeighted(weights))]; float num11 = 0.1f + HalfHeight(obj2.G); Teleport(obj2.G, ((Component)tuple.Item1).transform.position + Vector3.up * num11, ((Component)tuple.Item1).transform.rotation); occupied.Remove(obj2.Pos); if ((Object)(object)obj2.Room != (Object)null && perRoom.ContainsKey(obj2.Room)) { perRoom[obj2.Room]--; } obj2.Pos = ((Component)tuple.Item1).transform.position; obj2.Room = tuple.Item2; occupied.Add(obj2.Pos); perRoom[tuple.Item2] = (perRoom.TryGetValue(tuple.Item2, out var value3) ? value3 : 0) + 1; return true; } } private static Vector3 Center(PhysGrabObject g) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)g.rb != (Object)null)) { return ((Component)g).transform.position; } return g.rb.worldCenterOfMass; } private static Module Nearest(List<Module> modules, Vector3 p) { //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_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) Module result = null; float num = float.MaxValue; foreach (Module module in modules) { Vector3 val = ((Component)module).transform.position - p; val.y = 0f; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (sqrMagnitude < num) { num = sqrMagnitude; result = module; } } return result; } private static bool HasSolidCollider(PhysGrabObject g) { Collider[] componentsInChildren = ((Component)g).GetComponentsInChildren<Collider>(); foreach (Collider val in componentsInChildren) { if ((Object)(object)val != (Object)null && !val.isTrigger && val.enabled) { return true; } } return false; } private static float HalfHeight(PhysGrabObject g) { //IL_0004: 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_0040: 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_0037: Unknown result type (might be due to invalid IL or missing references) bool flag = false; Bounds val = default(Bounds); Collider[] componentsInChildren = ((Component)g).GetComponentsInChildren<Collider>(); foreach (Collider val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null) && !val2.isTrigger) { if (!flag) { val = val2.bounds; flag = true; } else { ((Bounds)(ref val)).Encapsulate(val2.bounds); } } } if (!flag) { return 0.3f; } return ((Bounds)(ref val)).extents.y; } private static bool Stuck(PhysGrabObject g) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0069: 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_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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) Collider[] componentsInChildren = ((Component)g).GetComponentsInChildren<Collider>(); bool flag = false; Bounds val = default(Bounds); Collider[] array = componentsInChildren; foreach (Collider val2 in array) { if (!((Object)(object)val2 == (Object)null) && !val2.isTrigger) { if (!flag) { val = val2.bounds; flag = true; } else { ((Bounds)(ref val)).Encapsulate(val2.bounds); } } } if (!flag) { return false; } array = Physics.OverlapBox(((Bounds)(ref val)).center, ((Bounds)(ref val)).extents * 0.2f, Quaternion.identity, Mask, (QueryTriggerInteraction)1); foreach (Collider val3 in array) { if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val3.attachedRigidbody != (Object)null) && Array.IndexOf(componentsInChildren, val3) < 0) { return true; } } return false; } private static bool Nudge(Obj o, List<Module> modules) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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_0033: 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_0056: 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: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: 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) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: 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_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) Module val = o.Room ?? Nearest(modules, o.Pos); if ((Object)(object)val == (Object)null) { return false; } Vector3 val2 = ((Component)val).transform.position - o.Pos; val2.y = 0f; if (((Vector3)(ref val2)).sqrMagnitude < 0.01f) { return false; } RaycastHit val3 = default(RaycastHit); if (!Physics.Raycast(o.Pos + ((Vector3)(ref val2)).normalized * 2.2f + Vector3.up * 2f, Vector3.down, ref val3, 5f, Mask, (QueryTriggerInteraction)1) || ((RaycastHit)(ref val3)).normal.y < 0.8f) { return false; } if (InZone(((RaycastHit)(ref val3)).point, out var _)) { return false; } Teleport(o.G, ((RaycastHit)(ref val3)).point + Vector3.up * (0.1f + HalfHeight(o.G)), ((Component)o.G).transform.rotation); o.Pos = ((RaycastHit)(ref val3)).point; return true; } private static void Teleport(PhysGrabObject g, Vector3 pos, Quaternion rot) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: 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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) try { g.Teleport(pos, rot); } catch { ((Component)g).transform.SetPositionAndRotation(pos, rot); if ((Object)(object)g.rb != (Object)null) { g.rb.position = pos; g.rb.rotation = rot; } } if ((Object)(object)g.rb != (Object)null && !g.rb.isKinematic) { g.rb.linearVelocity = Vector3.zero; g.rb.angularVelocity = Vector3.zero; } } private static bool Remove(PhysGrabObject g) { if ((Object)(object)g == (Object)null) { return false; } try { PhotonView component = ((Component)g).GetComponent<PhotonView>(); if (SemiFunc.IsMultiplayer() && (Object)(object)component != (Object)null) { if (!PhotonNetwork.IsMasterClient) { return false; } PhotonNetwork.Destroy(((Component)g).gameObject); } else { Object.Destroy((Object)(object)((Component)g).gameObject); } return true; } catch (Exception ex) { Plugin.Log.LogInfo((object)("[clutter] could not remove " + ((Object)g).name + ": " + ex.Message)); return false; } } private static string BaseName(string n) { int num = n.IndexOf("(Clone)", StringComparison.Ordinal); return ((num > 0) ? n.Substring(0, num) : n).Trim(); } private static string Name(Obj o) { if (!((Object)(object)o.G != (Object)null)) { return "object"; } return BaseName(((Object)o.G).name); } } internal static class Compat { internal static bool OtherModsPatchTileLayout() { HashSet<string> hashSet = new HashSet<string>(); MethodInfo methodInfo = AccessTools.Method(typeof(LevelGenerator), "TileGeneration", (Type[])null, (Type[])null); Collect(methodInfo, hashSet); if (methodInfo != null) { Collect(AccessTools.EnumeratorMoveNext((MethodBase)methodInfo), hashSet); } hashSet.Remove("interestinglevels.repo"); if (hashSet.Count > 0) { Plugin.Log.LogInfo((object)("[compat] other mods also patch the tile layout (the game's layout is kept unless you turn off \"Stand down for other layout mods\"): " + string.Join(", ", hashSet))); } return hashSet.Count > 0; } private static void Collect(MethodBase m, HashSet<string> owners) { if (m == null) { return; } Patches patchInfo = Harmony.GetPatchInfo(m); if (patchInfo == null) { return; } foreach (Patch item in patchInfo.Prefixes.Concat(patchInfo.Postfixes).Concat(patchInfo.Transpilers).Concat(patchInfo.Finalizers)) { owners.Add(item.owner); } } } public static class MapInfo { public static bool HasMap { get { if (MapState.Plan != null && (Object)(object)LevelGenerator.Instance != (Object)null) { return MapState.LevelId == ((Object)LevelGenerator.Instance).GetInstanceID(); } return false; } } public static string Shape { get { if (HasMap) { if (!MapState.FromLayout) { return "Game"; } return MapState.Shape.ToString(); } return ""; } } public static string Modifier => MapState.Modifier.ToString(); public static float DepthOf(Module module) { if (!HasMap) { return 0.5f; } return (float)MapState.DepthOf(module); } public static float DepthAt(Vector3 position) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) Module val = ModuleAt(position); if (!((Object)(object)val != (Object)null)) { return 0.5f; } return DepthOf(val); } public static string SpecialRoomOf(Module module) { if (!HasMap) { return "None"; } return MapState.TagOf(module).ToString(); } public static Module ModuleAt(Vector3 position) { //IL_002e: 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_0039: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)LevelGenerator.Instance == (Object)null) { return null; } Module result = null; float num = float.MaxValue; Module[] array = Object.FindObjectsByType<Module>((FindObjectsSortMode)0); foreach (Module val in array) { Vector3 val2 = ((Component)val).transform.position - position; val2.y = 0f; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (sqrMagnitude < num) { num = sqrMagnitude; result = val; } } return result; } } internal static class HistoryStore { private static History _h; private static bool _saveFailedLogged; internal static string FilePath => Path.Combine(Paths.ConfigPath, "InterestingLevels.history.txt"); internal static History H { get { if (_h == null) { string text = History.TryLoad(FilePath, Cfg.HistoryLength.Value, out _h); if (text.Length > 0) { Plugin.Log.LogInfo((object)("[history] " + text)); } _h.Length = Cfg.HistoryLength.Value; Plugin.Log.LogInfo((object)$"[history] {_h.MapCount} recent map(s) remembered from earlier sessions."); } return _h; } } internal static int MapCount => _h?.MapCount ?? 0; internal static void Record(Fingerprint f) { if (f == null) { return; } H.Length = Cfg.HistoryLength.Value; H.Record(f); try { H.Save(FilePath); } catch (Exception ex) { if (!_saveFailedLogged) { _saveFailedLogged = true; Plugin.Log.LogInfo((object)("[history] could not save (it still works for this session): " + ex.Message)); } } } internal static MakeConfig MakeConfig(bool verticalKnown, long budgetMs) { MakeConfig makeConfig = new MakeConfig(); makeConfig.ShapeWeights = new double[4] { Cfg.WeightClassic.Value, Cfg.WeightWinding.Value, Cfg.WeightHub.Value, Cfg.WeightCompact.Value }; makeConfig.LoopFrequency = Cfg.LoopFrequency.Value; makeConfig.BranchFrequency = Cfg.BranchFrequency.Value; makeConfig.ModifiersOn = Cfg.Modifiers.Value; makeConfig.ModifierChance = Cfg.ModifierChance.Value; makeConfig.ModifierWeights = new double[7] { Cfg.WeightSprawling.Value, Cfg.WeightLabyrinth.Value, Cfg.WeightTreasurePocket.Value, Cfg.WeightGoldRush.Value, Cfg.WeightLongHaul.Value, Cfg.WeightCrowded.Value, Cfg.WeightScavengerHunt.Value }; makeConfig.CenterpieceChance = (Cfg.Centerpieces.Value ? Cfg.CenterpieceChance.Value : 0f); makeConfig.ShortcutChance = (Cfg.Shortcuts.Value ? Cfg.ShortcutChance.Value : 0f); makeConfig.Themes = new ThemeSettings { Enabled = Cfg.ThemedRooms.Value, Chance = Cfg.ThemedRoomChance.Value, Max = Cfg.MaxThemedRooms.Value, Weights = new double[3] { Cfg.WeightFragileGallery.Value, Cfg.WeightHeavyStorage.Value, Cfg.WeightJunkRoom.Value } }; makeConfig.Special = MapState.SpecialSettings(forceVault: false); makeConfig.Freshness = Cfg.FreshnessStrength.Value; makeConfig.SimilarityThreshold = Cfg.SimilarityThreshold.Value; makeConfig.MaxTries = Cfg.MaxRegenerations.Value; makeConfig.SurpriseChance = Cfg.SurpriseChance.Value; makeConfig.VerticalRoomsKnown = verticalKnown; makeConfig.BudgetMs = budgetMs; return makeConfig; } } internal static class Freshness { private static readonly Dictionary<string, Vector3> LastRotation = new Dictionary<string, Vector3>(); private static readonly Dictionary<string, HashSet<string>> LastSpots = new Dictionary<string, HashSet<string>>(); private static readonly Dictionary<string, HashSet<string>> SpotsThisLevel = new Dictionary<string, HashSet<string>>(); private static readonly FieldInfo ModuleRotations = Acc.Field(typeof(LevelGenerator), "ModuleRotations"); internal static double Strength => Cfg.FreshnessStrength.Value; internal static void BeginLevel() { foreach (KeyValuePair<string, HashSet<string>> item in SpotsThisLevel) { LastSpots[item.Key] = item.Value; } SpotsThisLevel.Clear(); } internal static void DemoteRecentModules(LevelGenerator lg) { double strength = Strength; if (strength <= 0.0 || (Object)(object)lg.Level == (Object)null) { return; } IReadOnlyList<string> readOnlyList = HistoryStore.H.Recent("module:" + ((Object)lg.Level).name); if (readOnlyList.Count == 0) { return; } Dictionary<string, int> dictionary = new Dictionary<string, int>(); for (int num = readOnlyList.Count - 1; num >= 0; num--) { dictionary[readOnlyList[num]] = num; } int num2 = 0; string[] array = new string[5] { "Normal", "Passage", "DeadEnd", "Extraction", "Mega" }; foreach (string type in array) { for (int j = 1; j <= 3; j++) { List<PrefabRef> list = Acc.ShuffledList(lg, type, j); if (list == null || list.Count < 2) { continue; } List<PrefabRef> list2 = new List<PrefabRef>(); List<(PrefabRef, int)> list3 = new List<(PrefabRef, int)>(); foreach (PrefabRef item in list) { string key = ((PrefabRef<GameObject>)(object)item)?.ResourcePath ?? ""; if (dictionary.TryGetValue(key, out var value) && MapState.Rng.Chance(strength * (1.0 - (double)value / (double)(readOnlyList.Count + 4)))) { list3.Add((item, value)); } else { list2.Add(item); } } if (list3.Count != 0 && list2.Count != 0) { list3.Sort(((PrefabRef p, int r) a, (PrefabRef p, int r) b) => b.r.CompareTo(a.r)); list.Clear(); list.AddRange(list2); list.AddRange(list3.Select<(PrefabRef, int), PrefabRef>(((PrefabRef p, int r) b) => b.p)); num2 += list3.Count; } } } if (num2 > 0 && Cfg.DebugLogging.Value) { Plugin.Log.LogInfo((object)$"[fresh] {num2} recently used room(s) moved to the back of the pick order."); } } internal static void VaryRotation(LevelGenerator lg, Type type, int x, int y) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result