using System;
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 BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Mod.CustomCampaigns.Extensions;
using Mod.CustomCampaigns.Scripts;
using UnityEngine;
[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", "1.0.0")]
public sealed class Mod : BaseUnityPlugin
{
private const string modGUID = "Distance.CustomCampaigns";
private const string modName = "Custom Campaigns";
private const string modVersion = "1.0.0";
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 val = (SettingChangedEventArgs)(object)((e is SettingChangedEventArgs) ? e : null);
if (val != null)
{
}
}
}
}
namespace Mod.CustomCampaigns.Scripts
{
public class CreateCampaignLogic : MonoBehaviour
{
private LevelGridGrid grid_;
private void Awake()
{
grid_ = ((Component)this).GetComponentInParent<LevelGridGrid>();
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(LevelGridGrid), "PushGrid")]
internal static class LevelGridGrid__PushGrid
{
[HarmonyTranspiler]
internal static IEnumerable<CodeInstruction> AddButton(IEnumerable<CodeInstruction> 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<CodeInstruction> list = new List<CodeInstruction>(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<Label> collection = new List<Label>(list[i - 3].labels);
list[i - 3].labels.Clear();
list.InsertRange(i - 3, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[2]
{
new CodeInstruction(OpCodes.Ldarg_0, (object)null),
new CodeInstruction(OpCodes.Call, (object)typeof(LevelGridGrid__PushGrid).GetMethod("AddCampaignOptionButton"))
});
list[i - 3].labels.AddRange(collection);
break;
}
}
return list.AsEnumerable();
}
public static void AddCampaignOptionButton(LevelGridGrid instance)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Invalid comparison between Unknown and I4
if ((int)((LevelSelectMenuAbstract)instance.levelGridMenu_).displayType_ == 0)
{
ComponentEx.GetOrAddComponent<CreateCampaignLogic>((Component)(object)instance);
MenuPanel component = instance.gridPanel_.GetComponent<MenuPanel>();
if (Object.op_Implicit((Object)(object)component) && !((LevelSelectMenuAbstract)instance.levelGridMenu_).IsSimpleMenu_ && !instance.playlist_.IsResourcesPlaylist())
{
component.SetBottomLeftButton((InputAction)48, "CREATE\nCAMPAIGN");
}
}
}
}
[HarmonyPatch(typeof(LevelGridMenu), "CreateEntries")]
internal static class LevelGridMenu__CreateEntries
{
private class AddCampaignEntry : PlaylistEntry
{
public AddCampaignEntry(LevelGridMenu menu, LevelPlaylist playlist)
: base(menu, "Add Campaign", playlist, (Type)0, false, (UnlockStyle)7, true)
{
}
public override void OnClick()
{
//IL_0008: 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_0024: Expected O, but got Unknown
//IL_0024: Expected O, but got Unknown
InputPromptPanel.Create(new OnSubmit(SearchCollectionOnSteam), new OnPop(InputPop), "Enter Campaign Link:", (string)null);
}
private bool SearchCollectionOnSteam(out string errorMessage, string input)
{
errorMessage = "This feature is not implemented yet. Sorry!";
return false;
}
private void InputPop()
{
}
}
[HarmonyPostfix]
internal static void CustomPlaylist(LevelGridMenu __instance)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Invalid comparison between Unknown and I4
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Invalid comparison between Unknown and I4
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: Expected O, but got Unknown
bool flag = (int)((LevelSelectMenuAbstract)__instance).displayType_ == 3;
bool flag2 = (int)__instance.modeID_ == 1;
if (!flag)
{
return;
}
foreach (LevelPlaylist localPlaylist in GetLocalPlaylists())
{
__instance.CreateAndAddEntry(localPlaylist, (Type)4, true, (UnlockStyle)7, "");
}
string[] legacyFileNames_ = G.Sys.LevelSets_.LegacyFileNames_;
List<LevelNameAndPathPair> allLevelNameAndPathPairs = G.Sys.LevelSets_.GetSet((GameModeID)1).GetAllLevelNameAndPathPairs();
LevelSet val = new LevelSet();
for (int i = 0; i < allLevelNameAndPathPairs.Count; i++)
{
string fileNameWithoutExtension = Resource.GetFileNameWithoutExtension(allLevelNameAndPathPairs[i].levelPath_);
if (legacyFileNames_.Contains(fileNameWithoutExtension))
{
val.AddLevel(allLevelNameAndPathPairs[i].levelName_, Resource.GetAbsoluteOfficialLevelPath(fileNameWithoutExtension), (LevelType)2, (string)null);
break;
}
}
if (val.ResourcesLevelsCount_ > 0)
{
__instance.AddEntry((PlaylistEntry)(object)new AddCampaignEntry(__instance, LevelPlaylist.Create(val, "Add Campaign", (GameModeID)1)), "");
}
((UIExButtonContainer)__instance.buttonList_).SortAndUpdateVisibleButtons();
}
private static List<LevelPlaylist> GetLocalPlaylists()
{
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
//IL_00b2: Invalid comparison between Unknown and I4
//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
//IL_00bd: Invalid comparison between Unknown and I4
List<LevelPlaylist> list = new List<LevelPlaylist>();
if (DirectoryEx.Exists(Resource.PersonalLevelPlaylistsDirPath_))
{
List<string> filePathsInDirWithPattern = Resource.GetFilePathsInDirWithPattern(Resource.PersonalLevelPlaylistsDirPath_, "*.xml", (List<string>)null);
filePathsInDirWithPattern.RemoveAll((string s) => !Resource.FileExist(s));
foreach (string item in filePathsInDirWithPattern)
{
LevelPlaylist val = LevelGridMenu.LoadPlaylist(item);
if (!Object.op_Implicit((Object)(object)val))
{
Mod.Log.LogError((object)("Failed to load: " + item));
}
if (val.Count_ != 0 && ((int)val.FirstModeID_ == 14 || (int)val.FirstModeID_ == 15))
{
list.Add(val);
}
}
}
return list;
}
}
[HarmonyPatch(typeof(LevelGridMenu), "SetDisplayedInfoForSelectedPlaylist")]
internal static class SetDisplayedInfoForSelectedPlaylist
{
[HarmonyPostfix]
internal static void DisableGridDescriptionForAddCampaign(LevelGridMenu __instance)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Invalid comparison between Unknown and I4
if ((int)((LevelSelectMenuAbstract)__instance).displayType_ == 3 && ((Entry)__instance.displayedEntry_).labelText_ != "Adventure" && ((Entry)__instance.displayedEntry_).labelText_ != "Lost To Echoes" && ((Entry)__instance.displayedEntry_).labelText_ != "Nexus" && ((Entry)__instance.displayedEntry_).labelText_ != "The Other Side")
{
__instance.gridDescription_.text = string.Empty;
if (((Component)__instance.gridDescription_).gameObject.activeSelf)
{
((Component)__instance.gridDescription_).gameObject.SetActive(false);
}
}
}
}
[HarmonyPatch(typeof(LevelPlaylist), "Load")]
internal static class LevelPlaylist__Load
{
[HarmonyPostfix]
internal static void Postfix(ref GameObject __result, string levelPlaylistPath)
{
LevelPlaylistCompoundData levelPlaylistCompoundData = __result.gameObject.AddComponent<LevelPlaylistCompoundData>();
levelPlaylistCompoundData.FilePath = levelPlaylistPath;
levelPlaylistCompoundData.Playlist = __result.GetComponent<LevelPlaylist>();
}
}
internal static class LevelPlaylist__Create
{
[HarmonyPatch(typeof(LevelPlaylist), "Create", new Type[] { typeof(bool) })]
internal static class LevelPlaylist__Create_overload0
{
[HarmonyPostfix]
internal static void Postfix(ref LevelPlaylist __result)
{
LevelPlaylistCompoundData levelPlaylistCompoundData = ((Component)__result).gameObject.AddComponent<LevelPlaylistCompoundData>();
levelPlaylistCompoundData.Playlist = __result;
}
}
[HarmonyPatch(typeof(LevelPlaylist), "Create", new Type[]
{
typeof(LevelSet),
typeof(string)
})]
internal static class LevelPlaylist__Create_overload1
{
[HarmonyPostfix]
internal static void Postfix(ref LevelPlaylist __result)
{
LevelPlaylistCompoundData orAddComponent = GameObjectEx.GetOrAddComponent<LevelPlaylistCompoundData>(((Component)__result).gameObject);
orAddComponent.Playlist = __result;
}
}
[HarmonyPatch(typeof(LevelPlaylist), "Create", new Type[]
{
typeof(LevelSet),
typeof(string),
typeof(GameModeID)
})]
internal static class LevelPlaylist__Create_overload2
{
[HarmonyPostfix]
internal static void Postfix(ref LevelPlaylist __result, GameModeID customGameModeID)
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
LevelPlaylistCompoundData orAddComponent = GameObjectEx.GetOrAddComponent<LevelPlaylistCompoundData>(((Component)__result).gameObject);
orAddComponent.Playlist = __result;
orAddComponent.CustomGameModeID = customGameModeID;
}
}
[HarmonyPatch(typeof(LevelPlaylist), "Create", new Type[]
{
typeof(LevelSet),
typeof(string),
typeof(LevelGroupFlags)
})]
internal static class LevelPlaylist__Create_overload3
{
[HarmonyPostfix]
internal static void Postfix(ref LevelPlaylist __result, LevelGroupFlags flags)
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
LevelPlaylistCompoundData orAddComponent = GameObjectEx.GetOrAddComponent<LevelPlaylistCompoundData>(((Component)__result).gameObject);
orAddComponent.Playlist = __result;
orAddComponent.LevelGroupFlags = flags;
}
}
}
}
namespace Mod.CustomCampaigns.Extensions
{
public static class LevelPlaylistExtensions
{
public static bool IsResourcesPlaylist(this LevelPlaylist playlist)
{
LevelPlaylistCompoundData component = ((Component)playlist).GetComponent<LevelPlaylistCompoundData>();
if (!Object.op_Implicit((Object)(object)component) || component.FilePath == null)
{
return true;
}
string text = new FileInfo(component.FilePath).FullName.UniformPathSeparators();
string value = new DirectoryInfo(Path.Combine(Application.dataPath, "Resources")).FullName.UniformPathSeparatorsTrimmed() + "/";
return text.StartsWith(value, StringComparison.InvariantCultureIgnoreCase);
}
public static string ResourcePath(this LevelPlaylist playlist)
{
LevelPlaylistCompoundData component = ((Component)playlist).GetComponent<LevelPlaylistCompoundData>();
if (!Object.op_Implicit((Object)(object)component) || component.FilePath == null)
{
return string.Empty;
}
string text = new FileInfo(component.FilePath).FullName.UniformPathSeparators();
return new DirectoryInfo(Path.Combine(Application.dataPath, "Resources")).FullName.UniformPathSeparatorsTrimmed() + "/";
}
}
public static class StringExtensions
{
public static string UniformPathSeparators(this string source)
{
return source.Replace(Path.DirectorySeparatorChar, '/').Replace(Path.AltDirectorySeparatorChar, '/').Replace('\\', '/');
}
public static string UniformPathSeparatorsTrimmed(this string source)
{
return source.UniformPathSeparators().TrimEnd(new char[1] { '/' });
}
}
}