using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Mirror; using UnityEngine; 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: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("Mirror")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("clearwater.atlyss.additionalfasttravel")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.1.1.0")] [assembly: AssemblyInformationalVersion("1.1.1+9d764c15a3bba5167e5e9effa559e6f348d4c4f3")] [assembly: AssemblyProduct("AdditionalFastTravel")] [assembly: AssemblyTitle("clearwater.atlyss.additionalfasttravel")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 ATLYSS_AdditionalFastTravel { public static class FastTravelActions { public enum WarpResult { Warped, AlreadyHere, MultipleMatches, NoMatches, InDungeon } public enum GotoResult { Warped, MultipleMatches, NoMatches, InDungeon, UnknownPosition } public static void ListWarps() { List availableScenes = SceneData.GetAvailableScenes(); string text = string.Join("\n", availableScenes.Select((SceneData.KnownSceneData x) => " " + x.Name)); if (string.IsNullOrWhiteSpace(text)) { text = "No maps available! Tell the mod developer about this!"; } Utils.ChatMsg("Available warps:\n" + text); } public static void ListGotos() { List availableGotos = SceneData.GetAvailableGotos(); string text = string.Join("\n", availableGotos.Select((SceneData.Goto x) => " " + x.Name)); if (string.IsNullOrWhiteSpace(text)) { text = "No gotos available! Tell the mod developer about this!"; } Utils.ChatMsg("Available goto points for this area:\n" + text); } public static void WarpAndGoto(string sceneName, string locationName) { switch (WarpToScene(sceneName, "")) { case WarpResult.AlreadyHere: Utils.ChatMsg("Already in the given map!"); GoToLocation(locationName); break; case WarpResult.Warped: Main.StoredGoto = locationName; Main.StoredGotoNotBefore = DateTime.Now + TimeSpan.FromSeconds(2.0); break; } } public static WarpResult WarpToScene(string sceneName, string difficulty) { //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) if (SceneData.IsInDungeon()) { Utils.ChatMsg("Cannot use this command while in a dungeon."); return WarpResult.InDungeon; } List availableScenes = SceneData.GetAvailableScenes(); List list = Utils.FindClosestMatch(sceneName, availableScenes, (SceneData.KnownSceneData scene) => scene.Name); if (list.Count == 0) { Utils.ChatMsg("ERROR: No matches found for map " + sceneName + ". Use /warp to list all maps."); return WarpResult.NoMatches; } if (list.Count > 1) { string text = string.Join("\n", list.Select((SceneData.KnownSceneData x) => " " + x.Name)); Utils.ChatMsg("ERROR: Found multiple matches for map " + sceneName + ":\n" + text + "\nTry to use a more specific name or use /warp to list all maps."); return WarpResult.MultipleMatches; } if (SceneData.GetCurrentScene() == list[0].Path) { return WarpResult.AlreadyHere; } ZoneDifficulty val = (ZoneDifficulty)1; if (difficulty.Equals("HARD", StringComparison.InvariantCultureIgnoreCase)) { val = (ZoneDifficulty)2; } else if (difficulty.Equals("EASY", StringComparison.InvariantCultureIgnoreCase)) { val = (ZoneDifficulty)2; } string text2 = list[0].Gotos.FirstOrDefault((SceneData.Goto x) => x.SpawnPoint != null).SpawnPoint ?? "spawnPoint"; Player._mainPlayer._pSound._aSrcGeneral.PlayOneShot(Player._mainPlayer._pSound._portalInteract, 1f); Player._mainPlayer.Cmd_SceneTransport(list[0].Path, text2, val); return WarpResult.Warped; } public static GotoResult GoToLocation(string locationName) { //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) if (SceneData.IsInDungeon()) { Utils.ChatMsg("Cannot use this command while in a dungeon."); return GotoResult.InDungeon; } List availableGotos = SceneData.GetAvailableGotos(); List list = Utils.FindClosestMatch(locationName, availableGotos, (SceneData.Goto go) => go.Name); if (list.Count == 0) { Utils.ChatMsg("ERROR: No matches found for goto " + locationName + ". Use /goto to list all locations."); return GotoResult.NoMatches; } if (list.Count > 1) { string text = string.Join("\n", list.Select((SceneData.Goto x) => " " + x.Name)); Utils.ChatMsg("ERROR: Found multiple matches for goto " + locationName + ":\n" + text + "\nTry to use a more specific name or use /goto to list all locations."); return GotoResult.MultipleMatches; } Vector3? position = list[0].Position; if (!position.HasValue) { Utils.ChatMsg("ERROR: Couldn't retrieve position for " + list[0].Name + ", please report this to the mod developer!"); return GotoResult.UnknownPosition; } Player._mainPlayer._pSound._aSrcGeneral.PlayOneShot(Player._mainPlayer._pSound._warp, 1f); ((Collider)Player._mainPlayer._pMove._playerController).enabled = false; ((Component)Player._mainPlayer).transform.SetPositionAndRotation(position.Value, ((Component)Player._mainPlayer).transform.rotation); CameraFunction._current.CameraReset(); ((Collider)Player._mainPlayer._pMove._playerController).enabled = true; Utils.ChatMsg("Moved to " + list[0].Name + "."); return GotoResult.Warped; } } public static class Logging { public static ManualLogSource PluginLogger = Logger.CreateLogSource("AdditionalFastTravel"); public static void Debug(string text) { PluginLogger.LogDebug((object)text); } public static void Message(string text) { PluginLogger.LogMessage((object)text); } public static void Warn(string text) { PluginLogger.LogWarning((object)text); } public static void Error(string text) { PluginLogger.LogError((object)text); } public static void Fatal(string text) { PluginLogger.LogFatal((object)text); } public static void Info(string text) { PluginLogger.LogInfo((object)text); } } [BepInPlugin("clearwater.atlyss.additionalfasttravel", "AdditionalFastTravel", "1.1.1")] public class Main : BaseUnityPlugin { public static DateTime StoredGotoNotBefore { get; internal set; } = DateTime.Now; public static string StoredGoto { get; internal set; } = ""; private void Awake() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown Logging.Info("-- LOADING AdditionalFastTravel--"); Harmony val = new Harmony("clearwater.atlyss.additionalfasttravel"); val.PatchAll(); } private void LateUpdate() { if (!string.IsNullOrWhiteSpace(StoredGoto) && Object.op_Implicit((Object)(object)Player._mainPlayer) && !Player._mainPlayer._bufferingStatus && DateTime.Now >= StoredGotoNotBefore) { FastTravelActions.GoToLocation(StoredGoto); StoredGoto = ""; } } } public static class SceneData { public struct Goto { public string Name; public string? SpawnPoint; public Vector3? Position; public bool Disabled; public Goto() { SpawnPoint = null; Position = null; Disabled = false; Name = ""; } public static Goto FromSpawnPointDisable(string spawnPoint) { Goto result = new Goto(); result.Name = ""; result.SpawnPoint = spawnPoint; result.Disabled = true; return result; } public static Goto FromSpawnPoint(string name, string spawnPoint) { Goto result = new Goto(); result.Name = name; result.SpawnPoint = spawnPoint; return result; } public static Goto FromPosition(string name, Vector3 position) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) Goto result = new Goto(); result.Name = name; result.Position = position; return result; } } public struct KnownSceneData { public bool IsCustomMap; public string Name; public string Path; public List Gotos; public KnownSceneData() { IsCustomMap = false; Name = ""; Path = ""; Gotos = new List(); } } private static readonly List SceneDatas = new List(17) { new KnownSceneData { Name = "SanctumCatacombs", Path = "Assets/Scenes/map_dungeon00_sanctumCatacombs.unity", Gotos = new List(1) { Goto.FromSpawnPoint("Spawn", "spawnPoint") } }, new KnownSceneData { Name = "CrescentGrove", Path = "Assets/Scenes/map_dungeon01_crescentGrove.unity", Gotos = new List(1) { Goto.FromSpawnPoint("Spawn", "spawnPoint") } }, new KnownSceneData { Name = "Sanctum", Path = "Assets/Scenes/00_zone_forest/_zone00_sanctum.unity", Gotos = new List(8) { Goto.FromSpawnPoint("Spawn", "startPoint"), Goto.FromSpawnPoint("WorldPortal", "worldPortalPoint"), Goto.FromSpawnPoint("OuterSanctum", "gatePoint"), Goto.FromSpawnPoint("Respawn", "respawnPoint"), Goto.FromPosition("Shop", new Vector3(200f, 11f, -110f)), Goto.FromPosition("Enchanting", new Vector3(310f, 11f, -281f)), Goto.FromPosition("Barracks", new Vector3(-160f, 29f, -600f)), Goto.FromPosition("Lake", new Vector3(500f, 43f, 90f)) } }, new KnownSceneData { Name = "SanctumArena", Path = "Assets/Scenes/00_zone_forest/_zone00_sanctumArena.unity", Gotos = new List(1) { Goto.FromSpawnPoint("Spawn", "spawnPoint") } }, new KnownSceneData { Name = "OuterSanctum", Path = "Assets/Scenes/00_zone_forest/_zone00_outerSanctum.unity", Gotos = new List(4) { Goto.FromSpawnPoint("Sanctum", "spawnPoint"), Goto.FromSpawnPoint("ArcwoodPass", "arcwoodSpawn"), Goto.FromSpawnPoint("EffoldTerrace", "terraceSpawn"), Goto.FromSpawnPoint("TuulValley", "tuulValleyPoint") } }, new KnownSceneData { Name = "ArcwoodPass", Path = "Assets/Scenes/00_zone_forest/_zone00_arcwoodPass.unity", Gotos = new List(8) { Goto.FromPosition("Chapel", new Vector3(-54f, 1f, 1702f)), Goto.FromPosition("CatacombsEntrance", new Vector3(298f, 42f, 1819f)), Goto.FromPosition("BadgeMerchants", new Vector3(136f, 81f, 2585f)), Goto.FromSpawnPoint("OuterSanctum", "spawnPoint"), Goto.FromSpawnPoint("Waypoint", "catacombWaypoint"), Goto.FromSpawnPoint("DungeonPortal", "fortSpawn"), Goto.FromSpawnPoint("DungeonEnd", "endDungeonSpawn"), Goto.FromSpawnPoint("CrescentRoad", "keepSpawn") } }, new KnownSceneData { Name = "CatacombsArena", Path = "Assets/Scenes/00_zone_forest/_zone00_catacombsArena.unity", Gotos = new List(1) { Goto.FromSpawnPoint("Spawn", "spawnPoint") } }, new KnownSceneData { Name = "EffoldTerrace", Path = "Assets/Scenes/00_zone_forest/_zone00_effoldTerrace.unity", Gotos = new List(2) { Goto.FromSpawnPoint("Spawn", "startPoint"), Goto.FromPosition("CenterArea", new Vector3(20f, 18f, 45f)) } }, new KnownSceneData { Name = "CrescentRoad", Path = "Assets/Scenes/00_zone_forest/_zone00_crescentRoad.unity", Gotos = new List(3) { Goto.FromSpawnPoint("ArcwoodPass", "spawnPoint"), Goto.FromSpawnPoint("CrescentKeep", "keepSpawn"), Goto.FromSpawnPoint("LuvoraGarden", "gardenPoint") } }, new KnownSceneData { Name = "CrescentKeep", Path = "Assets/Scenes/00_zone_forest/_zone00_crescentKeep.unity", Gotos = new List(7) { Goto.FromPosition("KeepEntrance", new Vector3(-150f, 55f, 235f)), Goto.FromPosition("GroveLobby", new Vector3(-1265f, 225f, 575f)), Goto.FromSpawnPoint("CrescentRoad", "startPoint"), Goto.FromSpawnPoint("Waypoint1", "ckeepWaypoint1"), Goto.FromSpawnPoint("Waypoint2", "ckeepWaypoint2"), Goto.FromSpawnPoint("GateOfTheMoon", "moonGateSpawn"), Goto.FromSpawnPoint("CrescentGrove", "groveEntrance") } }, new KnownSceneData { Name = "LuvoraGarden", Path = "Assets/Scenes/00_zone_forest/_zone00_luvoraGarden.unity", Gotos = new List(1) { Goto.FromSpawnPoint("Spawn", "startPoint") } }, new KnownSceneData { Name = "TuulValley", Path = "Assets/Scenes/00_zone_forest/_zone00_tuulValley.unity", Gotos = new List(2) { Goto.FromSpawnPoint("OuterSanctum", "spawnPoint"), Goto.FromSpawnPoint("TuulEnclave", "enclavePoint") } }, new KnownSceneData { Name = "TuulEnclave", Path = "Assets/Scenes/00_zone_forest/_zone00_tuulEnclave.unity", Gotos = new List(2) { Goto.FromSpawnPoint("TuulValley", "spawnPoint"), Goto.FromSpawnPoint("BularrFortress", "fortSpawn") } }, new KnownSceneData { Name = "BularrFortress", Path = "Assets/Scenes/00_zone_forest/_zone00_bularFortress.unity", Gotos = new List(3) { Goto.FromPosition("AmmagonHut", new Vector3(-92f, 14f, -580f)), Goto.FromSpawnPoint("TuulEnclave", "startPoint"), Goto.FromSpawnPoint("Waypoint", "tuulValleyWaypoint") } }, new KnownSceneData { Name = "GateOfTheMoon", Path = "Assets/Scenes/00_zone_forest/_zone00_gateOfTheMoon.unity", Gotos = new List(5) { Goto.FromPosition("RedwoudEntrance", new Vector3(805f, 5f, 820f)), Goto.FromSpawnPoint("CrescentKeep", "spawnPoint"), Goto.FromSpawnPointDisable("treePoint"), Goto.FromSpawnPointDisable("autumnPoint"), Goto.FromSpawnPoint("WallOfTheStars", "starWallSpawn") } }, new KnownSceneData { Name = "WallOfTheStars", Path = "Assets/Scenes/00_zone_forest/_zone00_wallOfTheStars.unity", Gotos = new List(4) { Goto.FromPosition("Merchant", new Vector3(-100f, 12f, -345f)), Goto.FromSpawnPoint("GateOfTheMoon", "spawnPoint"), Goto.FromSpawnPoint("Waypoint", "wallStarWaypoint"), Goto.FromSpawnPoint("TrialOfTheStars", "trialSpawn") } }, new KnownSceneData { Name = "TrialOfTheStars", Path = "Assets/Scenes/00_zone_forest/_zone00_trialOfTheStars.unity", Gotos = new List(6) { Goto.FromPosition("CheckpointHub", new Vector3(30f, 0f, 188f)), Goto.FromPosition("Checkpoint1", new Vector3(60f, 448f, 185f)), Goto.FromPosition("Checkpoint2", new Vector3(-10f, 878f, 184f)), Goto.FromPosition("Checkpoint3", new Vector3(50f, 1130f, 181f)), Goto.FromPosition("Summit", new Vector3(-9f, 1511f, 289f)), Goto.FromSpawnPoint("WallOfTheStars", "spawnPoint") } } }; public static string LastNetworkSceneLoaded { get; internal set; } = ""; public static string GetCurrentScene() { //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) string result = ""; if (NetworkServer.active) { object obj; if (!Object.op_Implicit((Object)(object)Player._mainPlayer)) { obj = ""; } else { Scene scene = ((Component)Player._mainPlayer).gameObject.scene; obj = ((Scene)(ref scene)).path; } result = (string)obj; } else if (NetworkClient.active) { result = LastNetworkSceneLoaded; } return result; } public static bool IsInDungeon() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Invalid comparison between Unknown and I4 if ((Object)(object)Player._mainPlayer == (Object)null) { return false; } return (int)Player._mainPlayer._playerMapInstance._zoneType == 2; } public static List GetAvailableScenes() { List list = new List(SceneDatas); foreach (KeyValuePair extraMap in GameManager._current._cachedScriptableMapDatas) { string sanitizedMapName = extraMap.Value._mapLockID.Replace(" ", ""); if (!list.Any((KnownSceneData x) => x.Path == extraMap.Value._subScene) && !list.Any((KnownSceneData x) => x.Name == sanitizedMapName)) { list.Add(new KnownSceneData { Name = sanitizedMapName, Path = extraMap.Value._subScene, IsCustomMap = true, Gotos = new List() }); } } return list; } public static List GetAvailableGotos() { List availableScenes = GetAvailableScenes(); return UpdateFromMapSpawnPoints(availableScenes.FirstOrDefault((KnownSceneData x) => x.Path == GetCurrentScene()).Gotos ?? new List()); } private static List UpdateFromMapSpawnPoints(List gotos) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) SpawnPoint[] array = Object.FindObjectsByType((FindObjectsInactive)0, (FindObjectsSortMode)0); List list = new List(gotos); SpawnPoint[] array2 = array; foreach (SpawnPoint val in array2) { Scene scene = ((Component)val).gameObject.scene; if (((Scene)(ref scene)).path != GetCurrentScene()) { continue; } string tag = val._spawnPointTag; if (!string.IsNullOrWhiteSpace(tag)) { int num = list.FindIndex((Goto x) => x.SpawnPoint == tag); if (num != -1) { Goto value = list[num]; value.Position = ((Component)val).transform.position; list[num] = value; } else { string name = char.ToUpper(tag[0]) + tag.Substring(1); list.Add(Goto.FromPosition(name, ((Component)val).transform.position)); } } } return list.Where((Goto x) => !x.Disabled).ToList(); } } public static class Utils { public static List FindClosestMatch(string input, List options, Func keySelector) { Func keySelector2 = keySelector; string input2 = input; foreach (T option in options) { if (keySelector2(option).Equals(input2, StringComparison.InvariantCultureIgnoreCase)) { return new List(1) { option }; } } return options.Where((T x) => keySelector2(x).Contains(input2, StringComparison.InvariantCultureIgnoreCase)).ToList(); } public static void ChatMsg(string message) { ChatBehaviour._current.New_ChatMessage(message); } } internal static class ModInfo { public const string GUID = "clearwater.atlyss.additionalfasttravel"; public const string NAME = "AdditionalFastTravel"; public const string VERSION = "1.1.1"; } } namespace ATLYSS_AdditionalFastTravel.HarmonyPatches { [HarmonyPatch(typeof(NetworkManager), "ClientChangeScene")] internal static class ListenForSceneChanges { private static void Prefix(string newSceneName, SceneOperation sceneOperation) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 if ((int)sceneOperation == 1) { SceneData.LastNetworkSceneLoaded = newSceneName; } } } [HarmonyPatch(typeof(ChatBehaviour), "Cmd_SendChatMessage")] internal static class ListenForWarpCommandPatch { private static void Usage(string msg) { Utils.ChatMsg("Usage: " + msg); } private static bool Prefix(string _message) { string[] array = _message.Split(' ', StringSplitOptions.RemoveEmptyEntries); if (array.Length == 0) { return true; } if (array[0] == "/warp") { if (array.Length == 1) { FastTravelActions.ListWarps(); } if (array.Length == 2) { FastTravelActions.WarpToScene(array[1], ""); } else if (array.Length == 3) { FastTravelActions.WarpAndGoto(array[1], array[2]); } else { Usage("\n /warp [area] - warp to map\n /warp [area] [goto] - warp and goto at the same time"); } return false; } if (array[0] == "/dungeon") { if (array.Length == 1) { FastTravelActions.ListWarps(); } if (array.Length == 3) { FastTravelActions.WarpToScene(array[1], array[2]); } else { Usage("\n /dungeon [area] [difficulty] - warp to map with EASY / NORMAL / HARD difficulty"); } return false; } if (array[0] == "/goto") { if (array.Length == 1) { FastTravelActions.ListGotos(); } if (array.Length == 2) { FastTravelActions.GoToLocation(array[1]); } else { Usage("\n /goto [location] - go to location in current map"); } return false; } return true; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }