Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of TelAvivStage v0.4.1
plugins/TelAvivStage/TelAvivStage.dll
Decompiled 15 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security.Cryptography; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HG; using HG.Reflection; using R2API; using RoR2; using RoR2.ConVar; using RoR2.ContentManagement; using RoR2.Navigation; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.Networking; using UnityEngine.ResourceManagement.AsyncOperations; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: OptIn] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("TelAvivStage")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Tel Aviv, an original Risk of Rain 2 stage.")] [assembly: AssemblyFileVersion("0.4.0.0")] [assembly: AssemblyInformationalVersion("0.4.0")] [assembly: AssemblyProduct("TelAvivStage")] [assembly: AssemblyTitle("TelAvivStage")] [assembly: AssemblyVersion("0.4.0.0")] namespace TelAvivStage; internal sealed class TelAvivContent : IContentPackProvider { private readonly string folder; private readonly ManualLogSource log; private readonly int stageOrder; private readonly float weight; private readonly bool preLoop; private readonly bool postLoop; private AssetBundle sceneBundle; private AssetBundle assetsBundle; private AsyncOperationHandle<GameObject> teleporterIndicatorHandle; private AsyncOperationHandle<GameObject> hiddenPickupHandle; internal NavigationData Navigation; internal DccsPool MonsterPool; internal DccsPool InteractablePool; internal SpawnCard TeleporterCard; internal InteractableSpawnCard LemurianEgg; internal SceneDef Definition; public string identifier => "com.gal66.telavivstage"; internal string BundleFingerprint { get; } internal TelAvivContent(string folder, ManualLogSource log, int stageOrder, float weight, bool preLoop, bool postLoop) { TelAvivContent telAvivContent = this; this.folder = Path.Combine(folder, "AssetBundles"); this.log = log; this.stageOrder = stageOrder; this.weight = weight; this.preLoop = preLoop; this.postLoop = postLoop; SHA256 hash = SHA256.Create(); try { IEnumerable<string> values = new string[2] { "telavivscene", "telavivassets" }.Select(delegate(string name) { string text = Path.Combine(telAvivContent.folder, name); if (!File.Exists(text)) { throw new FileNotFoundException("Tel Aviv requires both built asset bundles.", text); } using FileStream inputStream = File.OpenRead(text); return BitConverter.ToString(hash.ComputeHash(inputStream)).Replace("-", ""); }); BundleFingerprint = string.Join("", values); } finally { if (hash != null) { ((IDisposable)hash).Dispose(); } } } public IEnumerator LoadStaticContentAsync(LoadStaticContentAsyncArgs args) { AssetBundleCreateRequest sceneRequest = AssetBundle.LoadFromFileAsync(Path.Combine(folder, "telavivscene")); yield return sceneRequest; sceneBundle = sceneRequest.assetBundle; AssetBundleCreateRequest assetRequest = AssetBundle.LoadFromFileAsync(Path.Combine(folder, "telavivassets")); yield return assetRequest; assetsBundle = assetRequest.assetBundle; if (!Object.op_Implicit((Object)(object)sceneBundle) || !Object.op_Implicit((Object)(object)assetsBundle) || !sceneBundle.GetAllScenePaths().Any((string path) => Path.GetFileNameWithoutExtension(path) == "telaviv_city")) { throw new InvalidDataException("Tel Aviv scene bundle is missing telaviv_city."); } TextAsset val = assetsBundle.LoadAsset<TextAsset>("telaviv_navigation"); if (!Object.op_Implicit((Object)(object)val)) { throw new InvalidDataException("Tel Aviv navigation was not baked."); } Navigation = JsonUtility.FromJson<NavigationData>(val.text); if (Navigation == null || Navigation.ground == null || Navigation.ground.Length < 40 || Navigation.air == null || Navigation.air.Length < 10) { throw new InvalidDataException("Tel Aviv needs valid baked ground and air navigation graphs."); } args.ReportProgress(0.4f); MonsterPool = Addressables.LoadAssetAsync<DccsPool>((object)"RoR2/Base/goolake/dpGooLakeMonsters.asset").WaitForCompletion(); InteractablePool = Addressables.LoadAssetAsync<DccsPool>((object)"RoR2/Base/goolake/dpGooLakeInteractables.asset").WaitForCompletion(); TeleporterCard = Addressables.LoadAssetAsync<SpawnCard>((object)"RoR2/Base/Teleporters/iscTeleporter.asset").WaitForCompletion(); LemurianEgg = Addressables.LoadAssetAsync<InteractableSpawnCard>((object)"RoR2/CU8/LemurianEgg/iscLemurianEgg.asset").WaitForCompletion(); if (!Object.op_Implicit((Object)(object)MonsterPool) || !Object.op_Implicit((Object)(object)InteractablePool) || !Object.op_Implicit((Object)(object)TeleporterCard)) { throw new InvalidOperationException("Required base-game director assets are unavailable."); } teleporterIndicatorHandle = LegacyResourcesAPI.LoadAsync<GameObject>("Prefabs/PositionIndicators/TeleporterChargingPositionIndicator"); hiddenPickupHandle = LegacyResourcesAPI.LoadAsync<GameObject>("Prefabs/PickupModels/PickupMystery"); yield return teleporterIndicatorHandle; yield return hiddenPickupHandle; if (!teleporterIndicatorHandle.IsValid() || !hiddenPickupHandle.IsValid() || (int)teleporterIndicatorHandle.Status != 1 || (int)hiddenPickupHandle.Status != 1 || !Object.op_Implicit((Object)(object)teleporterIndicatorHandle.Result) || !Object.op_Implicit((Object)(object)hiddenPickupHandle.Result)) { throw new InvalidOperationException("Required teleporter/pickup presentation assets failed to preload."); } Definition = ScriptableObject.CreateInstance<SceneDef>(); Definition.cachedName = "telaviv_city"; Definition.baseSceneNameOverride = "telaviv_city"; Definition.sceneType = (SceneType)1; Definition.stageOrder = stageOrder; Definition.isOfflineScene = false; Definition.nameToken = "TELAVIV_NAME"; Definition.subtitleToken = "TELAVIV_SUBTITLE"; Definition.portalSelectionMessageString = "TELAVIV_SEER"; Definition.loreToken = "TELAVIV_LORE"; Definition.shouldIncludeInLogbook = false; Definition.validForRandomSelection = true; Definition.allowItemsToSpawnObjects = true; Definition.environmentColor = new Color(0.57f, 0.71f, 0.74f); Definition.mainTrack = Addressables.LoadAssetAsync<MusicTrackDef>((object)"RoR2/Base/Common/MusicTrackDefs/muSong13.asset").WaitForCompletion(); Definition.bossTrack = Addressables.LoadAssetAsync<MusicTrackDef>((object)"RoR2/Base/Common/MusicTrackDefs/muSong05.asset").WaitForCompletion(); Definition.previewTexture = (Texture)(object)assetsBundle.LoadAsset<Texture2D>("telaviv_preview"); if (Object.op_Implicit((Object)(object)Definition.previewTexture)) { Definition.portalMaterial = StageRegistration.MakeBazaarSeerMaterial((Texture2D)Definition.previewTexture); } GameFields.Set(Definition, "shouldUpdateSceneCollectionAfterLooping", true); StageRegistration.RegisterSceneDefToNormalProgression(Definition, weight, preLoop, postLoop); args.ReportProgress(1f); } public IEnumerator GenerateContentPackAsync(GetContentPackAsyncArgs args) { args.output.sceneDefs.Add((SceneDef[])(object)new SceneDef[1] { Definition }); args.ReportProgress(1f); yield break; } public IEnumerator FinalizeAsync(FinalizeAsyncArgs args) { log.LogInfo((object)string.Format("Tel Aviv registered as independent stage {0}; {1} ground nodes and {2} air nodes. Scene: {3}.", stageOrder, Navigation.ground.Length, Navigation.air.Length, "telaviv_city")); args.ReportProgress(1f); yield break; } } [Serializable] internal sealed class NavigationData { public int schemaVersion; public GraphNode[] ground; public GraphNode[] air; public Point[] spawnPoints; public Point[] teleporterPoints; public Point boundsMin; public Point boundsMax; } [Serializable] internal sealed class Point { public float x; public float y; public float z; public Vector3 Vector => new Vector3(x, y, z); } [Serializable] internal sealed class GraphNode { public float x; public float y; public float z; public int flags; public int forbiddenHulls; public GraphLink[] links; public int[] visible; public Vector3 Vector => new Vector3(x, y, z); } [Serializable] internal sealed class GraphLink { public int index; public int hullMask; public float distance; } [BepInPlugin("com.gal66.telavivstage", "Tel Aviv", "0.4.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class TelAvivPlugin : BaseUnityPlugin { public const string PluginGuid = "com.gal66.telavivstage"; public const string PluginName = "Tel Aviv"; public const string PluginVersion = "0.4.0"; public const string SceneName = "telaviv_city"; private TelAvivContent content; private void Awake() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Expected O, but got Unknown ConfigEntry<int> val = ((BaseUnityPlugin)this).Config.Bind<int>("Rotation", "StageOrder", 2, new ConfigDescription("Normal loop slot, 1 to 4. Restart required. Slot 5 is reserved for the primordial teleporter.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 4), Array.Empty<object>())); ConfigEntry<float> val2 = ((BaseUnityPlugin)this).Config.Bind<float>("Rotation", "SelectionWeight", 1f, new ConfigDescription("Relative chance against other maps in the same slot. Restart required.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 10f), Array.Empty<object>())); ConfigEntry<bool> val3 = ((BaseUnityPlugin)this).Config.Bind<bool>("Rotation", "BeforeFirstLoop", true, "Allow Tel Aviv before the first loop. Restart required."); ConfigEntry<bool> val4 = ((BaseUnityPlugin)this).Config.Bind<bool>("Rotation", "AfterFirstLoop", true, "Allow Tel Aviv after looping. Restart required."); string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location); content = new TelAvivContent(directoryName, ((BaseUnityPlugin)this).Logger, val.Value, val2.Value, val3.Value, val4.Value); NetworkModCompatibilityHelper.networkModList = NetworkModCompatibilityHelper.networkModList.Append("com.gal66.telavivstage;0.4.0;" + content.BundleFingerprint + ";" + val.Value + ";" + val3.Value + ";" + val4.Value).ToArray(); ContentManager.collectContentPackProviders += new CollectContentPackProvidersDelegate(AddProvider); SceneManager.sceneLoaded += OnSceneLoaded; LanguageAPI.Add("TELAVIV_NAME", "Tel Aviv"); LanguageAPI.Add("TELAVIV_SUBTITLE", "The White City, Adrift"); LanguageAPI.Add("TELAVIV_SEER", "You dream of salt, concrete, and sleepless streets."); LanguageAPI.Add("TELAVIV_LORE", "A city remembered in fragments: three towers above a market, pale balconies turned toward the sea, and painted alleys that never learned to sleep. The distance between neighborhoods has collapsed. The streets still know the way."); if (Environment.GetCommandLineArgs().Contains("-telaviv-smoke")) { TelAvivSmokeTest telAvivSmokeTest = ((Component)this).gameObject.AddComponent<TelAvivSmokeTest>(); telAvivSmokeTest.Log = ((BaseUnityPlugin)this).Logger; telAvivSmokeTest.OutputDirectory = directoryName; } } private void AddProvider(AddContentPackProviderDelegate addProvider) { addProvider.Invoke((IContentPackProvider)(object)content); } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (((Scene)(ref scene)).name != "telaviv_city") { return; } try { TelAvivScene.Setup(scene, content, ((BaseUnityPlugin)this).Logger); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Tel Aviv scene setup failed: " + ex)); } } private void OnDestroy() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown ContentManager.collectContentPackProviders -= new CollectContentPackProvidersDelegate(AddProvider); SceneManager.sceneLoaded -= OnSceneLoaded; } } internal static class GameFields { internal static void Set(object target, string field, object value) { FieldInfo? field2 = target.GetType().GetField(field, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field2 == null) { throw new MissingFieldException(target.GetType().FullName, field); } field2.SetValue(target, value); } } internal static class TelAvivScene { internal static void Setup(Scene scene, TelAvivContent content, ManualLogSource log) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Expected O, but got Unknown //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_02fe: Unknown result type (might be due to invalid IL or missing references) //IL_0308: Unknown result type (might be due to invalid IL or missing references) //IL_030d: Unknown result type (might be due to invalid IL or missing references) //IL_0346: Unknown result type (might be due to invalid IL or missing references) //IL_034b: Unknown result type (might be due to invalid IL or missing references) //IL_035d: Unknown result type (might be due to invalid IL or missing references) //IL_0362: Unknown result type (might be due to invalid IL or missing references) //IL_038d: Unknown result type (might be due to invalid IL or missing references) //IL_038f: Unknown result type (might be due to invalid IL or missing references) //IL_0391: Unknown result type (might be due to invalid IL or missing references) //IL_039b: Unknown result type (might be due to invalid IL or missing references) //IL_03a5: Unknown result type (might be due to invalid IL or missing references) //IL_03a7: Unknown result type (might be due to invalid IL or missing references) //IL_03a9: Unknown result type (might be due to invalid IL or missing references) //IL_03ba: Unknown result type (might be due to invalid IL or missing references) //IL_03c0: Unknown result type (might be due to invalid IL or missing references) if (((Scene)(ref scene)).GetRootGameObjects().Any((GameObject go) => ((Object)go).name == "TelAviv.Runtime")) { return; } if (content.Navigation == null) { throw new InvalidOperationException("Content pack has not loaded."); } GameObject val = new GameObject("TelAviv.Runtime"); SceneManager.MoveGameObjectToScene(val, scene); val.SetActive(false); NodeGraph val2 = BuildGraph(content.Navigation.ground, "TelAvivGround", val.transform); NodeGraph val3 = BuildGraph(content.Navigation.air, "TelAvivAir", val.transform); GameObject obj = Child(val, "SceneInfo"); SceneInfo val4 = obj.AddComponent<SceneInfo>(); GameFields.Set(val4, "groundNodesAsset", val2); GameFields.Set(val4, "airNodesAsset", val3); ClassicStageInfo val5 = obj.AddComponent<ClassicStageInfo>(); GameFields.Set(val5, "monsterDccsPool", content.MonsterPool); GameFields.Set(val5, "interactableDccsPool", content.InteractablePool); val5.sceneDirectorInteractibleCredits = 360; val5.sceneDirectorMonsterCredits = 25; val5.bonusInteractibleCreditObjects = Array.Empty<BonusInteractibleCreditObject>(); val5.possibleMonsterFamilies = Array.Empty<MonsterFamily>(); GameObject val6 = Child(val, "Director"); val6.AddComponent<DirectorCore>(); SceneDirector val7 = val6.AddComponent<SceneDirector>(); ((Behaviour)val7).enabled = false; val7.teleporterSpawnCard = content.TeleporterCard; val7.lumerianEgg = new DirectorCard { spawnCard = (SpawnCard)(object)content.LemurianEgg, selectionWeight = 1 }; val7.expRewardCoefficient = 0.2f; val7.eliteBias = 1f; val7.spawnDistanceMultiplier = 1f; ConfigureCombatDirector(val6.AddComponent<CombatDirector>(), 2.3f, 4.3f); ConfigureCombatDirector(val6.AddComponent<CombatDirector>(), 22f, 30f); Child(val, "GameManager").AddComponent<GlobalEventManager>(); Vector3 entryOrigin = content.Navigation.spawnPoints[0].Vector; IOrderedEnumerable<GraphNode> orderedEnumerable = content.Navigation.ground.Where((GraphNode node) => (node.flags & 1) != 0 && (node.flags & 4) == 0 && (node.forbiddenHulls & 2) == 0 && content.Navigation.teleporterPoints.All((Point point) => Vector3.Distance(node.Vector, point.Vector) >= 45f)).OrderBy(delegate(GraphNode node) { //IL_0001: 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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) Vector3 val8 = node.Vector - entryOrigin; return ((Vector3)(ref val8)).sqrMagnitude; }); List<GraphNode> list = new List<GraphNode>(); foreach (GraphNode candidate in orderedEnumerable) { if (!list.Any((GraphNode node) => Vector3.Distance(node.Vector, candidate.Vector) < 6f)) { list.Add(candidate); if (list.Count >= RoR2Application.maxPlayers) { break; } } } if (list.Count < RoR2Application.maxPlayers) { throw new InvalidOperationException("Tel Aviv has insufficient clear entry nodes away from teleporter plazas."); } foreach (GraphNode item in list) { GameObject obj2 = Child(val, "PlayerSpawn"); obj2.transform.position = item.Vector + Vector3.up * 0.15f; obj2.AddComponent<SpawnPoint>(); } Vector3 vector = content.Navigation.boundsMin.Vector; Vector3 vector2 = content.Navigation.boundsMax.Vector; GameObject obj3 = Child(val, "MapBounds"); obj3.layer = LayerIndex.defaultLayer.intVal; BoxCollider obj4 = obj3.AddComponent<BoxCollider>(); ((Collider)obj4).isTrigger = true; obj4.center = (vector + vector2) * 0.5f; obj4.size = vector2 - vector; MapZone obj5 = obj3.AddComponent<MapZone>(); obj5.triggerType = (TriggerType)0; obj5.zoneType = (ZoneType)0; TelAvivSceneMonitor telAvivSceneMonitor = val.AddComponent<TelAvivSceneMonitor>(); telAvivSceneMonitor.Log = log; ((Behaviour)telAvivSceneMonitor).enabled = false; TelAvivDirectorActivation telAvivDirectorActivation = val.AddComponent<TelAvivDirectorActivation>(); telAvivDirectorActivation.Log = log; telAvivDirectorActivation.Director = val7; telAvivDirectorActivation.CombatDirectors = val6.GetComponents<CombatDirector>(); telAvivDirectorActivation.Monitor = telAvivSceneMonitor; val.SetActive(true); typeof(ClassicStageInfo).GetMethod("RebuildCards", BindingFlags.Instance | BindingFlags.NonPublic)?.Invoke(val5, new object[2]); Object.Destroy((Object)(object)val2); Object.Destroy((Object)(object)val3); log.LogInfo((object)$"TELAVIV_BOOTSTRAP scene={((Scene)(ref scene)).name} server={NetworkServer.active} ground={val4.groundNodes.GetNodeCount()} air={val4.airNodes.GetNodeCount()} director=ready"); } private static void ConfigureCombatDirector(CombatDirector director, float minReroll, float maxReroll) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Expected O, but got Unknown //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Expected O, but got Unknown ((Behaviour)director).enabled = false; director.customName = ((minReroll < 10f) ? "Tel Aviv fast waves" : "Tel Aviv slow waves"); director.minRerollSpawnInterval = minReroll; director.maxRerollSpawnInterval = maxReroll; director.moneyWaveIntervals = (RangeFloat[])(object)new RangeFloat[2] { new RangeFloat { min = 0.5f, max = 0.5f }, new RangeFloat { min = 3f, max = 4f } }; director.creditMultiplier = 0.75f; director.expRewardCoefficient = 0.2f; director.goldRewardCoefficient = 1f; director.spawnDistanceMultiplier = 1f; director.maxSpawnDistance = 120f; director.onSpawnedServer = new OnSpawnedServer(); director.onSpawnedWithDirectorServer = new OnSpawnedWithDirectorServer(); } private static GameObject Child(GameObject parent, string name) { //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_0019: Expected O, but got Unknown GameObject val = new GameObject(name); val.transform.SetParent(parent.transform, false); return val; } private static NodeGraph BuildGraph(GraphNode[] data, string name, Transform parent) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Expected O, but got Unknown //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) NodeGraph val = ScriptableObject.CreateInstance<NodeGraph>(); ((Object)val).name = name; GameObject val2 = new GameObject(name + ".Source"); val2.transform.SetParent(parent, false); List<MapNode> list = new List<MapNode>(data.Length); List<SerializableBitArray> list2 = new List<SerializableBitArray>(data.Length); for (int i = 0; i < data.Length; i++) { GameObject val3 = new GameObject("Node" + i); val3.transform.SetParent(val2.transform, false); val3.transform.position = data[i].Vector; MapNode val4 = val3.AddComponent<MapNode>(); val4.flags = (NodeFlags)(byte)data[i].flags; val4.forbiddenHulls = (HullMask)data[i].forbiddenHulls; list.Add(val4); SerializableBitArray val5 = new SerializableBitArray(data.Length); int[] visible = data[i].visible; foreach (int num in visible) { val5[num] = true; } list2.Add(val5); } for (int k = 0; k < data.Length; k++) { GraphLink[] links = data[k].links; foreach (GraphLink graphLink in links) { list[k].links.Add(new Link { nodeB = list[graphLink.index], distanceScore = graphLink.distance, hullMask = graphLink.hullMask, jumpHullMask = 0, minJumpHeight = 0f, gateName = "" }); } } val.SetNodes(list.AsReadOnly(), list2.AsReadOnly()); Object.Destroy((Object)(object)val2); return val; } } internal sealed class TelAvivDirectorActivation : MonoBehaviour { internal ManualLogSource Log; internal SceneDirector Director; internal CombatDirector[] CombatDirectors; internal TelAvivSceneMonitor Monitor; private IEnumerator Start() { float deadline = Time.realtimeSinceStartup + 60f; while ((!Object.op_Implicit((Object)(object)Stage.instance) || !Object.op_Implicit((Object)(object)Stage.instance.sceneDef) || Stage.instance.sceneDef.cachedName != "telaviv_city" || Stage.instance.entryDifficultyCoefficient <= 0f) && Time.realtimeSinceStartup < deadline) { yield return null; } if (!Object.op_Implicit((Object)(object)Stage.instance) || !Object.op_Implicit((Object)(object)Stage.instance.sceneDef) || Stage.instance.sceneDef.cachedName != "telaviv_city" || Stage.instance.entryDifficultyCoefficient <= 0f) { Log.LogError((object)"TELAVIV_VALIDATION_FAILED: vanilla network Stage initialization timed out; population was not started."); yield break; } CombatDirector[] combatDirectors = CombatDirectors; for (int i = 0; i < combatDirectors.Length; i++) { ((Behaviour)combatDirectors[i]).enabled = true; } ((Behaviour)Director).enabled = true; ((Behaviour)Monitor).enabled = true; Log.LogInfo((object)$"TELAVIV_STAGE_READY difficulty={Stage.instance.entryDifficultyCoefficient} entryPoints={SpawnPoint.readOnlyInstancesList.Count}; scene population enabled"); } } internal sealed class TelAvivSceneMonitor : MonoBehaviour { internal ManualLogSource Log; private float remaining = 3f; private void Update() { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) remaining -= Time.unscaledDeltaTime; if (remaining > 0f) { return; } ((Behaviour)this).enabled = false; if (NetworkServer.active) { TeleporterInteraction instance = TeleporterInteraction.instance; Log.LogInfo((object)string.Format("TELAVIV_POPULATED teleporter={0} combatDirectors={1} interactables={2} monsters={3}", Object.op_Implicit((Object)(object)instance) ? ((object)((Component)instance).transform.position/*cast due to .constrained prefix*/).ToString() : "MISSING", CombatDirector.instancesList.Count, Object.FindObjectsOfType<PurchaseInteraction>().Length, TeamComponent.GetTeamMembers((TeamIndex)2).Count)); if (!Object.op_Implicit((Object)(object)instance)) { Log.LogError((object)"TELAVIV_VALIDATION_FAILED: no teleporter was spawned."); } } } } internal sealed class TelAvivSmokeTest : MonoBehaviour { private sealed class SurveyCamera : MonoBehaviour, ICameraStateProvider { internal Vector3 Position; internal Vector3 Target; public void GetCameraState(CameraRigController rig, ref CameraState state) { //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_000e: 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_0019: 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_0023: Unknown result type (might be due to invalid IL or missing references) state.position = Position; state.rotation = Quaternion.LookRotation(Target - Position); state.fov = 68f; } public bool IsUserLookAllowed(CameraRigController rig) { return false; } public bool IsUserControlAllowed(CameraRigController rig) { return false; } public bool IsHudAllowed(CameraRigController rig) { return true; } } internal ManualLogSource Log; internal string OutputDirectory; private bool initialSceneSelected; private bool overrideCleared; private bool roofProbesPassed; private void OnRunStarted(Run run) { Run.onRunStartGlobal -= OnRunStarted; initialSceneSelected = Object.op_Implicit((Object)(object)run.nextStageScene) && run.nextStageScene.cachedName == "telaviv_city"; object? obj = typeof(Run).GetField("cvRunSceneOverride", BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null); StringConVar val = (StringConVar)((obj is StringConVar) ? obj : null); if (val != null) { ((BaseConVar)val).SetString(string.Empty); overrideCleared = ((BaseConVar)val).GetString() == string.Empty; } Console.instance.SubmitCmd((NetworkUser)null, "run_prevent_gameover 1", false); Log.LogInfo((object)$"TELAVIV_SMOKE_INITIAL_SELECTION selected={initialSceneSelected} overrideCleared={overrideCleared}"); } private void OnDestroy() { Run.onRunStartGlobal -= OnRunStarted; } private IEnumerator Start() { float deadline = Time.realtimeSinceStartup + 180f; while ((!RoR2Application.loadFinished || !Object.op_Implicit((Object)(object)Console.instance)) && Time.realtimeSinceStartup < deadline) { yield return null; } if (!RoR2Application.loadFinished) { Log.LogError((object)"TELAVIV_SMOKE_FAILED: application startup timeout"); yield break; } yield return (object)new WaitForSecondsRealtime(3f); Log.LogInfo((object)"TELAVIV_SMOKE: starting a non-listening local test session"); Console.instance.SubmitCmd((NetworkUser)null, "gamemode ClassicRun; host 0", false); deadline = Time.realtimeSinceStartup + 60f; while ((!NetworkServer.active || !Object.op_Implicit((Object)(object)PreGameController.instance)) && Time.realtimeSinceStartup < deadline) { yield return null; } if (!Object.op_Implicit((Object)(object)PreGameController.instance)) { Log.LogError((object)"TELAVIV_SMOKE_FAILED: local pregame timeout"); yield break; } GameFields.Set(CheatsConVar.instance, "_boolValue", true); ((BaseConVar)CheatsConVar.instance).SetString("1"); Run.onRunStartGlobal += OnRunStarted; Console.instance.SubmitCmd((NetworkUser)null, "run_scene_override telaviv_city; pregame_start_run", false); deadline = Time.realtimeSinceStartup + 90f; Scene scene; while (true) { if (Object.op_Implicit((Object)(object)SceneInfo.instance)) { scene = ((Component)SceneInfo.instance).gameObject.scene; if (!(((Scene)(ref scene)).name != "telaviv_city")) { break; } } if (!(Time.realtimeSinceStartup < deadline)) { break; } yield return null; } if (Object.op_Implicit((Object)(object)SceneInfo.instance)) { scene = ((Component)SceneInfo.instance).gameObject.scene; if (!(((Scene)(ref scene)).name != "telaviv_city")) { if (Object.op_Implicit((Object)(object)Run.instance)) { Console.instance.SubmitCmd((NetworkUser)null, "run_prevent_gameover 1", false); } yield return (object)new WaitForSecondsRealtime(8f); SceneDef def = SceneInfo.instance.sceneDef; NodeGraph groundNodes = SceneInfo.instance.groundNodes; int groundCount = ((groundNodes != null) ? groundNodes.GetNodeCount() : 0); NodeGraph airNodes = SceneInfo.instance.airNodes; int airCount = ((airNodes != null) ? airNodes.GetNodeCount() : 0); SceneDef next = Run.instance?.nextStageScene; bool stageReady = Object.op_Implicit((Object)(object)Stage.instance) && (Object)(object)Stage.instance.sceneDef == (Object)(object)def && Stage.instance.entryDifficultyCoefficient > 0f; bool flag = false; if (Object.op_Implicit((Object)(object)def) && Object.op_Implicit((Object)(object)def.destinationsGroup) && Object.op_Implicit((Object)(object)next)) { Enumerator<SceneEntry> enumerator = def.destinationsGroup.sceneEntries.GetEnumerator(); try { while (enumerator.MoveNext()) { SceneEntry current = enumerator.Current; if ((Object)(object)current.sceneDef == (Object)(object)next || (Object)(object)current.fallbackSceneDef == (Object)(object)next) { flag = true; } } } finally { ((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose(); } } bool validNextStage = Object.op_Implicit((Object)(object)def) && Object.op_Implicit((Object)(object)next) && (Object)(object)next != (Object)(object)def && (int)next.sceneType == 1 && next.stageOrder == def.stageOrder + 1 && flag; LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser(); CharacterBody body = ((firstLocalUser != null) ? firstLocalUser.cachedBody : null); if (Object.op_Implicit((Object)(object)body) && Object.op_Implicit((Object)(object)body.currentVehicle)) { body.currentVehicle.EjectPassenger(); yield return (object)new WaitForSecondsRealtime(1f); } Log.LogInfo((object)(Object.op_Implicit((Object)(object)body) ? ("TELAVIV_SMOKE_PLAYER body=" + ((Object)body).name) : "TELAVIV_SMOKE_NO_LOCAL_PLAYER: screenshot records the current camera; this is not a player gameplay capture.")); string screenshotPath = Path.Combine(OutputDirectory, "smoke-telaviv.png"); bool screenshotRequested = false; try { if (File.Exists(screenshotPath)) { File.Delete(screenshotPath); } ScreenCapture.CaptureScreenshot(screenshotPath); screenshotRequested = true; } catch (Exception ex) { Log.LogError((object)("TELAVIV_SMOKE_SCREENSHOT_FAILED: " + ex.Message)); } if (screenshotRequested) { yield return (object)new WaitForEndOfFrame(); yield return null; deadline = Time.realtimeSinceStartup + 10f; while (!ScreenshotExists(screenshotPath) && Time.realtimeSinceStartup < deadline) { yield return null; } } bool screenshotWritten = screenshotRequested && ScreenshotExists(screenshotPath); Log.LogInfo((object)$"TELAVIV_SMOKE_SCREENSHOT written={screenshotWritten} localPlayer={Object.op_Implicit((Object)(object)body)} path={screenshotPath}"); if (Object.op_Implicit((Object)(object)body)) { yield return RoofProbes(body); } object[] obj = new object[12] { groundCount, airCount, stageReady, Object.op_Implicit((Object)(object)TeleporterInteraction.instance), Object.op_Implicit((Object)(object)def) && def.hasAnyDestinations, null, null, null, null, null, null, null }; obj[5] = ((next != null) ? next.cachedName : null); obj[6] = next?.stageOrder; obj[7] = validNextStage; obj[8] = overrideCleared; obj[9] = (Object)(object)DirectorCore.instance != (Object)null; obj[10] = screenshotWritten; obj[11] = Object.op_Implicit((Object)(object)body); string text = string.Format("ground={0} air={1} stageReady={2} teleporter={3} progression={4} next={5} nextOrder={6} validNext={7} overrideCleared={8} director={9} screenshot={10} localPlayer={11}; teleporter charging and stage exit were not exercised", obj); text += $"; roofStandingProbes={roofProbesPassed}"; if (initialSceneSelected && overrideCleared && stageReady && groundCount > 0 && airCount > 0 && Object.op_Implicit((Object)(object)TeleporterInteraction.instance) && validNextStage && Object.op_Implicit((Object)(object)DirectorCore.instance) && screenshotWritten && roofProbesPassed) { Log.LogInfo((object)("TELAVIV_SMOKE_COMPLETE: " + text)); } else { Log.LogError((object)("TELAVIV_SMOKE_FAILED: " + text)); } yield break; } } Log.LogError((object)"TELAVIV_SMOKE_FAILED: stage load timeout"); } private IEnumerator RoofProbes(CharacterBody body) { Vector3[] positions = (Vector3[])(object)new Vector3[11] { new Vector3(100f, 20f, -27f), new Vector3(-142f, 16.46f, 32f), new Vector3(158f, 32f, 155f), new Vector3(53f, 0f, -59f), new Vector3(-64.5f, 0.41f, 55f), new Vector3(-99f, 0f, -160f), new Vector3(102f, 0f, -123f), new Vector3(-118f, 0f, -48f), new Vector3(96f, 4f, 56f), new Vector3(-60f, 5.8f, 165f), new Vector3(-52.5f, 0f, -174f) }; string[] names = new string[11] { "market-roof", "white-city-roof", "azrieli-lookout", "jasmino", "hakosem", "levinsky", "abulafia", "abuhassan", "miznon", "anita", "puaa" }; Vector3[] views = (Vector3[])(object)new Vector3[11] { new Vector3(85f, 26f, -42f), new Vector3(-161f, 23f, 12f), new Vector3(165f, 38f, 163f), new Vector3(62f, 6f, -48f), new Vector3(-69f, 4.5f, 43f), new Vector3(-94f, 3.8f, -165f), new Vector3(102f, 5.8f, -133f), new Vector3(-118f, 4f, -59f), new Vector3(96f, 8.5f, 43f), new Vector3(-62f, 8.6f, 156f), new Vector3(-48f, 4f, -186f) }; Vector3[] targets = (Vector3[])(object)new Vector3[11] { new Vector3(132f, 20f, 65f), new Vector3(-110f, 16f, 30f), new Vector3(80f, 12f, 45f), new Vector3(52.5f, 3.4f, -73f), new Vector3(-64.5f, 3.2f, 64f), new Vector3(-99f, 2.5f, -151f), new Vector3(102f, 4.5f, -112f), new Vector3(-118f, 2.4f, -40f), new Vector3(96f, 6.8f, 62f), new Vector3(-60f, 8.6f, 173f), new Vector3(-52.5f, 2.8f, -167f) }; CameraRigController rig = null; foreach (CameraRigController readOnlyInstances in CameraRigController.readOnlyInstancesList) { if (Object.op_Implicit((Object)(object)readOnlyInstances) && readOnlyInstances.localUserViewer != null) { rig = readOnlyInstances; break; } } SurveyCamera survey = new GameObject("Tel Aviv diagnostic camera").AddComponent<SurveyCamera>(); bool previousGod = body.healthComponent.godMode; Vector3 start = body.footPosition; body.healthComponent.godMode = true; roofProbesPassed = true; for (int i = 0; i < positions.Length; i++) { TeleportHelper.TeleportBody(body, positions[i] + Vector3.up * 2f, true); survey.Position = views[i]; survey.Target = targets[i]; if (Object.op_Implicit((Object)(object)rig)) { rig.SetOverrideCam((ICameraStateProvider)(object)survey, 0f); } yield return (object)new WaitForSecondsRealtime(2f); Vector3 footPosition = body.footPosition; bool flag = Mathf.Abs(footPosition.y - positions[i].y) < 0.8f && Vector3.Distance(new Vector3(footPosition.x, positions[i].y, footPosition.z), positions[i]) < 2f; roofProbesPassed &= flag; Log.LogInfo((object)$"TELAVIV_ROOF_PROBE {names[i]} supported={flag} feet={footPosition} expected={positions[i]}"); string path = Path.Combine(OutputDirectory, "smoke-view-" + names[i] + ".png"); if (File.Exists(path)) { File.Delete(path); } ScreenCapture.CaptureScreenshot(path); yield return (object)new WaitForEndOfFrame(); yield return null; float deadline = Time.realtimeSinceStartup + 5f; while (!ScreenshotExists(path) && Time.realtimeSinceStartup < deadline) { yield return null; } roofProbesPassed &= ScreenshotExists(path); } if (Object.op_Implicit((Object)(object)rig)) { rig.SetOverrideCam((ICameraStateProvider)null, 0f); } Object.Destroy((Object)(object)((Component)survey).gameObject); TeleportHelper.TeleportBody(body, start + Vector3.up * 2f, true); body.healthComponent.godMode = previousGod; } private static bool ScreenshotExists(string path) { try { return File.Exists(path) && new FileInfo(path).Length > 0; } catch (IOException) { return false; } } }