using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Xml.Serialization;
using HarmonyLib;
using UnityEngine.SceneManagement;
using UnityModManagerNet;
using Utility;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("SearchLocalCampaignFaster")]
[assembly: AssemblyCompany("Gorzontrok")]
[assembly: AssemblyProduct("SearchLocalCampaignFaster")]
[assembly: AssemblyCopyright("Copyright © Gorzontrok 2024")]
[assembly: Guid("63355e42-c4af-4a8a-be88-af5826ba7116")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace SearchLocalCampaignFaster;
internal static class Main
{
public static ModEntry mod;
public static bool enabled;
public static Settings settings;
private static bool Load(ModEntry modEntry)
{
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Expected O, but got Unknown
modEntry.OnGUI = OnGUI;
modEntry.OnSaveGUI = OnSaveGUI;
modEntry.OnToggle = OnToggle;
mod = modEntry;
settings = ModSettings.Load<Settings>(modEntry);
try
{
Harmony val = new Harmony(modEntry.Info.Id);
Assembly executingAssembly = Assembly.GetExecutingAssembly();
val.PatchAll(executingAssembly);
}
catch (Exception ex)
{
mod.Logger.Log("Failed to Patch Harmony\n" + ex.ToString());
}
return true;
}
private static bool OnToggle(ModEntry modEntry, bool value)
{
enabled = value;
return true;
}
private static void OnGUI(ModEntry modEntry)
{
Extensions.Draw<Settings>(settings, modEntry);
}
private static void OnSaveGUI(ModEntry modEntry)
{
((ModSettings)settings).Save(modEntry);
}
}
public class Settings : ModSettings, IDrawable
{
[Draw(/*Could not decode attribute arguments.*/)]
public bool searchOnlyInTopFolder = true;
public int maxSearchDepth = 1000;
public void OnChange()
{
}
public override void Save(ModEntry modEntry)
{
ModSettings.Save<Settings>(this, modEntry);
}
}
[HarmonyPatch(typeof(BrowseCampaigns))]
public static class BrowseCampaignsPatch
{
public const byte HEADER_SEPARATOR = 31;
public const string LEVEL_TOP_FOLDER = "Levels/";
public static int MaxSearchDepth => Main.settings.maxSearchDepth;
public static bool SearchOnlyInTopFolder => Main.settings.searchOnlyInTopFolder;
[HarmonyPrefix]
[HarmonyPatch("LoadOfflineCampaigns")]
public static bool LoadOfflineCampaigns()
{
if (!Main.enabled)
{
return true;
}
try
{
FilterFiles(".bfg", out var files, out var headers);
FilterFiles(".bfd", out var files2, out var headers2);
FilterFiles(".bfc", out var files3, out var headers3);
SingletonMono<NewCustomCampaignMenu>.Instance.ReceiveUpdatedEntries(headers3, headers, headers2, files3, files, files2);
return false;
}
catch (Exception ex)
{
Main.mod.Logger.LogException(ex);
}
return true;
}
public static void FilterFiles(string fileExtension, out string[] files, out List<CampaignHeader> headers)
{
List<string> list = new List<string>(Directory.GetFiles("Levels/", "*" + fileExtension, (!SearchOnlyInTopFolder) ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly));
Dictionary<string, CampaignHeader> dictionary = new Dictionary<string, CampaignHeader>();
for (int i = 0; i < list.Count; i++)
{
try
{
string text = list[i].Remove(0, "Levels/".Length);
text = text.Remove(text.Length - fileExtension.Length);
CampaignHeader campaignHeader = GetCampaignHeader("Levels/", text + fileExtension);
if (campaignHeader != null && !string.IsNullOrEmpty(campaignHeader.name))
{
dictionary.Add(text, campaignHeader);
}
}
catch (Exception ex)
{
Main.mod.Logger.LogException("Can't load header of file '" + Path.GetFileName(list[i]) + "'", ex);
}
}
Dictionary<string, CampaignHeader> dictionary2 = dictionary.OrderBy((KeyValuePair<string, CampaignHeader> kvp) => kvp.Key).ToDictionary((KeyValuePair<string, CampaignHeader> x) => x.Key, (KeyValuePair<string, CampaignHeader> x) => x.Value);
files = dictionary2.Keys.ToArray();
headers = dictionary2.Values.ToList();
}
public static CampaignHeader GetCampaignHeader(string directory, string file)
{
return GetCampaignHeader(Path.Combine(directory, file));
}
public static CampaignHeader GetCampaignHeader(string path)
{
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: Expected O, but got Unknown
CampaignHeader val = null;
FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read);
List<byte> list = new List<byte>();
for (int i = 0; i < MaxSearchDepth; i++)
{
int num = fileStream.ReadByte();
if (num == 31)
{
break;
}
list.Add((byte)num);
}
if (list.Count == 0 || list.Count >= MaxSearchDepth)
{
throw new Exception("Unit separator character not founded");
}
string @string = Encoding.Default.GetString(list.ToArray());
XmlSerializer xmlSerializer = new XmlSerializer(typeof(CampaignHeader));
using (StringReader textReader = new StringReader(@string))
{
val = (CampaignHeader)xmlSerializer.Deserialize(textReader);
}
val.isPublished = !string.IsNullOrEmpty(val.md5);
return val;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(NewCustomCampaignMenu), "LaunchOfflineCampaign")]
private static bool LaunchOfflineCustomCampaign(NewCustomCampaignMenu __instance, CampaignHeader header, string fileName)
{
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_00d9: 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_0065: Unknown result type (might be due to invalid IL or missing references)
LevelSelectionController.ResetLevelAndGameModeToDefault();
PlayerProgress.Instance.lastOnlineLevelProgress = 0;
GameState.Instance.sceneToLoad = LevelSelectionController.JoinScene;
__instance.highlightState = (HighlightState)4;
GameModeController.publishRun = false;
if (header != null)
{
GameModeController.GameMode = header.gameMode;
}
else
{
GameModeController.GameMode = (GameMode)0;
}
LevelSelectionController.campaignToLoad = fileName;
LevelSelectionController.loadCustomCampaign = true;
LevelSelectionController.loadPublishedCampaign = header.isPublished;
LevelSelectionController.CurrentLevelNum = 0;
GameState.Instance.loadMode = (MapLoadMode)0;
Traverse.Create(typeof(StatisticsController)).Method("ResetScore", new object[0]).GetValue();
LevelEditorGUI.levelEditorActive = false;
try
{
if (LevelSelectionController.loadPublishedCampaign)
{
LevelSelectionController.currentCampaign = FileIO.LoadPublishedCampaignFromDisk(fileName, ".bfg");
}
else
{
LevelSelectionController.currentCampaign = FileIO.LoadCampaignFromDisk(fileName);
}
}
catch (Exception ex)
{
__instance.mapDetails.text = "failed to load campaign : " + ex.Message;
__instance.highlightState = (HighlightState)1;
Main.mod.Logger.Log(ex.ToString());
return false;
}
Traverse.Create((object)__instance).Method("ClearEntries", new object[0]).GetValue();
SceneLoader.LoadScene(LevelSelectionController.JoinScene, (LoadSceneMode)0);
return false;
}
}