using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Security; using System.Security.Permissions; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Events.Player; using HarmonyLib; using Mod.CustomCampaigns.Extensions; using Mod.CustomCampaigns.Scripts; using Steamworks; using UnityEngine; using UnityEngine.Networking; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("CustomCampaigns")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("CustomCampaigns")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("3dd30da1-6c83-4cc3-8922-ea8b1847fd6d")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace Mod.CustomCampaigns { [BepInPlugin("Distance.CustomCampaigns", "Custom Campaigns", "2.0.1")] public sealed class Mod : BaseUnityPlugin { private const string modGUID = "Distance.CustomCampaigns"; private const string modName = "Custom Campaigns"; private const string modVersion = "2.0.1"; private Dictionary collectionIDs = new Dictionary(); private string campaignTitle = string.Empty; private string campaignDesc = string.Empty; private static readonly Harmony harmony = new Harmony("Distance.CustomCampaigns"); public static ManualLogSource Log = new ManualLogSource("Custom Campaigns"); public static Mod Instance; private void Awake() { if ((Object)(object)Instance == (Object)null) { Instance = this; } Log = Logger.CreateLogSource("Distance.CustomCampaigns"); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Thanks for using Custom Campaigns!"); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Loading..."); harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Loaded!"); } private void OnConfigChanged(object sender, EventArgs e) { SettingChangedEventArgs e2 = (SettingChangedEventArgs)(object)((e is SettingChangedEventArgs) ? e : null); if (e2 != null) { } } public bool ValidateUrl(string url, out string errorMessage) { if (url.StartsWith("https://steamcommunity.com/sharedfiles/filedetails/?id=")) { Regex regex = new Regex("^(https:\\/\\/steamcommunity\\.com\\/sharedfiles\\/filedetails\\/\\?id=)\\d*$"); if (regex.IsMatch(url)) { errorMessage = "THERE WAS NO ERROR YIPPEE!!!"; return true; } errorMessage = "THIS STEAM LINK IS NOT A WORKSHOP ITEM"; return false; } if (url.StartsWith("https:")) { errorMessage = "THIS LINK IS NOT A VALID LINK"; return false; } if (url == "") { errorMessage = "YOU DIDN'T SUBMIT ANYTHING"; return false; } errorMessage = "CANNOT PARSE. PLEASE TRY AGAIN"; return false; } public IEnumerator ParseCollection(string url) { MenuPanelManager MPM = G.Sys.MenuPanelManager_; SteamworksUGC UGC = G.Sys.SteamworksManager_.UGC_; UGC.SetupSteamProgressText("Downloading Campaign..."); UGC.progressBar_.value = 0f; UnityWebRequest request = new UnityWebRequest(url); request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); request.method = "GET"; yield return request.Send(); if (request.isError) { Log.LogError((object)"Failed to request the link!"); string error = request.error; if (error == null) { error = "Unknown Error!"; } Log.LogError((object)error); MPM.ShowError("Failed to connect to the web page", "Error", (OnButtonClicked)null, (Pivot)4); MPM.MenuInputEnabled_ = true; UGC.DestroySteamProgressText(); yield break; } UGC.ProgressTextLabel_.text = "Parsing the web page..."; UGC.progressBar_.value = 0.5f; collectionIDs = new Dictionary(); campaignTitle = string.Empty; campaignDesc = string.Empty; try { string requestHTML = request.downloadHandler.text; if (!requestHTML.Contains("Collections")) { MPM.ShowError("This Workshop link is not a Distance Workshop Collection link! \nPlease submit a link that is a Distance Workshop Collection", "Error", (OnButtonClicked)null, (Pivot)4); MPM.MenuInputEnabled_ = true; UGC.DestroySteamProgressText(); yield break; } Regex MatchAllIDs = new Regex("(?<={\"id\":\")\\d*"); if (MatchAllIDs.IsMatch(requestHTML)) { MatchCollection matchIDs = MatchAllIDs.Matches(requestHTML); WorkshopLevelInfo wInfo = default(WorkshopLevelInfo); foreach (Match mID in matchIDs) { Log.LogInfo((object)("ID Found: " + mID.Value)); bool levelInstalled = false; try { levelInstalled = UGC.storedPublishedFileIDs_.TryGetWorkshopLevelInfo((ulong)Convert.ToInt64(mID.Value), ref wInfo); if (!string.IsNullOrEmpty(wInfo.title_)) { Log.LogInfo((object)("Level Already Installed: " + wInfo.title_)); } } catch (Exception) { Log.LogWarning((object)"Level is not already installed: Will attempt to download"); } collectionIDs.Add((ulong)Convert.ToInt64(mID.Value), levelInstalled); wInfo = null; } } else { Log.LogWarning((object)"Failed to find any level IDs in the collection"); } Regex matchTitle = new Regex("(?<=
).*(?=
)"); if (matchTitle.IsMatch(requestHTML)) { Match mTitle = matchTitle.Match(requestHTML); campaignTitle = mTitle.Value; } Regex matchDescription = new Regex("(?<=
).*(?=
)"); if (matchDescription.IsMatch(requestHTML)) { Match mDesc = matchDescription.Match(requestHTML); string betterDesc = mDesc.Value.Replace("
", "\n"); campaignDesc = betterDesc; } else { Log.LogWarning((object)"Failed to find the description in the collection"); } if (collectionIDs.Count == 0) { MPM.ShowError("This collection has no levels!", "Error", (OnButtonClicked)null, (Pivot)4); MPM.MenuInputEnabled_ = true; UGC.DestroySteamProgressText(); yield break; } } catch (Exception ex2) { Exception e = ex2; Log.LogError((object)"Encountered an error when parsing the link!"); string error2 = e.ToString(); if (error2 == null) { error2 = "Unknown Error!"; } Log.LogError((object)error2); MPM.ShowError("Failed to parse the web page", "Error", (OnButtonClicked)null, (Pivot)4); MPM.MenuInputEnabled_ = true; UGC.DestroySteamProgressText(); yield break; } List pFileIds = new List(); foreach (KeyValuePair kvp in collectionIDs) { if (!kvp.Value) { Log.LogInfo((object)("Level ID to Download: " + kvp.Key)); pFileIds.Add(new PublishedFileId_t(kvp.Key)); } } if (pFileIds.Count > 0) { Log.LogInfo((object)"Beginning download process..."); UGC.StartWorkshopLevelsUpdate((WorkshopUpdateType)1, pFileIds.ToArray(), new OnPanelPop(ConvertLevelsToCampaign), (OnPanelPop)delegate { MPM.ShowError("Failed to download workshop levels from the collection", "Error", (OnButtonClicked)null, (Pivot)4); }); } else { ConvertLevelsToCampaign(); } MPM.MenuInputEnabled_ = true; UGC.DestroySteamProgressText(); } private void ConvertLevelsToCampaign() { //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Expected O, but got Unknown //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Expected O, but got Unknown MenuPanelManager menuPanelManager_ = G.Sys.MenuPanelManager_; SteamworksUGC uGC_ = G.Sys.SteamworksManager_.UGC_; List list = new List(); Log.LogInfo((object)"Preparing to create campaign playlist..."); WorkshopLevelInfo val = default(WorkshopLevelInfo); foreach (KeyValuePair collectionID in collectionIDs) { uGC_.storedPublishedFileIDs_.TryGetWorkshopLevelInfo(collectionID.Key, ref val); Log.LogInfo((object)("Level Title: " + val.title_ + " Path: " + Resource.GetAbsoluteLevelPath(val.relativePath_))); list.Add(new LevelNameAndPathPair(val.title_, Resource.GetAbsoluteLevelPath(val.relativePath_))); } Log.LogInfo((object)"Creating Playlist..."); LevelSet val2 = new LevelSet(); val2.resourcesLevelNameAndPathPairsInSet_ = list; LevelPlaylist val3 = LevelPlaylist.Create(val2, campaignTitle, (GameModeID)15); val3.Awake(); val3.Save(); menuPanelManager_.ShowError("Return to the main menu to refresh the campaign list", "Campaign Installed", (OnButtonClicked)null, (Pivot)4); } } } namespace Mod.CustomCampaigns.Scripts { public class CreateCampaignLogic : MonoBehaviour { private LevelGridGrid grid_; private void Awake() { grid_ = ((Component)this).GetComponentInParent(); if (!Object.op_Implicit((Object)(object)grid_)) { Mod.Log.LogError((object)"LevelGridGrid component not found"); } Mod.Log.LogInfo((object)"Created Component!"); } private void Update() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Invalid comparison between Unknown and I4 //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Expected O, but got Unknown if (grid_.isGridPushed_ && (int)((LevelSelectMenuAbstract)grid_.levelGridMenu_).displayType_ == 0 && !grid_.playlist_.IsResourcesPlaylist() && G.Sys.InputManager_.GetKeyUp((InputAction)48, -2)) { LevelSet set = new LevelSet(); set.resourcesLevelNameAndPathPairsInSet_ = grid_.playlist_.GetLevelSet(); grid_.levelGridMenu_.menuPanelManager_.ShowOkCancel("Create a campaign out of the [c][9480e7]" + grid_.playlist_.playlistName_ + "[-][c] playlist?", "Create Campaign", (OnButtonClicked)delegate { LevelPlaylist val = LevelPlaylist.Create(set, grid_.playlist_.playlistName_, (GameModeID)15); val.Awake(); val.Save(); ((UIExButtonContainer)grid_.levelGridMenu_.buttonList_).Remove((Entry)(object)grid_.levelGridMenu_.selectedEntry_); ((UIExButtonContainer)grid_.levelGridMenu_.buttonList_).SortAndUpdateVisibleButtons(); grid_.levelGridMenu_.SelectEntry(grid_.levelGridMenu_.ScrollableEntries_[0], true); }, (OnButtonClicked)null, (Pivot)4); } } } public class LevelPlaylistCompoundData : MonoBehaviour { public LevelPlaylist Playlist { get; internal set; } public PlaylistEntry PlaylistEntry { get; internal set; } public string FilePath { get; internal set; } public GameModeID CustomGameModeID { get; internal set; } public LevelGroupFlags LevelGroupFlags { get; internal set; } public Type PlaylistType { get { //IL_000d: Unknown result type (might be due to invalid IL or missing references) PlaylistEntry playlistEntry = PlaylistEntry; return (Type)((playlistEntry == null) ? (-1) : ((int)playlistEntry.type_)); } } } } namespace Mod.CustomCampaigns.Patches { [HarmonyPatch(typeof(AdventureMode), "OnEventCarInstantiate")] internal static class AdventureMode__OnEventCarInstantiate { [HarmonyPostfix] internal static void RemoveResetHint(AdventureMode __instance, Data data) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) LocalPlayerControlledCar component = data.car.GetComponent(); if (BehaviourEx.ExistsAndIsEnabled((Behaviour)(object)component) && ((GameMode)__instance).gameMan_.IsCampaignModeNormal_ && __instance is NexusMode && ((GameMode)__instance).gameMan_.LevelName_ != "Mobilization" && ((GameMode)__instance).gameMan_.LevelName_ != "Resonance" && ((GameMode)__instance).gameMan_.LevelName_ != "Deterrance" && ((GameMode)__instance).gameMan_.LevelName_ != "Terminus" && ((GameMode)__instance).gameMan_.LevelName_ != "Collapse") { component.showBackToResetWarning_ = false; } } } [HarmonyPatch(typeof(LevelGridGrid), "PushGrid")] internal static class LevelGridGrid__PushGrid { [HarmonyTranspiler] internal static IEnumerable AddButton(IEnumerable instructions) { //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Expected O, but got Unknown //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Expected O, but got Unknown Mod.Log.LogInfo((object)"Transpiling..."); List list = new List(instructions); for (int i = 3; i < list.Count; i++) { if (list[i - 2].opcode == OpCodes.Callvirt && ((MethodInfo)list[i - 2].operand).Name == "Push" && list[i].opcode == OpCodes.Call && ((MethodInfo)list[i].operand).Name == "GridPushChange") { Mod.Log.LogInfo((object)$"call MenuPanel.Push @ {i - 2}"); List