Decompiled source of LabyrinthianFacilities v0.7.3
LabyrinthianFacilities.dll
Decompiled 2 weeks 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.Collections.ObjectModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using BoundsExtensions; using DunGen; using DunGen.Graph; using HarmonyLib; using LabyrinthianFacilities.Compatibility; using LabyrinthianFacilities.NetcodePatcher; using LabyrinthianFacilities.Patches; using LabyrinthianFacilities.Serialization; using LabyrinthianFacilities.Util; using Microsoft.CodeAnalysis; using TMPro; using Unity.AI.Navigation; using Unity.Netcode; using UnityEngine; using UnityEngine.AI; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("LabyrinthianFacilities")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("LabyrinthianFacilities")] [assembly: AssemblyTitle("LabyrinthianFacilities")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [module: NetcodePatchedAssembly] internal class <Module> { static <Module>() { } } namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace LabyrinthianFacilities { public class Config { internal static ConfigFile ConfigFile; private static Config singleton; private ConfigEntry<bool> m_GlobalEnable; private ConfigEntry<bool> m_EnableNoncollectionPenalty; private ConfigEntry<bool> m_ExcludeCruiserScrap; private ConfigEntry<bool> m_ExcludeSurfaceScrap; private ConfigEntry<bool> m_ExcludeHive; private ConfigEntry<bool> m_SaveGrabbableMapObjects; private ConfigEntry<bool> m_SaveEquipment; private ConfigEntry<bool> m_SaveScrap; private ConfigEntry<bool> m_SaveHives; private ConfigEntry<bool> m_SaveCruisers; private ConfigEntry<bool> m_SaveHazards; private ConfigEntry<bool> m_SaveTurrets; private ConfigEntry<bool> m_SaveLandmines; private ConfigEntry<bool> m_SaveSpikeTraps; private ConfigEntry<bool> m_UseCustomGeneration; private ConfigEntry<bool> m_SaveMaps; private ConfigEntry<float> m_MinimumTileMultiplier; private ConfigEntry<float> m_MaximumTileMultiplier; private ConfigEntry<float> m_LowerIterationMultiplier; private ConfigEntry<float> m_UpperIterationMultiplier; private ConfigEntry<string> m_BlacklistedInteriors; private ConfigEntry<bool> m_BouncyCruisers; private ConfigEntry<bool> m_ForbiddenPassages; private ConfigEntry<LogLevel> m_LogLevels; private ConfigEntry<bool> m_EnableVerboseGeneration; private ConfigEntry<bool> m_EnableVerboseSerialization; private ConfigEntry<bool> m_EnableVerboseDeserialization; private ConfigEntry<bool> m_EnableHistory; private ConfigEntry<bool> m_UseSetSeed; private ConfigEntry<int> m_Seed; private ConfigEntry<bool> m_IncrementSetSeed; private string p_blacklistedInteriorsString; public static Config Singleton => singleton ?? (singleton = new Config()); public bool GlobalEnable { get; set; } public bool EnableNoncollectionPenalty { get; set; } public bool ExcludeCruiserScrap { get; set; } public bool ExcludeSurfaceScrap { get; set; } public bool ExcludeHive { get; set; } public bool SaveGrabbableMapObjects { get; set; } public bool SaveEquipment { get; set; } public bool SaveScrap { get; set; } public bool SaveHives { get; set; } public bool SaveCruisers { get; set; } public bool SaveHazards { get; set; } public bool SaveTurrets { get; set; } public bool SaveLandmines { get; set; } public bool SaveSpikeTraps { get; set; } public bool UseCustomGeneration { get; set; } public bool SaveMaps { get; set; } public float MinimumTileMultiplier { get; set; } public float MaximumTileMultiplier { get; set; } public float LowerIterationMultiplier { get; set; } public float UpperIterationMultiplier { get; set; } public string BlacklistedInteriorsString { get { return p_blacklistedInteriorsString; } set { p_blacklistedInteriorsString = value; BlacklistedInteriors = GetBlacklistedInteriors(); } } public bool BouncyCruisers { get; set; } public bool ForbiddenPassages { get; set; } public LogLevel LogLevels { get; set; } public bool EnableVerboseGeneration { get; set; } public bool EnableVerboseSerialization { get; set; } public bool EnableVerboseDeserialization { get; set; } public bool EnableHistory { get; set; } public bool UseSetSeed { get; set; } public int Seed { get; set; } public bool IncrementSetSeed { get; set; } public HashSet<string> BlacklistedInteriors { get; private set; } public Config() { if (singleton != null) { throw new InvalidOperationException("Singleton violation"); } singleton = this; ConfigFile configFile = ConfigFile; configFile.SaveOnConfigSet = false; string text = "Features"; m_GlobalEnable = configFile.Bind<bool>(text, "GlobalEnable", true, "Enables the mod. Set this to false if you want to hurt my feelings. "); text = "Features.NoncollectionPenalty"; m_EnableNoncollectionPenalty = configFile.Bind<bool>(text, "EnableNoncollectionPenalty", true, "NOT YET IMPLEMENTED; Generates less scrap the next day if there is already scrap from days prior. "); m_ExcludeSurfaceScrap = configFile.Bind<bool>(text, "ExcludeSurfaceScrap", false, "NOT YET IMPLEMENTED; Exclude scrap at the surface when considering noncollection penalty\n(Requires EnableNoncollectionPenalty)"); m_ExcludeCruiserScrap = configFile.Bind<bool>(text, "ExcludeCruiserScrap", false, "NOT YET IMPLEMENTED; Exclude scrap in cruisers when considering noncollection penalty\n(Requires EnableNoncollectionPenalty)"); m_ExcludeHive = configFile.Bind<bool>(text, "ExcludeHive", true, "NOT YET IMPLEMENTED; Exclude beehives when considering noncollection penalty\n(Requires EnableNoncollectionPenalty)"); text = "Features.MapObjects"; m_SaveGrabbableMapObjects = configFile.Bind<bool>(text, "SaveGrabbableMapObjects", true, "Save 'GrabbableMapObjects' (basically scrap & equipment)"); m_SaveEquipment = configFile.Bind<bool>(text, "SaveEquipment", true, "Save Equipment (Requires SaveGrabbableMapObjects)"); m_SaveScrap = configFile.Bind<bool>(text, "SaveScrap", true, "Save Scrap (Requires SaveGrabbableMapObjects)"); m_SaveHives = configFile.Bind<bool>(text, "SaveHives", true, "Save Beehives (Requires SaveGrabbableMapObjects)"); m_SaveCruisers = configFile.Bind<bool>(text, "SaveCruisers", true, "Save Cruisers"); text = "Features.Hazards"; m_SaveHazards = configFile.Bind<bool>(text, "SaveHazards", false, "Save Hazards (turrets, landmines, etc.)"); m_SaveTurrets = configFile.Bind<bool>(text, "SaveTurrets", true, "Save Turrets (Requires SaveHazards)"); m_SaveLandmines = configFile.Bind<bool>(text, "SaveLandmines", true, "Save Landmines (Requires SaveHazards)"); m_SaveSpikeTraps = configFile.Bind<bool>(text, "SaveSpikeTraps", true, "Save Spike Traps (Requires SaveHazards)"); text = "Features.InteriorGeneration"; m_UseCustomGeneration = configFile.Bind<bool>(text, "UseCustomGeneration", true, "Use Custom Generation"); m_SaveMaps = configFile.Bind<bool>(text, "SaveMaps", true, "Save interiors (Requires UseCustomGeneration)"); m_MinimumTileMultiplier = configFile.Bind<float>(text, "MinimumTileMultiplier", 2.5f, "Multiplier for the minimum amount of tiles. Multiplies by the average amount of main tiles that would be generated by DunGen. (Requires UseCustomGeneration)"); m_MaximumTileMultiplier = configFile.Bind<float>(text, "MaximumTileMultiplier", 6f, "Multiplier for the maximum amount of tiles. Multiplies by the average amount of main tiles that would be generated by DunGen. (Requires UseCustomGeneration)"); m_LowerIterationMultiplier = configFile.Bind<float>(text, "LowerIterationMultiplier", 1f, "Multiplier for the minimum amount of tiles to generate in a single day. Multiplies by the the result of MinimumTileMultiplier's multiplication. (Requires UseCustomGeneration)"); m_UpperIterationMultiplier = configFile.Bind<float>(text, "UpperIterationMultiplier", 1.5f, "Multiplier for the maximum amount of tiles to generate in a single day. Multiplies by the the result of *Minimum*TileMultiplier's multiplication. (Requires UseCustomGeneration)"); m_BlacklistedInteriors = configFile.Bind<string>(text, "BlacklistedInteriors", "", "Comma separated list of the names of dungeon flows that should not use custom interior generation. This is typically reserved for interiors that do not generate correctly. See LethalLevelLoader's config for the names of dungeon flows. Case Sensitive. "); text = "Features.EasterEggs"; m_BouncyCruisers = configFile.Bind<bool>(text, "BouncyCruisers", false, "The magic word is '" + EasterEggDetection.cruiserMagicWord + "'"); m_ForbiddenPassages = configFile.Bind<bool>(text, "ForbiddenPassages", false, "...?"); text = "Debug.Logging"; m_LogLevels = configFile.Bind<LogLevel>(text, "LogLevels", (LogLevel)63, "Which log levels to show in the console"); m_EnableVerboseGeneration = configFile.Bind<bool>(text, "EnableVerboseGeneration", false, "Enables verbose logging for generation\n(Requires LogLevels contains Debug)"); m_EnableVerboseSerialization = configFile.Bind<bool>(text, "EnableVerboseSerialization", false, "Enables verbose logging for serialization (used for saving maps & sending data to clients)\n(Requires LogLevels contains Debug)"); m_EnableVerboseDeserialization = configFile.Bind<bool>(text, "EnableVerboseDeserialization", false, "Enables verbose logging for deserialization (used for loading maps & receiving data from server)\n(Requires LogLevels contains Debug)"); text = "Debug.History"; m_EnableHistory = configFile.Bind<bool>(text, "EnableHistory", true, "Enables recording of seeds, interiors, and moons each day, for each save. Located in the same place as savedata. "); text = "Features.SetSeed"; m_UseSetSeed = configFile.Bind<bool>(text, "UseSetSeed", false, "Enables the set seed\n(The set seed only affects tile generation; it does not affect weather, sales, or which interior is chosen)"); m_Seed = configFile.Bind<int>(text, "Seed", 0, "The seed to use for set seed"); m_IncrementSetSeed = configFile.Bind<bool>(text, "IncrementSetSeed", true, "Whether to increment the set seed daily"); configFile.Save(); configFile.SaveOnConfigSet = true; InitFromConfigFile(); } public void InitFromConfigFile() { //IL_0194: Unknown result type (might be due to invalid IL or missing references) GlobalEnable = m_GlobalEnable.Value; EnableNoncollectionPenalty = m_EnableNoncollectionPenalty.Value; ExcludeCruiserScrap = m_ExcludeCruiserScrap.Value; ExcludeSurfaceScrap = m_ExcludeSurfaceScrap.Value; ExcludeHive = m_ExcludeHive.Value; SaveGrabbableMapObjects = m_SaveGrabbableMapObjects.Value; SaveEquipment = m_SaveEquipment.Value; SaveScrap = m_SaveScrap.Value; SaveHives = m_SaveHives.Value; SaveCruisers = m_SaveCruisers.Value; SaveHazards = m_SaveHazards.Value; SaveTurrets = m_SaveTurrets.Value; SaveLandmines = m_SaveLandmines.Value; SaveSpikeTraps = m_SaveSpikeTraps.Value; UseCustomGeneration = m_UseCustomGeneration.Value; SaveMaps = m_SaveMaps.Value; MinimumTileMultiplier = m_MinimumTileMultiplier.Value; MaximumTileMultiplier = m_MaximumTileMultiplier.Value; LowerIterationMultiplier = m_LowerIterationMultiplier.Value; UpperIterationMultiplier = m_UpperIterationMultiplier.Value; BouncyCruisers = m_BouncyCruisers.Value; ForbiddenPassages = m_ForbiddenPassages.Value; LogLevels = m_LogLevels.Value; EnableVerboseGeneration = m_EnableVerboseGeneration.Value; EnableVerboseSerialization = m_EnableVerboseSerialization.Value; EnableVerboseDeserialization = m_EnableVerboseDeserialization.Value; EnableHistory = m_EnableHistory.Value; UseSetSeed = m_UseSetSeed.Value; Seed = m_Seed.Value; IncrementSetSeed = m_IncrementSetSeed.Value; BlacklistedInteriorsString = m_BlacklistedInteriors.Value; } private HashSet<string> GetBlacklistedInteriors() { HashSet<string> hashSet = new HashSet<string>(); string blacklistedInteriorsString = BlacklistedInteriorsString; int num = 0; for (int i = 0; i < blacklistedInteriorsString.Length; i++) { if (blacklistedInteriorsString[i] == ',') { hashSet.Add(blacklistedInteriorsString.Substring(num, num - i).Trim()); num = i + 1; } } if (num != blacklistedInteriorsString.Length) { hashSet.Add(blacklistedInteriorsString.Substring(num).Trim()); } return hashSet; } } public class ConfigNetworkSerializer<T> : Serializer<T> where T : Config { public override void Serialize(SerializationContext sc, T tgt) { sc.AddBools(new <>z__ReadOnlyArray<bool>(new bool[21] { tgt.GlobalEnable, tgt.EnableNoncollectionPenalty, tgt.ExcludeCruiserScrap, tgt.ExcludeSurfaceScrap, tgt.ExcludeHive, tgt.SaveGrabbableMapObjects, tgt.SaveEquipment, tgt.SaveScrap, tgt.SaveHives, tgt.SaveCruisers, tgt.SaveHazards, tgt.SaveTurrets, tgt.SaveLandmines, tgt.SaveSpikeTraps, tgt.UseCustomGeneration, tgt.SaveMaps, tgt.BouncyCruisers, tgt.ForbiddenPassages, tgt.EnableHistory, tgt.UseSetSeed, tgt.IncrementSetSeed }), (bool b) => b); sc.Add(tgt.MinimumTileMultiplier); sc.Add(tgt.MaximumTileMultiplier); sc.Add(tgt.LowerIterationMultiplier); sc.Add(tgt.UpperIterationMultiplier); sc.Add(tgt.Seed); sc.Add(tgt.BlacklistedInteriorsString); sc.Add((byte)0); } protected override T Deserialize(T rt, DeserializationContext dc) { IEnumerator<bool> enumerator = dc.ConsumeBools(21uL).GetEnumerator(); enumerator.MoveNext(); rt.GlobalEnable = enumerator.Current; enumerator.MoveNext(); rt.EnableNoncollectionPenalty = enumerator.Current; enumerator.MoveNext(); rt.ExcludeCruiserScrap = enumerator.Current; enumerator.MoveNext(); rt.ExcludeSurfaceScrap = enumerator.Current; enumerator.MoveNext(); rt.ExcludeHive = enumerator.Current; enumerator.MoveNext(); rt.SaveGrabbableMapObjects = enumerator.Current; enumerator.MoveNext(); rt.SaveEquipment = enumerator.Current; enumerator.MoveNext(); rt.SaveScrap = enumerator.Current; enumerator.MoveNext(); rt.SaveHives = enumerator.Current; enumerator.MoveNext(); rt.SaveCruisers = enumerator.Current; enumerator.MoveNext(); rt.SaveHazards = enumerator.Current; enumerator.MoveNext(); rt.SaveTurrets = enumerator.Current; enumerator.MoveNext(); rt.SaveLandmines = enumerator.Current; enumerator.MoveNext(); rt.SaveSpikeTraps = enumerator.Current; enumerator.MoveNext(); rt.UseCustomGeneration = enumerator.Current; enumerator.MoveNext(); rt.SaveMaps = enumerator.Current; enumerator.MoveNext(); rt.BouncyCruisers = enumerator.Current; enumerator.MoveNext(); rt.ForbiddenPassages = enumerator.Current; enumerator.MoveNext(); rt.EnableHistory = enumerator.Current; enumerator.MoveNext(); rt.UseSetSeed = enumerator.Current; enumerator.MoveNext(); rt.IncrementSetSeed = enumerator.Current; dc.Consume(4).CastInto(out float o); rt.MinimumTileMultiplier = o; dc.Consume(4).CastInto(out o); rt.MaximumTileMultiplier = o; dc.Consume(4).CastInto(out o); rt.LowerIterationMultiplier = o; dc.Consume(4).CastInto(out o); rt.UpperIterationMultiplier = o; dc.Consume(4).CastInto(out int o2); rt.Seed = o2; dc.ConsumeUntil((byte b) => b == 0).CastInto(out string str); rt.BlacklistedInteriorsString = str; dc.Consume(1); return rt; } public override T Deserialize(DeserializationContext dc) { return Deserialize((T)Config.Singleton, dc); } } public interface IDoorwayManager : ICollection<Doorway>, IEnumerable<Doorway>, IEnumerable { IChoice<Doorway, float> GetLeaves(Func<Doorway, float> weightFunction); IChoice<Connection, float> GetPotentialConnections(Func<Connection, float> weightFunction); IChoice<Connection, float> GetActiveConnections(Func<Connection, float> weightFunction); } public class DoorwayManager : IDoorwayManager, ICollection<Doorway>, IEnumerable<Doorway>, IEnumerable { public enum DoorType { LEAF, ACTIVE_CONNECTOR, POTENTIAL_CONNECTOR, FALSE_POTENTIAL_CONNECTOR } protected GameMap map; private Dictionary<Doorway, DoorType> doorways; private Dictionary<Vector3, Doorway> leaves; private HashSet<Connection> activeConnections; private Dictionary<Vector3, Connection> potentialConnections; private Dictionary<Vector3, Connection> falsePotentialConnections; public GameMap Map => map; public virtual BoundsMap<Tile> BoundsMap => Map.BoundsMap; public int Count => doorways.Count; public virtual bool IsReadOnly => false; public virtual byte DoorPosPrecision => 3; public virtual float DoorPrecision => 1f / (float)(1 << (int)DoorPosPrecision); protected virtual float clearancePrecision => 1f; protected virtual float maxClearance => clearancePrecision * 256f; public IReadOnlyCollection<Doorway> Leaves => leaves.Values; public IReadOnlyCollection<Connection> ActiveConnections => activeConnections; public IReadOnlyCollection<Connection> PotentialConnections => potentialConnections.Values; public IReadOnlyCollection<Connection> FalsePotentialConnections => falsePotentialConnections.Values; public DoorwayManager(GameMap map) { this.map = map; doorways = new Dictionary<Doorway, DoorType>(); leaves = new Dictionary<Vector3, Doorway>(); activeConnections = new HashSet<Connection>(); potentialConnections = new Dictionary<Vector3, Connection>(); falsePotentialConnections = new Dictionary<Vector3, Connection>(); } public bool Validate() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: 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) foreach (KeyValuePair<Doorway, DoorType> doorway in doorways) { Doorway key = doorway.Key; if ((Object)(object)key == (Object)null) { return false; } DoorType value = doorway.Value; Vector3 key2 = ApproxPosition(key); Connection value2; switch (value) { case DoorType.LEAF: { if (!leaves.TryGetValue(key2, out var value3) || (Object)(object)key != (Object)(object)value3) { return false; } break; } case DoorType.ACTIVE_CONNECTOR: if (!activeConnections.Contains(new Connection(key, key.Connection))) { return false; } break; case DoorType.POTENTIAL_CONNECTOR: if (!potentialConnections.TryGetValue(key2, out value2) || ((Object)(object)value2.d1 != (Object)(object)key && (Object)(object)value2.d2 != (Object)(object)key)) { return false; } break; case DoorType.FALSE_POTENTIAL_CONNECTOR: if (!falsePotentialConnections.TryGetValue(key2, out value2) || ((Object)(object)value2.d1 != (Object)(object)key && (Object)(object)value2.d2 != (Object)(object)key)) { return false; } break; default: return false; } } return true; } protected virtual void UnsetDoorway(Doorway d, Vector3 approxPos = default(Vector3)) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: 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) if (!doorways.TryGetValue(d, out var value)) { return; } if (approxPos == default(Vector3)) { approxPos = ApproxPosition(d); } Connection value2; switch (value) { case DoorType.LEAF: { if (!leaves.Remove(approxPos, out var value3) || (Object)(object)value3 != (Object)(object)d) { throw new InvalidOperationException("Desync between leaves and doorways"); } break; } case DoorType.ACTIVE_CONNECTOR: activeConnections.Remove(new Connection(d, d.Connection)); break; case DoorType.POTENTIAL_CONNECTOR: if (potentialConnections.Remove(approxPos, out value2) && (Object)(object)value2.d1 != (Object)(object)d && (Object)(object)value2.d2 != (Object)(object)d) { throw new InvalidOperationException("Desync between potentialConnections and doorways"); } break; case DoorType.FALSE_POTENTIAL_CONNECTOR: if (falsePotentialConnections.Remove(approxPos, out value2) && (Object)(object)value2.d1 != (Object)(object)d && (Object)(object)value2.d2 != (Object)(object)d) { throw new InvalidOperationException("Desync between falsePotentialConnections and doorways"); } break; } } protected virtual void SetLeaf(Doorway d, Vector3 approxPos = default(Vector3)) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0004: 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_0023: 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) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_006a: 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) if (approxPos == default(Vector3)) { approxPos = ApproxPosition(d); } if (leaves.ContainsKey(approxPos)) { throw new InvalidOperationException($"How do we have two leaves at {approxPos}? ({d} & leaves[approxPos])"); } UnsetDoorway(d); doorways[d] = DoorType.LEAF; leaves.Add(approxPos, d); } protected virtual void SetActiveConnector(Doorway d) { //IL_0005: 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_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) UnsetDoorway(d); UnsetDoorway(d.Connection); doorways[d] = DoorType.ACTIVE_CONNECTOR; if (doorways.ContainsKey(d.Connection)) { doorways[d.Connection] = DoorType.ACTIVE_CONNECTOR; } activeConnections.Add(new Connection(d, d.Connection)); } protected virtual void SetPotentialConnection(Connection c, Vector3 approxPos = default(Vector3)) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0004: 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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: 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_014d: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) if (approxPos == default(Vector3)) { approxPos = ApproxPosition(c.d1); } UnsetDoorway(c.d1); UnsetDoorway(c.d2); if (c.d1.Fits(c.d2)) { if (potentialConnections.ContainsKey(approxPos)) { Plugin.LogError($"Two potential connections at the same position? ({approxPos})"); return; } doorways[c.d1] = DoorType.POTENTIAL_CONNECTOR; if (doorways.ContainsKey(c.d2)) { doorways[c.d2] = DoorType.POTENTIAL_CONNECTOR; } potentialConnections.Add(approxPos, c); } else if (falsePotentialConnections.ContainsKey(approxPos)) { Plugin.LogError($"Two false potential connections at the same position? ({approxPos})"); } else { doorways[c.d1] = DoorType.FALSE_POTENTIAL_CONNECTOR; if (doorways.ContainsKey(c.d2)) { doorways[c.d2] = DoorType.FALSE_POTENTIAL_CONNECTOR; } falsePotentialConnections.Add(approxPos, c); } } public void Add(Doorway d) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)d == (Object)null) { Debug.LogException((Exception)new ArgumentNullException("Doorway d")); } else { if (Contains(d)) { return; } Subscribe(d); if (d.IsVacant) { Vector3 val = ApproxPosition(d); if (leaves.TryGetValue(val, out var value)) { SetPotentialConnection(new Connection(d, value), val); } else { SetLeaf(d, val); } } else { SetActiveConnector(d); } } } private void RemoveAction(Doorway d) { if (!Remove(d)) { Debug.LogError((object)$"Failed to remove doorway {(((Object)(object)d == (Object)null) ? ((object?)d) : ((object?)((Object)d).name))} from DoorwayManager"); } } public bool Remove(Doorway d) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) if (!doorways.ContainsKey(d)) { return false; } Unsubscribe(d); Connection value; switch (doorways[d]) { case DoorType.LEAF: { if (!leaves.Remove(ApproxPosition(d), out var value2) || (Object)(object)d != (Object)(object)value2) { Debug.LogWarning((object)"DoorwayManager: Desync between doorways and leaves, this *will* become a problem"); } break; } case DoorType.ACTIVE_CONNECTOR: if (!Contains(d.Connection)) { activeConnections.Remove(new Connection(d, d.Connection)); } break; case DoorType.POTENTIAL_CONNECTOR: { potentialConnections.Remove(ApproxPosition(d), out value); Doorway other = value.GetOther(d); if (Contains(other)) { SetLeaf(other); } break; } case DoorType.FALSE_POTENTIAL_CONNECTOR: { falsePotentialConnections.Remove(ApproxPosition(d), out value); Doorway other = value.GetOther(d); if (Contains(other)) { SetLeaf(other); } break; } } doorways.Remove(d); return true; } public bool Contains(Doorway d) { return doorways.ContainsKey(d); } public virtual void Clear() { doorways.Clear(); leaves.Clear(); activeConnections.Clear(); potentialConnections.Clear(); falsePotentialConnections.Clear(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public IEnumerator<Doorway> GetEnumerator() { return doorways.Keys.GetEnumerator(); } public void CopyTo(Doorway[] arr, int startIdx) { throw new NotImplementedException(); } protected virtual void Subscribe(Doorway d) { d.OnDestroyEvent += RemoveAction; d.OnDisconnectEvent += DisconnectDoor; d.OnConnectEvent += ConnectDoor; } protected virtual void Unsubscribe(Doorway d) { d.OnDestroyEvent -= RemoveAction; d.OnDisconnectEvent -= DisconnectDoor; d.OnConnectEvent -= ConnectDoor; } public virtual Vector3 ApproxPosition(Doorway door) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_0046: 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_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)door == (Object)null) { throw new NullReferenceException("Cannot get the position of a destroyed doorway. "); } Vector3 position = ((Component)door).transform.position; return new Vector3(DoorPrecision * (float)(int)(position.x / DoorPrecision + 0.5f), DoorPrecision * (float)(int)(position.y / DoorPrecision + 0.5f), DoorPrecision * (float)(int)(position.z / DoorPrecision + 0.5f)); } public virtual float ClearanceRadius(Doorway d) { //IL_0013: 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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0035: 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_004a: Unknown result type (might be due to invalid IL or missing references) float num = clearancePrecision; Bounds bounds = default(Bounds); do { ((Bounds)(ref bounds))..ctor(((Component)d).transform.position + num * ((Component)d).transform.forward, 2f * num * Vector3.one); if (BoundsMap.Intersects(bounds)) { break; } num *= 2f; } while (!(num >= maxClearance)); return num; } public IChoice<Doorway, float> GetLeaves(Func<Doorway, float> weightFunc) { WeightedChoiceList<Doorway> weightedChoiceList = new WeightedChoiceList<Doorway>(); foreach (Doorway value in leaves.Values) { weightedChoiceList.Add(value, weightFunc(value)); } return weightedChoiceList; } public IChoice<Connection, float> GetActiveConnections(Func<Connection, float> weightFunc) { WeightedChoiceList<Connection> weightedChoiceList = new WeightedChoiceList<Connection>(); foreach (Connection activeConnection in activeConnections) { weightedChoiceList.Add(activeConnection, weightFunc(activeConnection)); } return weightedChoiceList; } public IChoice<Connection, float> GetPotentialConnections(Func<Connection, float> weightFunc) { WeightedChoiceList<Connection> weightedChoiceList = new WeightedChoiceList<Connection>(); foreach (Connection value in potentialConnections.Values) { weightedChoiceList.Add(value, weightFunc(value)); } return weightedChoiceList; } public void DisconnectDoor(Doorway d) { //IL_0009: 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) //IL_003f: 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_002a: Unknown result type (might be due to invalid IL or missing references) if (leaves.TryGetValue(ApproxPosition(d), out var value)) { SetPotentialConnection(new Connection(d, value)); } else { SetLeaf(d); } } public void ConnectDoor(Doorway d1, Doorway d2) { SetActiveConnector(d1); } } public struct Connection : IEquatable<Connection>, IEquatable<ITuple> { public Doorway d1; public Doorway d2; public Connection(Doorway d1, Doorway d2) { this.d1 = d1; this.d2 = d2; } public Doorway GetOther(Doorway d) { if ((Object)(object)d != (Object)(object)d1 && (Object)(object)d != (Object)(object)d2) { throw new ArgumentException("Doorway expected to be one of the doorways in the connection"); } return ((Object)(object)d == (Object)(object)d1) ? d2 : d1; } public void Deconstruct(out Doorway d1, out Doorway d2) { d1 = this.d1; d2 = this.d2; } public override bool Equals(object other) { if (other is ITuple tup) { return Equals(tup); } if (other is Connection con) { return Equals(con); } return false; } public bool Equals(Connection con) { Connection connection = con; var (doorway3, doorway4) = (Connection)(ref connection); return ((Object)(object)d1 == (Object)(object)doorway3 && (Object)(object)d2 == (Object)(object)doorway4) || ((Object)(object)d1 == (Object)(object)doorway4 && (Object)(object)d2 == (Object)(object)doorway3); } public bool Equals(ITuple tup) { if (tup.Length != 2) { return false; } Doorway doorway; Doorway doorway2; try { doorway = (Doorway)tup[0]; doorway2 = (Doorway)tup[1]; } catch (InvalidCastException) { return false; } return ((Object)(object)d1 == (Object)(object)doorway && (Object)(object)d2 == (Object)(object)doorway2) || ((Object)(object)d1 == (Object)(object)doorway2 && (Object)(object)d2 == (Object)(object)doorway); } public override int GetHashCode() { return ((object)d1).GetHashCode() ^ ((object)d2).GetHashCode(); } } public class Doorway : MonoBehaviour { protected bool initialized; protected Tile tile; protected Vector2 size; protected Doorway connection; public Tile Tile { get { if ((Object)(object)this.tile == (Object)null) { this.tile = null; Tile[] componentsInParent = ((Component)this).GetComponentsInParent<Tile>(((Component)this).gameObject.activeInHierarchy); foreach (Tile tile in componentsInParent) { if (tile.Initialized) { this.tile = tile; break; } } } return this.tile; } } public Vector2 Size { get { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: 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) return size; } protected set { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) size = value; } } public bool IsVacant => (Object)(object)connection == (Object)null; public bool Initialized { get { return initialized; } protected set { initialized = value; } } public Doorway Connection => connection; public event Action<Doorway> OnDisconnectEvent; public event Action<Doorway> OnDestroyEvent; public event Action<Doorway, Doorway> OnConnectEvent; private void OnDestroy() { Disconnect(); this.OnDestroyEvent?.Invoke(this); } public virtual void Initialize() { if (!Initialized) { Initialized = true; connection = null; } } public virtual bool Fits(Doorway other) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) return size == other.size; } public void Connect(Doorway other) { if (!Fits(other)) { string message = "Cannot connect doors that do not fit together\n" + $"\t(Tiles {Tile} & {other.Tile})"; throw new ArgumentException(message); } connection = other; other.connection = this; this.OnConnectEvent?.Invoke(this, other); other.OnConnectEvent?.Invoke(other, this); } public void Disconnect() { if (!((Object)(object)connection == (Object)null)) { this.OnDisconnectEvent?.Invoke(this); Doorway doorway = connection; connection = null; doorway.Disconnect(); } } } public class Tile : MonoBehaviour { protected Doorway[] doorways = null; protected Bounds bounding_box = new Bounds(Vector3.zero, Vector3.zero); protected bool initialized = false; public bool Initialized { get { return initialized; } protected set { initialized = value; } } public bool HasLeafDoorway { get { Doorway[] array = Doorways; foreach (Doorway doorway in array) { if (doorway.IsVacant) { return true; } } return false; } } public bool IsPrefab { get { //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) Scene scene = ((Component)this).gameObject.scene; return !((Scene)(ref scene)).IsValid(); } } public Doorway[] Doorways => doorways ?? (doorways = ((Component)this).GetComponentsInChildren<Doorway>()); public virtual float IntersectionTolerance => 0.625f; public Bounds LooseBoundingBox { get { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: 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) //IL_0017: 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_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_0037: Unknown result type (might be due to invalid IL or missing references) Bounds boundingBox = BoundingBox; Vector3 center = ((Bounds)(ref boundingBox)).center; boundingBox = BoundingBox; return new Bounds(center, ((Bounds)(ref boundingBox)).size - 2f * IntersectionTolerance * Vector3.one); } } public Bounds BoundingBox => bounding_box; public GameMap Map => ((Component)this).GetComponentInParent<GameMap>(true); public Tile Instantiate(Transform parent = null) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) Tile component = Object.Instantiate<GameObject>(((Component)this).gameObject).GetComponent<Tile>(); component.bounding_box = new Bounds(Vector3.zero, Vector3.zero); ((Component)component).transform.parent = parent; component.Initialize(this); return component; } public virtual void Initialize(Tile prefab) { if (!initialized) { initialized = true; } } public void RotateBy(Quaternion quat) { //IL_0007: 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_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_002f: 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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) Vector3 val = ((Bounds)(ref bounding_box)).center - ((Component)this).transform.position; ((Bounds)(ref bounding_box)).center = ((Component)this).transform.position + quat * val; ((Bounds)(ref bounding_box)).extents = quat * ((Bounds)(ref bounding_box)).extents; bounding_box.FixExtents(); ((Component)this).transform.Rotate(((Quaternion)(ref quat)).eulerAngles, (Space)0); } public void MoveTo(Vector3 pos) { //IL_0007: 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_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_0031: 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) Vector3 val = ((Component)this).transform.position - ((Bounds)(ref bounding_box)).center; ((Bounds)(ref bounding_box)).center = pos; ((Component)this).transform.position = pos + val; } public bool PlaceAsRoot(Transform parent) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) ((Component)this).transform.parent = parent; MoveTo(parent.position); return true; } public bool Place(int thisDoorwayIdx, Doorway other) { //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: 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_00f8: 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_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) if (thisDoorwayIdx >= Doorways.Length) { throw new IndexOutOfRangeException($"Door index of new tile out of range. Tried to select idx {thisDoorwayIdx} with only {Doorways.Length} doors. "); } if ((Object)(object)this == (Object)null) { throw new ArgumentNullException("Cannot place a tile that is being destroyed"); } if ((Object)(object)other == (Object)null) { throw new ArgumentNullException("No doorway provided to connect to"); } if ((Object)(object)other.Tile.Map == (Object)null) { throw new ArgumentException("Tile must connect to a doorway that is placed within a map"); } Transform parent = ((Component)this).transform.parent; ((Component)this).transform.parent = ((Component)other).transform; Doorway doorway = Doorways[thisDoorwayIdx]; Vector3 up = ((Component)doorway).transform.up; Quaternion quat = Quaternion.Inverse(((Component)doorway).transform.rotation) * ((Component)other).transform.rotation * new Quaternion(up.x, up.y, up.z, 0f); RotateBy(quat); Vector3 val = ((Component)doorway).transform.position - ((Bounds)(ref bounding_box)).center; MoveTo(((Component)other).transform.position - val); if (!Map.VerifyTilePlacement(new PlacementInfo(this, thisDoorwayIdx, other))) { ((Component)this).transform.SetParent(parent); return false; } doorway.Connect(other); return true; } public virtual byte[] GetSerializationId() { return (((Object)this).name.Substring(0, ((Object)this).name.Length - "(Clone)".Length) + "\0").GetBytes(); } public virtual Tile GetPrefab(object ident) { return GetPrefab((string)ident); } public static Tile GetPrefab(string id) { //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) Object[] array = Resources.FindObjectsOfTypeAll(typeof(Tile)); for (int i = 0; i < array.Length; i++) { Tile tile = (Tile)(object)array[i]; if (((Object)tile).name == id) { Scene scene = ((Component)tile).gameObject.scene; if (!((Scene)(ref scene)).IsValid()) { return tile; } } } return null; } } public abstract class GenerationAction { } public class YieldFrame : GenerationAction { } public class PlacementInfo : GenerationAction { private Tile newtile; private int newDoorwayIdx; private Doorway attachmentPoint; public Tile NewTile { get { return newtile; } set { newtile = value; } } public int NewDoorwayIdx { get { return newDoorwayIdx; } set { newDoorwayIdx = value; } } public Doorway AttachmentPoint { get { return attachmentPoint; } set { attachmentPoint = value; } } public PlacementInfo(Tile newTile, int newDoorwayIdx = 0, Doorway attachmentPoint = null) { newtile = newTile; this.newDoorwayIdx = newDoorwayIdx; this.attachmentPoint = attachmentPoint; } public override string ToString() { return "PlacementInfo: " + ((Object)newtile).name + ":" + ((Object)newtile.Doorways[newDoorwayIdx]).name + " onto " + ((Object)attachmentPoint.Tile).name + ":" + ((Object)attachmentPoint).name; } } public class RemovalInfo : GenerationAction { private Tile target; public Tile Target => target; public RemovalInfo(Tile target) { this.target = target; } } public abstract class ConnectionAction : GenerationAction { public Doorway d1 { get; private set; } public Doorway d2 { get; private set; } public (Doorway d1, Doorway d2) Doorways => (d1, d2); public ConnectionAction(Doorway d1, Doorway d2) { this.d1 = d1; this.d2 = d2; if (!d1.Fits(d2)) { throw new ArgumentException($"Doors {d1} and {d2} do not fit together"); } } } public class ConnectAction : ConnectionAction { public ConnectAction(Doorway d1, Doorway d2) : base(d1, d2) { } } public class DisconnectAction : ConnectionAction { public DisconnectAction(Doorway d1, Doorway d2) : base(d1, d2) { } } public interface ITileGenerator { IEnumerable<GenerationAction> Generator(GameMap map); } public class GameMap : MonoBehaviour { protected Tile rootTile; private BoundsMap<Tile> boundsMap; protected NavMeshSurface navSurface; public Tile RootTile { get { return rootTile; } protected set { rootTile = value; } } public int TileCount => ((Component)this).GetComponentsInChildren<Tile>().Length; public BoundsMap<Tile> BoundsMap { get { return boundsMap; } private set { boundsMap = value; } } public virtual IDoorwayManager DoorwayManager { get; protected set; } = null; public event Action<Tile> TileInsertionEvent; public event Action<Tile> TileRemovalEvent; public event Action<GameMap> GenerationCompleteEvent; protected virtual void Awake() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) rootTile = null; if (DoorwayManager == null) { DoorwayManager = new DoorwayManager(this); } boundsMap = new BoundsMap<Tile>(Vector3.zero, 1024f, (Tile t) => t.LooseBoundingBox); navSurface = ((Component)this).gameObject.AddComponent<NavMeshSurface>(); navSurface.collectObjects = (CollectObjects)2; navSurface.useGeometry = (NavMeshCollectGeometry)1; TileRemovalEvent += RemoveTileAction; } protected virtual void OnDestroy() { navSurface.RemoveData(); } public virtual bool PerformAction(GenerationAction action) { if (action is PlacementInfo placement) { Result<Tile, string> result = AddTile(placement); if (result.isOk) { this.TileInsertionEvent?.Invoke(result.Ok); } else { this.TileInsertionEvent?.Invoke(null); } } else if (action is RemovalInfo removal) { RemoveTile(removal); } else if (action is ConnectAction connectAction) { var (doorway, other) = connectAction.Doorways; doorway.Connect(other); } else if (action is DisconnectAction disconnectAction) { disconnectAction.d1.Disconnect(); } else if (!(action is YieldFrame)) { return false; } return true; } public virtual IEnumerator GenerateCoroutine(ITileGenerator tileGen) { foreach (GenerationAction action in tileGen.Generator(this)) { if (!PerformAction(action)) { throw new InvalidOperationException($"Unknown GenerationAction: {action}"); } if (action is YieldFrame) { yield return null; } } this.GenerationCompleteEvent?.Invoke(this); } protected void AddDoorway(Doorway d) { if ((Object)(object)d == (Object)null) { Debug.LogError((object)("Cannot add null doorway to " + ((object)this).GetType().Name + ". Is it destroyed?"), (Object)(object)this); } else { DoorwayManager.Add(d); } } protected void RemoveDoorway(Doorway d) { if ((Object)(object)d == (Object)null) { throw new NullReferenceException("Cannot remove a leaf that has already been destroyed"); } if (!DoorwayManager.Remove(d)) { Debug.LogError((object)("Doorway " + ((Object)d.Tile).name + ":" + ((Object)d).name + " not found/removed"), (Object)(object)this); } } public virtual bool VerifyTilePlacement(PlacementInfo placement) { Tile newTile = placement.NewTile; if ((Object)(object)newTile == (Object)null) { Debug.LogException((Exception)new ArgumentNullException("Tile tile"), (Object)(object)this); return false; } return !boundsMap.Intersects(newTile); } public virtual Result<Tile, string> AddTile(PlacementInfo placement) { Tile tile = placement.NewTile; if (tile.IsPrefab) { tile = tile.Instantiate(((Component)this).transform); } if ((Object)(object)RootTile == (Object)null) { RootTile = tile; RootTile.PlaceAsRoot(((Component)this).transform); } else { Doorway attachmentPoint = placement.AttachmentPoint; int newDoorwayIdx = placement.NewDoorwayIdx; if (!attachmentPoint.Fits(tile.Doorways[newDoorwayIdx])) { Object.Destroy((Object)(object)((Component)tile).gameObject); return Result<Tile, string>.NewErr("Doorways do not fit"); } if (!tile.Place(newDoorwayIdx, attachmentPoint)) { Object.Destroy((Object)(object)((Component)tile).gameObject); return Result<Tile, string>.NewErr("Failure in Tile.Place"); } } Doorway[] doorways = tile.Doorways; foreach (Doorway d in doorways) { AddDoorway(d); } try { boundsMap.Add(tile); } catch (ArgumentException) { RemoveTile(new RemovalInfo(tile)); if ((Object)(object)tile != (Object)null) { Object.Destroy((Object)(object)((Component)tile).gameObject); } tile = null; return Result<Tile, string>.NewErr("Could not be added to boundsMap"); } return Result<Tile, string>.NewOk(tile); } private void RemoveTileAction(Tile t) { if (!boundsMap.Remove(t)) { Debug.LogError((object)("Tile " + ((Object)t).name + " was not in boundsMap?")); } } public void RemoveTile(RemovalInfo removal) { if ((Object)(object)removal.Target == (Object)null) { Debug.LogError((object)"Cannot remove tile that has already been destroyed"); return; } Tile[] componentsInChildren = ((Component)removal.Target).GetComponentsInChildren<Tile>(((Component)this).gameObject.activeInHierarchy); foreach (Tile obj in componentsInChildren) { this.TileRemovalEvent?.Invoke(obj); } Object.Destroy((Object)(object)((Component)removal.Target).gameObject); } public void GenerateNavMesh(int agentId) { navSurface.RemoveData(); navSurface.agentTypeID = agentId; navSurface.BuildNavMesh(); navSurface.AddData(); } } public class GameMapSerializer<T, TTile> : Serializer<T> where T : GameMap where TTile : Tile { protected ISerializer<TTile> TileSer; public GameMapSerializer(ISerializer<TTile> tileSerializer) { TileSer = tileSerializer; } public override void Serialize(SerializationContext sc, T map) { sc.Add(((Object)map).name.GetBytes()); sc.Add(new byte[1]); sc.AddInline(map.RootTile, TileSer); } protected override T Deserialize(T map, DeserializationContext dc) { map.AddTile(new PlacementInfo((TTile)dc.ConsumeInline(TileSer))); return map; } public override T Deserialize(DeserializationContext dc) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) dc.ConsumeUntil((byte b) => b == 0).CastInto(out string str); dc.Consume(1); T baseObject = new GameObject(str).AddComponent<T>(); return Deserialize(baseObject, dc); } } public class TileSerializer<T> : Serializer<T> where T : Tile { protected GameMap ParentMap; public TileSerializer(GameMap map) { ParentMap = map; } public override void Serialize(SerializationContext sc, T tgt) { sc.Add(tgt.GetSerializationId()); sc.Add(((ushort)tgt.Doorways.Length).GetBytes()); Doorway[] doorways = tgt.Doorways; foreach (Doorway doorway in doorways) { sc.AddReference(doorway.Connection?.Tile, this); if ((Object)(object)doorway.Connection == (Object)null) { sc.Add(((ushort)0).GetBytes()); } else { sc.Add(((ushort)Array.IndexOf(doorway.Connection.Tile.Doorways, doorway.Connection)).GetBytes()); } } } protected override T Deserialize(T tile, DeserializationContext dc) { int address = dc.Address; bool flag = false; dc.Consume(2).CastInto(out ushort o); for (int i = 0; i < o; i++) { int num = i; int num2 = dc.ConsumeReference(this); dc.Consume(2).CastInto(out ushort o2); if (num2 == 0) { continue; } if (num2 < address) { T val = (T)dc.GetReference(num2); if (DeserializationContext.Verbose) { Plugin.LogDebug($"Attaching {((Object)tile).name}:{num} to {((Object)val).name}:{o2}"); } if (!flag) { flag = true; ParentMap.AddTile(new PlacementInfo(tile, num, val.Doorways[o2])); } else { ParentMap.PerformAction(new ConnectAction(tile.Doorways[num], val.Doorways[o2])); } } else if (num2 == address) { throw new Exception("Tile connects to itself??"); } } return tile; } public override T Deserialize(DeserializationContext dc) { int address = dc.Address; dc.ConsumeUntil((byte b) => b == 0).CastInto(out string str); dc.Consume(1); T val = (T)(Tile.GetPrefab(str)?.Instantiate(((Component)ParentMap).transform)); if ((Object)(object)val == (Object)null) { throw new NullReferenceException("Could not find a prefab with id '" + str + "'"); } return Deserialize(val, dc); } } public class PropAction : GenerationAction { protected Prop target; protected bool enable; public Prop Prop => target; public bool Enable => enable; public PropAction(Prop t, bool e) { target = t; enable = e; } } internal sealed class ArchetypeRegionPlacer : IDisposable { private GameMap map; private Doorway root; private Archetype archetype; private HashSet<DTile> tilesPlaced; private DoorwayManager doorwayManager; private WeightedChoiceList<DTile> possibleTiles; private Tile tile; private ChoiceList<Doorway> possibleDoorways; private Doorway doorway; private IChoice<Doorway, float> possibleLeaves; private Doorway leaf; public DungeonFlowConverter parent { get; private set; } public int iterationsSinceLastSuccess { get; private set; } private int NumLeaves => doorwayManager.Leaves.Count; public Random Rng => parent.Rng; public bool Exhausted => ((Object)(object)tile == (Object)null && possibleTiles.OpenCount == 0) || NumLeaves == 0; public ArchetypeRegionPlacer(DungeonFlowConverter parent, GameMap map, Doorway root, Archetype archetype, HashSet<DTile> tilesPlaced) { if (parent == null) { throw new ArgumentNullException("parent"); } if ((Object)(object)map == (Object)null) { throw new ArgumentNullException("map"); } if ((Object)(object)root == (Object)null) { throw new ArgumentNullException("root"); } if (archetype == null) { throw new ArgumentNullException("archetype"); } if (tilesPlaced == null) { throw new ArgumentNullException("tilesPlaced"); } this.parent = parent; this.map = map; this.root = root; this.archetype = archetype; this.tilesPlaced = tilesPlaced; doorwayManager = new DoorwayManager(map); AddDoorway(root); possibleDoorways = null; possibleLeaves = null; iterationsSinceLastSuccess = 0; possibleTiles = new WeightedChoiceList<DTile>(archetype.Tiles); tile = null; doorway = (leaf = null); map.TileInsertionEvent += Handler; } ~ArchetypeRegionPlacer() { Dispose(isDisposing: false); } public void Dispose() { Dispose(isDisposing: true); GC.SuppressFinalize(this); } private void Dispose(bool isDisposing) { if (isDisposing) { map.TileInsertionEvent -= Handler; } } public PlacementInfo YieldAttempt() { do { GetNewLeaf(); } while ((Object)(object)leaf == (Object)null && !Exhausted); if (Exhausted) { return null; } if ((Object)(object)leaf == (Object)null) { throw new Exception("null leaf with no exhaustion?"); } PlacementInfo placementInfo = new PlacementInfo(tile, Array.IndexOf(tile.Doorways, doorway), leaf); if (Config.Singleton.EnableVerboseGeneration) { Plugin.LogDebug($"Trying {placementInfo}"); } return placementInfo; } private void Handler(Tile t) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Invalid comparison between Unknown and I4 if ((Object)(object)t != (Object)null) { Doorway[] doorways = t.Doorways; foreach (Doorway doorway in doorways) { AddDoorway(doorway); } if ((int)((Component)tile).GetComponent<Tile>().RepeatMode == 2) { tilesPlaced.Add((DTile)tile); } tile = null; this.doorway = (leaf = null); possibleTiles.Reset(); iterationsSinceLastSuccess = 0; } else { if (Config.Singleton.EnableVerboseGeneration) { Plugin.LogDebug("Placement Failed"); } iterationsSinceLastSuccess++; } } private void GetNewLeaf() { if ((Object)(object)doorway == (Object)null || possibleLeaves.OpenCount == 0) { GetNewDoorway(); if ((Object)(object)doorway == (Object)null || possibleLeaves.OpenCount == 0) { leaf = null; return; } } leaf = possibleLeaves.Yield((float)((double)possibleLeaves.OpenWidth * Rng.NextDouble())); } private void GetNewDoorway() { if ((Object)(object)tile == (Object)null || possibleDoorways.OpenCount == 0) { do { GetNewTile(); } while (tilesPlaced.Contains((DTile)tile) && !Exhausted); if ((Object)(object)tile == (Object)null) { doorway = null; return; } } doorway = possibleDoorways.Yield(Rng.Next(possibleDoorways.OpenCount)); possibleLeaves = doorwayManager.GetLeaves((Doorway d) => (d.Size == doorway.Size) ? doorwayManager.ClearanceRadius(d) : 0f); } private void GetNewTile() { if (possibleTiles.OpenCount == 0) { tile = null; return; } tile = possibleTiles.Yield((float)((double)possibleTiles.OpenWidth * Rng.NextDouble())); possibleDoorways = new ChoiceList<Doorway>(tile.Doorways); } private void AddDoorway(Doorway leaf) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) if (archetype.GetDoorwayCountBySize(leaf.Size) != 0) { doorwayManager.Add(leaf); possibleLeaves = null; } } } public class Archetype { public WeightedList<DTile> Tiles; public Dictionary<Vector2, int> DoorwayCountBySize; public float Length; public Archetype(float length) { Tiles = new WeightedList<DTile>(); DoorwayCountBySize = new Dictionary<Vector2, int>(); Length = length; } public void AddTile(DTile tile, float weight) { //IL_004e: 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_002d: 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) //IL_0037: Unknown result type (might be due to invalid IL or missing references) Tiles.Add(tile, weight); Doorway[] doorways = tile.Doorways; foreach (Doorway doorway in doorways) { try { DoorwayCountBySize[doorway.Size]++; } catch (KeyNotFoundException) { DoorwayCountBySize.Add(doorway.Size, 1); } } } public int GetDoorwayCountBySize(Vector2 size) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) if (!DoorwayCountBySize.TryGetValue(size, out var value)) { return 0; } return value; } } public class DungeonFlowConverter : ITileGenerator { protected DungeonFlow flow; protected DTile StartRoom; protected List<List<Archetype>> archetypes; protected HashSet<DTile> tilesPlaced; private const int MAX_ATTEMPTS = 10; private int iterationsSinceLastSuccess = 0; private int seed; private Random rng; public int TileCountLowerBound { get; protected set; } public int TileCountUpperBound { get; protected set; } public int TileCountAverage => (TileCountLowerBound + TileCountUpperBound) / 2; public int PlacementLowerBound => (int)(Config.Singleton.LowerIterationMultiplier * (float)TileCountLowerBound); public int PlacementUpperBound => (int)(Config.Singleton.UpperIterationMultiplier * (float)TileCountLowerBound); public int Seed { get { return seed; } set { rng = new Random(value); seed = value; } } public Random Rng => rng; public DungeonFlow Flow => flow; public float DoorwayConnectionChance => flow.DoorwayConnectionChance / 2f; public float DoorwayDisconnectChance => flow.DoorwayConnectionChance / 2f; public DungeonFlowConverter(DungeonFlow flow, int seed) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Invalid comparison between Unknown and I4 Seed = seed; tilesPlaced = new HashSet<DTile>(); this.flow = flow; GraphNode node = null; foreach (GraphNode node2 in flow.Nodes) { if ((int)node2.NodeType == 1) { node = node2; break; } } FindStartRoom(node); int num = (int)((float)(flow.Length.Min + flow.Length.Max) / 2f * RoundManager.Instance.mapSizeMultiplier * RoundManager.Instance.currentLevel.factorySizeMultiplier); TileCountLowerBound = (int)((float)num * Config.Singleton.MinimumTileMultiplier); TileCountUpperBound = (int)((float)num * Config.Singleton.MaximumTileMultiplier); float num2 = 0f; archetypes = new List<List<Archetype>>(); flow.Lines.Sort(delegate(GraphLine x, GraphLine y) { float num5 = x.Position - y.Position; if (num5 == 0f) { return 0; } return (num5 > 0f) ? 1 : (-1); }); foreach (GraphLine line in flow.Lines) { List<Archetype> list = new List<Archetype>(); archetypes.Add(list); num2 += line.Length; foreach (DungeonArchetype dungeonArchetype in line.DungeonArchetypes) { Archetype archetype = new Archetype(line.Length); list.Add(archetype); float num3 = 1f / (float)dungeonArchetype.TileSets.Count; foreach (TileSet tileSet in dungeonArchetype.TileSets) { foreach (GameObjectChance weight2 in tileSet.TileWeights.Weights) { float num4 = (weight2.MainPathWeight + weight2.BranchPathWeight) / 2f; DTile component = weight2.Value.GetComponent<DTile>(); if ((Object)(object)component == (Object)null) { Plugin.LogError("Bad dtile"); } if (!((Object)(object)component == (Object)(object)StartRoom) && !(((Object)component).name == "StartRoom") && !(((Object)component).name == "ManorStartRoom")) { float weight = num3 * num4; archetype.AddTile(component, weight); } } } } } for (int i = 0; i < archetypes.Count; i++) { for (int j = 0; j < archetypes[i].Count; j++) { archetypes[i][j].Length /= num2; } } } private void FindStartRoom(GraphNode node) { foreach (TileSet tileSet in node.TileSets) { foreach (GameObjectChance weight in tileSet.TileWeights.Weights) { SpawnSyncedObject[] componentsInChildren = weight.Value.GetComponentsInChildren<SpawnSyncedObject>(true); foreach (SpawnSyncedObject val in componentsInChildren) { EntranceTeleport component = val.spawnPrefab.GetComponent<EntranceTeleport>(); if (((component != null) ? ((Object)component).name : null) == "EntranceTeleportA") { StartRoom = weight.Value.GetComponent<DTile>(); return; } } } } Plugin.LogError("Could not find a start room with an EntranceTeleportA. Defaulting to first tile we find."); object startRoom; if (node == null) { startRoom = null; } else { TileSet obj = node.TileSets[0]; if (obj == null) { startRoom = null; } else { GameObjectChanceTable tileWeights = obj.TileWeights; if (tileWeights == null) { startRoom = null; } else { GameObjectChance obj2 = tileWeights.Weights[0]; if (obj2 == null) { startRoom = null; } else { GameObject value = obj2.Value; startRoom = ((value != null) ? value.GetComponent<DTile>() : null); } } } } StartRoom = (DTile)startRoom; } public virtual (int min, int max) GetGlobalPropRange(int id) { foreach (GlobalPropSettings globalProp in flow.GlobalProps) { if (globalProp.ID == id) { return (globalProp.Count.Min, globalProp.Count.Max); } } Plugin.LogError($"Global Prop bounds not found for id {id}"); return (1, 1); } public void FailedPlacementHandler(Tile tile) { if ((Object)(object)tile == (Object)null) { iterationsSinceLastSuccess++; } else { iterationsSinceLastSuccess = 0; } } protected IEnumerable<PlacementInfo> PlaceRoot(GameMap map) { if ((Object)(object)StartRoom == (Object)null) { Plugin.LogError("Start tile not found D:"); yield return null; yield break; } if (Config.Singleton.EnableVerboseGeneration) { Plugin.LogDebug("Using '" + ((Object)StartRoom).name + "' as start room"); } yield return new PlacementInfo(StartRoom); string startname = ""; string name = ((Object)StartRoom).name; string text = name; string text2 = text; if (!(text2 == "ElevatorConnector")) { if (text2 == "Level2StartRoomConnector") { startname = "ManorStartRoom"; } } else { startname = "StartRoom"; } DTile fakestartroom = null; DTile[] array = Resources.FindObjectsOfTypeAll<DTile>(); foreach (DTile t2 in array) { if (((Object)t2).name == startname) { fakestartroom = t2; break; } } if (!((Object)(object)fakestartroom != (Object)null)) { yield break; } int didx; for (didx = 0; didx < fakestartroom.Doorways.Length && !(fakestartroom.Doorways[didx].Size == map.RootTile.Doorways[0].Size); didx++) { } Action<Tile> foo = delegate(Tile t) { if ((Object)(object)t == (Object)null) { Plugin.LogFatal("Failed to place start room - the map will fail to generate"); } }; map.TileInsertionEvent += foo; yield return new PlacementInfo(fakestartroom, didx, map.RootTile.Doorways[0]); map.TileInsertionEvent -= foo; } protected IEnumerable<RemovalInfo> RemoveTiles(GameMap map) { Stopwatch timer = new Stopwatch(); timer.Start(); Plugin.LogInfo("Removing tiles..."); int tileCount = map.TileCount; int upperBound = Math.Min(TileCountUpperBound - PlacementLowerBound, tileCount); int lowerBound = Math.Max(4 * tileCount / 5, TileCountLowerBound); if (lowerBound > upperBound) { lowerBound = upperBound; } int targetCount = Rng.Next(lowerBound, upperBound + 1); int numTilesToDelete = tileCount - targetCount; if (Config.Singleton.EnableVerboseGeneration) { Plugin.LogDebug($"Removing {numTilesToDelete} tiles..."); } while (numTilesToDelete > 0) { Tile[] tiles = ((Component)map).GetComponentsInChildren<Tile>(); if (tiles.Length <= 1) { break; } Tile selected; int numTilesUnderSelection; do { selected = tiles[Rng.Next(tiles.Length)]; numTilesUnderSelection = ((Component)selected).GetComponentsInChildren<DTile>().Length; } while (numTilesUnderSelection > numTilesToDelete); if (Config.Singleton.EnableVerboseGeneration) { Plugin.LogDebug("Removing " + ((Object)selected).name); } yield return new RemovalInfo(selected); numTilesToDelete -= numTilesUnderSelection; } timer.Stop(); Plugin.LogDebug($"Finished removing tiles in {timer.Elapsed.TotalSeconds} seconds"); } protected IEnumerable<GenerationAction> AttemptArchetypePlacement(GameMap map, Doorway root, Archetype archetype, int length, Action<int> reaction) { int progress = 0; using (ArchetypeRegionPlacer arp = new ArchetypeRegionPlacer(this, map, root, archetype, tilesPlaced)) { int numAttempts = 0; while (progress != length) { PlacementInfo attempt = arp.YieldAttempt(); if (attempt != null) { yield return attempt; } if (attempt != null && arp.iterationsSinceLastSuccess == 0) { progress++; if (Config.Singleton.EnableVerboseGeneration) { Plugin.LogDebug($"+ ({numAttempts}) {((Object)attempt.NewTile).name} | {((Object)attempt.AttachmentPoint.Tile).name}"); } } else if (attempt == null) { if (!((float)progress < 0.7f * (float)length)) { break; } if (Config.Singleton.EnableVerboseGeneration) { Plugin.LogDebug($"Root failure: Generated {progress}/{length} tiles from root {root.Tile}"); if (attempt == null) { Plugin.LogDebug("Reason: Exhausted all options"); } else { Plugin.LogDebug("Reason: Exceeded 30 attempts between placements"); } } if (progress != 0) { progress = 0; yield return new YieldFrame(); yield return new RemovalInfo(root.Connection.Tile); yield return new YieldFrame(); } break; } if (Config.Singleton.EnableVerboseGeneration) { numAttempts = arp.iterationsSinceLastSuccess; } } } if (Config.Singleton.EnableVerboseGeneration) { Plugin.LogDebug($"Generated {progress}/{length} tiles from root {root.Tile}"); } reaction(progress); } protected IEnumerable<GenerationAction> PlaceTiles(GameMap map) { Stopwatch timer = new Stopwatch(); timer.Start(); Plugin.LogInfo("Placing tiles..."); int mapTileCount = map.TileCount; int lowerBound = Math.Max(mapTileCount, TileCountLowerBound); int target = Rng.Next(lowerBound, TileCountUpperBound + 1); int tile_demand = target - mapTileCount; tile_demand = Math.Max(tile_demand, PlacementLowerBound); tile_demand = Math.Min(tile_demand, PlacementUpperBound); if (Config.Singleton.EnableVerboseGeneration) { Plugin.LogDebug($"Queueing {tile_demand} tiles..."); } int tile_demand_theory = tile_demand; List<(Archetype a, int len)> archetypeSizes = new List<(Archetype, int)>(); for (int k = 0; k < archetypes.Count; k++) { Archetype archetype2 = archetypes[k][Rng.Next(archetypes[k].Count)]; int tileCount2 = (int)(archetype2.Length * (float)tile_demand + 0.5f); int lower = (int)(0.9f * (float)tileCount2); if (lower <= 0) { lower = 1; } int upper = (int)(1.1f * (float)tileCount2); if (upper > tile_demand_theory) { upper = tile_demand_theory; } if (upper < lower) { break; } tileCount2 = Rng.Next(lower, upper); tile_demand_theory -= tileCount2; archetypeSizes.Add((archetype2, tileCount2)); } if (tile_demand_theory != 0) { if (archetypeSizes.Count == 0) { Plugin.LogError("Was not able to select a single archetypes to generate this round"); } for (int j = 0; j < archetypeSizes.Count; j++) { archetypeSizes[j] = (archetypeSizes[j].a, archetypeSizes[j].len + tile_demand_theory / archetypeSizes.Count); } } if (Config.Singleton.EnableVerboseGeneration) { string msg = $"Archetype sizes: ({archetypeSizes.Count}) - "; foreach (var item in archetypeSizes) { _ = item.a; int len = item.len; msg += $"{len}, "; } Plugin.LogDebug(msg.Substring(0, msg.Length - 2)); } foreach (var item2 in archetypeSizes) { Archetype archetype = item2.a; int length = item2.len; IDoorwayManager doorwayManager = map.DoorwayManager; IChoice<Doorway, float> roots = doorwayManager.GetLeaves((Doorway d) => archetype.GetDoorwayCountBySize(d.Size)); foreach (WeightedList<Doorway>.Entry entry2 in ((WeightedList<Doorway>)roots).Entries) { if ((Object)(object)entry2.item == (Object)null) { Plugin.LogError("null leaf"); break; } } bool forelse = true; for (int i = 0; i < 50; i++) { if (roots.OpenCount == 0) { break; } Doorway root = roots.Yield(roots.OpenWidth * (float)Rng.NextDouble()); if ((Object)(object)root == (Object)null) { Plugin.LogError("null root"); foreach (WeightedList<Doorway>.Entry entry in ((WeightedList<Doorway>)roots).Entries) { Plugin.LogError(string.Format("{0} | {1}", ((Object)(object)entry.item == (Object)null) ? "null" : ((Object)entry.item).name, entry.weight)); } } foreach (GenerationAction item3 in AttemptArchetypePlacement(reaction: delegate(int p) { tile_demand -= p; if (p != 0) { forelse = false; } }, map: map, root: root, archetype: archetype, length: length)) { yield return item3; } if (!forelse) { break; } yield return new YieldFrame(); } if (forelse) { Plugin.LogError($"Failed to generate an archetype of {length} tiles"); } } Plugin.LogInfo($"Failed to place {tile_demand} tiles"); timer.Stop(); Plugin.LogDebug($"Finished generating tiles in {timer.Elapsed.TotalSeconds} seconds"); } protected IEnumerable<ConnectionAction> HandleConnections(GameMap map) { List<ConnectionAction> list = new List<ConnectionAction>(); foreach (ConnectAction item in ConnectTiles(map)) { list.Add(item); } foreach (DisconnectAction item2 in DisconnectTiles(map)) { list.Add(item2); } return list; } private IEnumerable<ConnectAction> ConnectTiles(GameMap map) { Plugin.LogInfo("Queueing making some loops..."); foreach (Connection con in map.DoorwayManager.GetPotentialConnections((Connection c) => 1f)) { if (Rng.NextDouble() < (double)DoorwayConnectionChance) { if (Config.Singleton.EnableVerboseGeneration) { Plugin.LogDebug("C " + ((Object)con.d1.Tile).name + "." + ((Object)con.d1).name + " | " + ((Object)con.d2.Tile).name + "." + ((Object)con.d2).name); } yield return new ConnectAction(con.d1, con.d2); } } } private IEnumerable<DisconnectAction> DisconnectTiles(GameMap map) { Plugin.LogInfo("Queueing removing some loops..."); foreach (var (d1, d2) in map.DoorwayManager.GetActiveConnections((Connection c) => 1f)) { if ((Object)(object)((Component)d1.Tile).transform.parent != (Object)(object)((Component)d2).transform && (Object)(object)((Component)d2.Tile).transform.parent != (Object)(object)((Component)d1).transform && Rng.NextDouble() < (double)DoorwayDisconnectChance) { if (Config.Singleton.EnableVerboseGeneration) { Plugin.LogDebug("D " + ((Object)d1.Tile).name + "." + ((Object)d1).name + " | " + ((Object)d2.Tile).name + "." + ((Object)d2).name); } yield return new DisconnectAction(d1, d2); } } } protected virtual IEnumerable<PropAction> HandleProps(DGameMap map) { Stopwatch timer = new Stopwatch(); timer.Start(); map.InitializeGlobalPropSets(this); foreach (PropAction item in HandleDoorProps(map)) { yield return item; } foreach (PropAction item2 in HandleTileProps(map)) { yield return item2; } foreach (PropAction item3 in HandleMapProps(map)) { yield return item3; } if (Config.Singleton.ForbiddenPassages) { DDoorway[] componentsInChildren = ((Component)map).GetComponentsInChildren<DDoorway>(); foreach (DDoorway d in componentsInChildren) { if (d.IsVacant && (Object)(object)d.ActiveRandomObject != (Object)null && Rng.Next(100) == 0) { d.ActiveRandomObject.SetActive(value: false); } } } timer.Stop(); Plugin.LogDebug($"Finished prop handling in {timer.Elapsed.TotalSeconds} seconds"); } private IEnumerable<PropAction> HandleDoorProps(DGameMap map) { if (Config.Singleton.EnableVerboseGeneration) { Plugin.LogDebug("Handling door props..."); } Stopwatch timer = new Stopwatch(); timer.Start(); DDoorway[] doorways = ((Component)map).GetComponentsInChildren<DDoorway>(); DDoorway[] array = doorways; foreach (DDoorway door in array) { if (!((Object)(object)door.ActiveRandomObject != (Object)null)) { DDoorway tgt = ((door.IsVacant || Rng.Next(2) == 0) ? door : ((DDoorway)door.Connection)); tgt.SetActiveObject((float)Rng.NextDouble()); } } DDoorway[] array2 = doorways; foreach (DDoorway door2 in array2) { foreach (Prop p in door2.IsVacant ? door2.Connectors : door2.Blockers) { yield return new PropAction(p, e: false); } } timer.Stop(); Plugin.LogDebug($"\tFinished door props in {timer.Elapsed.TotalSeconds} seconds"); } private IEnumerable<PropAction> HandleMapProps(DGameMap map) { if (Config.Singleton.EnableVerboseGeneration) { Plugin.LogDebug("Handling global props..."); } Stopwatch timer = new Stopwatch(); timer.Start(); foreach (PropSet propset in map.GlobalPropSets) { if (Config.Singleton.EnableVerboseGeneration) { Plugin.LogDebug("Handling propset w/ " + ((propset.Count > 0) ? ((Object)propset[0f]).name : "nothing in it") + " " + $"({propset.Count} props)"); } foreach (PropAction action2 in HandlePropSetPos(propset)) { if (Config.Singleton.EnableVerboseGeneration) { Plugin.LogDebug("+" + ((Object)action2.Prop).name); } yield return action2; } foreach (PropAction action in HandlePropSetNeg(propset, globalPropSet: true)) { if (Config.Singleton.EnableVerboseGeneration) { Plugin.LogDebug("-" + ((Object)action.Prop).name); } yield return action; } } timer.Stop(); Plugin.LogDebug($"\tFinished handling global props in {timer.Elapsed.TotalSeconds} seconds"); } private IEnumerable<PropAction> HandleTileProps(DGameMap map) { if (Config.Singleton.EnableVerboseGeneration) { Plugin.LogDebug("Handling local props..."); } Stopwatch timer = new Stopwatch(); timer.Start(); DTile[] componentsInChildren = ((Component)map).GetComponentsInChildren<DTile>(); foreach (DTile tile in componentsInChildren) { foreach (PropSet propset2 in tile.LocalPropSets) { foreach (PropAction action2 in HandlePropSetPos(propset2)) { if (Config.Singleton.EnableVerboseGeneration) { Plugin.LogDebug("+" + ((Object)action2.Prop).name); } yield return action2; } } foreach (PropSet propset in tile.LocalPropSets) { foreach (PropAction action in HandlePropSetNeg(propset)) { if (Config.Singleton.EnableVerboseGeneration) { Plugin.LogDebug("-" + ((Object)action.Prop).name); } yield return action; } } } timer.Stop(); Plugin.LogDebug($"\tFinished handling tile props in {timer.Elapsed.TotalSeconds} seconds"); } private IEnumerable<PropAction> HandlePropSetPos(PropSet propset) { if (propset == null) { Plugin.LogException(new ArgumentNullException("propset")); yield break; } WeightedList<Prop> copy = new WeightedList<Prop>(); int numActive = 0; int numEnable = Rng.Next(propset.Range.min, propset.Range.max + 1); if (numEnable > propset.Count) { numEnable = propset.Count; } foreach (var (prop, weight) in propset.Entries) { if ((Object)(object)prop == (Object)null && prop != null) { Plugin.LogError("Destroyed prop in propset"); } else if (((Component)prop).gameObject.activeSelf) { numActive++; } else if (!prop.IsDoorProp) { copy.Add(prop, weight); } } for (int i = numActive; i < numEnable; i++) { Prop tgt; do { if (copy.Count == 0) { tgt = null; break; } tgt = copy[copy.SummedWeight * (float)Rng.NextDouble()]; copy.Remove(tgt); } while (((Component)tgt).gameObject.activeSelf || !((Component)((Component)tgt).transform.parent).gameObject.activeInHierarchy); if ((Object)(object)tgt == (Object)null) { break; } yield return new PropAction(tgt, e: true); } } private IEnumerable<PropAction> HandlePropSetNeg(PropSet propset, bool globalPropSet = false) { if (propset == null) { Plugin.LogException(new ArgumentNullException("propset")); yield break; } WeightedList<Prop> copy = new WeightedList<Prop>(); int numActive = 0; int numEnable = propset.Range.max; if (numEnable > propset.Count) { numEnable = propset.Count; } foreach (var (prop, weight) in propset.Entries) { if ((Object)(object)prop == (Object)null && prop != null) { Plugin.LogError("Destroyed prop in propset"); } else if (((Component)prop).gameObject.activeInHierarchy) { numActive++; copy.Add(prop, weight); } } int i = numActive; while (i > numEnable && copy.Count != 0) { Prop tgt = copy[copy.SummedWeight * (float)Rng.NextDouble()]; copy.Remove(tgt); yield return new PropAction(tgt, e: false); i--; } } public virtual IEnumerable<GenerationAction> Generator(GameMap m) { Stopwatch timer = new Stopwatch(); timer.Start(); DGameMap map = (DGameMap)m; if ((Object)(object)map.RootTile == (Object)null) { foreach (PlacementInfo action in PlaceRoot(map)) { if (action != null) { yield return action; continue; } yield break; } } else { foreach (RemovalInfo item in RemoveTiles(map)) { yield return item; } } yield return new YieldFrame(); foreach (GenerationAction item2 in PlaceTiles(map)) { yield return item2; } Stopwatch conTimer = new Stopwatch(); conTimer.Start(); foreach (ConnectionAction item3 in HandleConnections(map)) { yield return item3; } conTimer.Stop(); Plugin.LogDebug($"Finished connections in {conTimer.Elapsed.TotalSeconds} seconds"); foreach (PropAction item4 in HandleProps(map)) { yield return item4; } yield return new YieldFrame(); timer.Stop(); Plugin.LogDebug($"Finished generation in {timer.Elapsed.TotalSeconds} seconds"); } } public class DDoorway : Doorway { protected List<Prop> alwaysBlockers; protected List<Prop> alwaysDoors; protected WeightedList<Prop> randomBlockerSet; protected WeightedList<Prop> randomDoorSet; protected Prop activeRandomObject = null; public float VerticalOffset => base.Tile.IntersectionTolerance + 0.125f; public Vector3 PositionOffset => ((Component)this).transform.up * VerticalOffset; public Prop ActiveRandomObject { get { return activeRandomObject; } protected set { activeRandomObject = value; } } public IEnumerable<Prop> Blockers { get { foreach (Prop alwaysBlocker in alwaysBlockers) { yield return alwaysBlocker; } foreach (Prop item in randomBlockerSet) { yield return item; } } } public IEnumerable<Prop> Connectors { get { foreach (Prop alwaysDoor in alwaysDoors) { yield return alwaysDoor; } foreach (Prop item in randomDoorSet) { yield return item; } } } public bool OwnsActiveRandomObject => (base.IsVacant ? randomBlockerSet : randomDoorSet).Contains(ActiveRandomObject); private void fixRotation() { //IL_0007: 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_000f: 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) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) Quaternion rotation = ((Component)this).transform.rotation; Vector3 eulerAngles = ((Quaternion)(ref rotation)).eulerAngles; ((Component)this).transform.rotation = Quaternion.Euler(new Vector3((float)(int)(eulerAngles.x + 0.5f), (float)(int)(eulerAngles.y + 0.5f), (float)(int)(eulerAngles.z + 0.5f))); } private Prop instantiateSubPart(GameObject o, bool isblocker) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)o == (Object)null) { return null; } if ((Object)(object)o.GetComponentInParent<Tile>(true) != (Object)(object)base.Tile) { o = Object.Instantiate<GameObject>(o); o.transform.SetParent(((Component)this).transform); o.transform.localPosition = -PositionOffset; o.transform.localRotation = Quaternion.identity; } Prop prop = o.GetComponent<Prop>() ?? o.AddComponent<Prop>(); if (isblocker) { prop.IsBlocker = true; } else { prop.IsConnector = true; } return prop; } public DDoorway() { if (!((Object)(object)((Component)this).gameObject == (Object)null)) { InitSize(); } } private void Awake() { base.OnDisconnectEvent += delegate { OnDisconnect(); }; base.OnConnectEvent += delegate { OnConnect(); }; } public void InitSize() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) Doorway component = ((Component)this).GetComponent<Doorway>(); base.Size = component.Socket.Size; } public override void Initialize() { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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) if (base.Initialized) { return; } base.Initialize(); InitSize(); fixRotation(); if ((Object)(object)base.Tile == (Object)null) { throw new NullReferenceException("DDoorway has no parent tile. "); } Transform transform = ((Component)this).transform; transform.position += PositionOffset; Doorway component = ((Component)this).GetComponent<Doorway>(); List<Prop> list = new List<Prop>(component.BlockerSceneObjects.Count); for (int i = 0; i < component.BlockerSceneObjects.Count; i++) { GameObject val = component.BlockerSceneObjects[i]; if (!((Object)(object)val == (Object)null)) { Prop prop = instantiateSubPart(val, isblocker: true); prop.Enable(); list.Add(prop); } } alwaysBlockers = list; list = new List<Prop>(component.ConnectorSceneObjects.Count); for (int j = 0; j < component.ConnectorSceneObjects.Count; j++) { GameObject val2 = component.ConnectorSceneObjects[j]; if (!((Object)(object)val2 == (Object)null)) { Prop prop2 = instantiateSubPart(val2, isblocker: false); prop2.Disable(); list.Add(prop2); } } alwaysDoors = list; randomBlockerSet = new WeightedList<Prop>(component.BlockerPrefabWeights.Count); foreach (GameObjectWeight blockerPrefabWeight in component.BlockerPrefabWeights) { GameObject gameObject = blockerPrefabWeight.GameObject; if (!((Object)(object)gameObject == (Object)null)) { Prop prop3 = instantiateSubPart(gameObject, isblocker: true); prop3.Disable(); randomBlockerSet.Add(prop3, blockerPrefabWeight.Weight); } } randomDoorSet = new WeightedList<Prop>(component.ConnectorPrefabWeights.Count); foreach (GameObjectWeight connectorPrefabWeight in component.ConnectorPrefabWeights) { GameObject gameObject2 = connectorPrefabWeight.GameObject; if (!((Object)(object)gameObject2 == (Object)null)) { Prop prop4 = instantiateSubPart(gameObject2, isblocker: false); prop4.Disable(); randomDoorSet.Add(prop4, connectorPrefabWeight.Weight); } } } protected bool CheckDunGenRule(TileConnectionRule rule, DDoorway other) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Invalid comparison between Unknown and I4 CanTilesConnectDelegate @delegate = rule.Delegate; return @delegate == null || (int)@delegate.Invoke(((Component)base.Tile).GetComponent<Tile>(), ((Component)other.Tile).GetComponent<Tile>(), ((Component)this).GetComponent<Doorway>(), ((Component)other).GetComponent<Doorway>()) != 1; } public override bool Fits(Doorway o) { if (!(o is DDoorway other)) { return false; } if (!base.Fits(other)) { return false; } foreach (TileConnectionRule customConnectionRule in DoorwayPairFinder.CustomConnectionRules) { if (!CheckDunGenRule(customConnectionRule, other)) { return false; } } return true; } protected virtual void OnConnect() { foreach (Prop alwaysBlocker in alwaysBlockers) { alwaysBlocker.Disable(); } foreach (Prop alwaysDoor in alwaysDoors) { alwaysDoor.Enable(); } activeRandomObject?.Disable(); activeRandomObject = null; } public virtual void SetActiveObject(float idx) { activeRandomObject?.Disable(); DDoorway dDoorway = (DDoorway)connection; if (base.IsVacant) { if (randomBlockerSet.Count == 0) { activeRandomObject = null; } else { activeRandomObject = randomBlockerSet[randomBlockerSet.SummedWeight * idx]; } } else { if (randomDoorSet.Count == 0) { activeRandomObject = null; if (dDoorway.randomDoorSet.Count != 0) { dDoorway.SetActiveObject(idx); } return; } activeRandomObject = randomDoorSet[randomDoorSet.SummedWeight * idx]; } activeRandomObject?.Enable(); if ((Object)(object)dDoorway != (Object)null) { dDoorway.activeRandomObject?.Disable(); dDoorway.activeRandomObject = activeRandomObject; } } public virtual void SetActiveObject(Prop prop) { activeRandomObject?.Disable(); DDoorway dDoorway = (DDoorway)connection; if (base.IsVacant) { if (!randomBlockerSet.Contains(prop)) { throw new ArgumentException("Provided prop '" + ((Object)prop).name + "' is not a randomBlocker of the door '" + ((Object)base.Tile).name + ":" + ((Object)this).name + "'"); } } else if (!randomDoorSet.Contains(prop)) { throw new ArgumentException("Provided prop '{prop.name}' is not a randomDoor of the door '" + ((Object)base.Tile).name + ":" + ((Object)this).name + "'"); } activeRandomObject = prop; activeRandomObject?.Enable(); if ((Object)(object)dDoorway != (Object)null) { dDoorway.activeRandomObject?.Disable(); dDoorway.activeRandomObject = activeRandomObject; } } public virtual IList<Prop> GetProps() { List<Prop> list = new List<Prop>(); IEnumerable<Prop> enumerable = alwaysBlockers.Concat(alwaysDoors).Concat(randomBlockerSet).Concat(randomDoorSet); foreach (Prop item in enumerable) { if (!list.Contains(item)) { list.Add(item); } } return list; } protected virtual void OnDisconnect() { if ((Object)(object)this == (Object)null) { return; } foreach (Prop alwaysBlocker in alwaysBlockers) { alwaysBlocker.Enable(); } foreach (Prop alwaysDoor in alwaysDoors) { alwaysDoor.Disable(); } activeRandomObject?.Disable(); activeRandomObject = null; } public bool RemoveProp(Prop p) { return alwaysBlockers.Remove(p) || alwaysDoors.Remove(p) || randomBlockerSet.Remove(p) || randomDoorSet.Remove(p); } } public class Prop : MonoBehaviour { public bool IsBlocker { get; set; } = false; public bool IsConnector { get; set; } = false; public bool IsTileProp { get; set; } = false; public bool IsMapProp { get; set; } = false; public bool IsDoorProp => IsBlocker || IsConnector; public DTile Tile => ((Component)this).GetComponentInParent<DTile>(((Component)this).gameObject.activeInHierarchy); public DDoorway Doorway => ((Component)this).GetComponentInParent<DDoorway>(((Component)this).gameObject.activeInHierarchy); public DGameMap Map => ((Component)this).GetComponentInParent<DGameMap>(((Component)this).gameObject.activeInHierarchy); public MonoBehaviour Parent => (MonoBehaviour)(IsDoorProp ? ((object)Doorway) : ((object)Tile)); public void SetActive(bool value) { if (value) { Enable(); } else { Disable(); } } public virtual void Enable() { if ((Object)(object)this == (Object)null) { Plugin.LogError("Cannot enable a prop which has been destroyed"); } else { ((Component)this).gameObject.SetActive(true); } } public virtual void Disable() { if ((Object)(object)this == (Object)null) { Plugin.LogError("Cannot disable a prop which has been destroyed"); } else { ((Component)this).gameObject.SetActive(false); } } protected virtual void OnDestroy() { if (IsDoorProp) { DDoorway doorway = Doorway; if ((Object)(object)doorway != (Object)null) { doorway.RemoveProp(this); } } DTile tile = Tile; if ((Object)(object)tile != (Object)null) { tile.RemoveProp(this); } DGameMap map = Map; if ((Object)(object)map != (Object)null) { map.RemoveProp(this); } } } public class PropSet : WeightedList<Prop> { public (int min, int max) Range { get; set; } = (0, 0); public WeightedList<Prop> Props => this; public PropSet() { } public PropSet(LocalPropSet pset) { foreach (GameObjectChance weight in pset.Props.Weights) { if (!((Object)(object)weight.Value == (Object)null)) { Prop prop = weight.Value.GetComponent<Prop>() ?? weight.Value.AddComponent<Prop>(); prop.IsTileProp = true; Add(prop, (weight.MainPathWeight + weight.BranchPathWeight) / 2f); } } Range = (pset.PropCount.Min, pset.PropCount.Max); } public override bool Add(Prop p, float weight) { if ((Object)(object)p == (Object)null) { return false; } if (Remove(p, out var weight2)) { return Add(p, weight + weight2); } return base.Add(p, weight); } } public class DTile : Tile { public List<Func<bool, PlacementInfo>> ValidatePlacement; protected List<PropSet> localPropSets; protected List<(Prop prop, int id, float weight)> globalProps; internal IList<PropSet> LocalPropSets { get { IList<PropSet> list = localPropSets?.AsReadOnly(); return list ?? new PropSet[0]; } } internal IList<(Prop prop, int id, float weight)> GlobalProps { get { IList<(Prop, int, float)> list = globalProps?.AsReadOnly(); return list ?? new(Prop, int, float)[0]; } } private Bounds DeriveBounds() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_05af: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: 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_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing ref