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.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("BlueprintSort")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1")]
[assembly: AssemblyProduct("BlueprintSort")]
[assembly: AssemblyTitle("BlueprintSort")]
[assembly: AssemblyVersion("1.0.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[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 BlueprintSort
{
public enum SortMode
{
Name,
Updated,
Created
}
[BepInPlugin("com.quantumcreation.dsp.blueprintsort", "Blueprint Sort", "1.0.1")]
[BepInProcess("DSPGAME.exe")]
public class Plugin : BaseUnityPlugin
{
public const string Guid = "com.quantumcreation.dsp.blueprintsort";
public const string Version = "1.0.1";
internal static ManualLogSource Log;
internal static ConfigEntry<SortMode> Mode;
private void Awake()
{
Log = ((BaseUnityPlugin)this).Logger;
Mode = ((BaseUnityPlugin)this).Config.Bind<SortMode>("General", "SortOrder", SortMode.Updated, "Order of the Blueprint Library. Name = the game's alphabetical order, Updated = most recently saved first, Created = most recently created first. The Sort button in the library cycles through these.");
Harmony.CreateAndPatchAll(typeof(BrowserPatch), "com.quantumcreation.dsp.blueprintsort");
}
}
[HarmonyPatch(typeof(UIBlueprintBrowser))]
internal static class BrowserPatch
{
private static Button sortButton;
private static Text sortLabel;
[HarmonyTranspiler]
[HarmonyPatch("SetCurrentDirectory")]
private static IEnumerable<CodeInstruction> SortListings(IEnumerable<CodeInstruction> instructions)
{
Type[] array = new Type[3]
{
typeof(string),
typeof(string),
typeof(SearchOption)
};
MethodInfo getDirs = AccessTools.Method(typeof(Directory), "GetDirectories", array, (Type[])null);
MethodInfo getFiles = AccessTools.Method(typeof(Directory), "GetFiles", array, (Type[])null);
int replaced = 0;
foreach (CodeInstruction instruction in instructions)
{
if (CodeInstructionExtensions.Calls(instruction, getDirs))
{
instruction.operand = AccessTools.Method(typeof(BrowserPatch), "GetDirectories", (Type[])null, (Type[])null);
replaced++;
}
else if (CodeInstructionExtensions.Calls(instruction, getFiles))
{
instruction.operand = AccessTools.Method(typeof(BrowserPatch), "GetFiles", (Type[])null, (Type[])null);
replaced++;
}
yield return instruction;
}
if (replaced != 2)
{
Plugin.Log.LogWarning((object)$"Expected 2 directory listings in SetCurrentDirectory, patched {replaced}");
}
}
public static string[] GetDirectories(string path, string pattern, SearchOption option)
{
return Sort(Directory.GetDirectories(path, pattern, option), isDir: true);
}
public static string[] GetFiles(string path, string pattern, SearchOption option)
{
return Sort(Directory.GetFiles(path, pattern, option), isDir: false);
}
private static string[] Sort(string[] paths, bool isDir)
{
SortMode mode = Plugin.Mode.Value;
if (mode == SortMode.Name || paths.Length < 2)
{
return paths;
}
try
{
return paths.OrderByDescending((string p) => Stamp(p, isDir, mode)).ThenBy<string, string>((string p) => p, StringComparer.OrdinalIgnoreCase).ToArray();
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("Sorting failed, keeping name order: " + ex.Message));
return paths;
}
}
private static DateTime Stamp(string path, bool isDir, SortMode mode)
{
if (!isDir)
{
return Time(new FileInfo(path), mode);
}
DirectoryInfo directoryInfo = new DirectoryInfo(path);
DateTime dateTime = Time(directoryInfo, mode);
FileInfo[] files = directoryInfo.GetFiles("*.txt", SearchOption.AllDirectories);
for (int i = 0; i < files.Length; i++)
{
DateTime dateTime2 = Time(files[i], mode);
if (dateTime2 > dateTime)
{
dateTime = dateTime2;
}
}
return dateTime;
}
private static DateTime Time(FileSystemInfo info, SortMode mode)
{
if (mode != SortMode.Created)
{
return info.LastWriteTimeUtc;
}
return info.CreationTimeUtc;
}
[HarmonyPostfix]
[HarmonyPriority(200)]
[HarmonyPatch("_OnCreate")]
private static void AddSortButton(UIBlueprintBrowser __instance)
{
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_00b3: Expected O, but got Unknown
//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
//IL_0105: Unknown result type (might be due to invalid IL or missing references)
//IL_0111: Unknown result type (might be due to invalid IL or missing references)
//IL_0116: Unknown result type (might be due to invalid IL or missing references)
//IL_0164: Unknown result type (might be due to invalid IL or missing references)
//IL_016e: Expected O, but got Unknown
//IL_017f: Unknown result type (might be due to invalid IL or missing references)
//IL_0189: Expected O, but got Unknown
Button val = ((IEnumerable<Button>)((Component)__instance).GetComponentsInChildren<Button>(true)).FirstOrDefault((Func<Button, bool>)IsShowInExplorer);
if ((Object)(object)val == (Object)null)
{
Plugin.Log.LogWarning((object)"Show in Explorer button not found; sort only via config");
return;
}
GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, ((Component)val).transform.parent, false);
((Object)val2).name = "blueprint-sort-button";
Localizer[] componentsInChildren = val2.GetComponentsInChildren<Localizer>(true);
for (int i = 0; i < componentsInChildren.Length; i++)
{
Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
}
RectTransform val3 = (RectTransform)val2.transform;
RectTransform val4 = (RectTransform)((Component)val).transform;
Rect rect = val4.rect;
float num = ((Rect)(ref rect)).width + 6f;
val3.anchoredPosition = val4.anchoredPosition - new Vector2(num, 0f);
if (!((Transform)val4).IsChildOf((Transform)(object)__instance.addrTrans))
{
RectTransform addrTrans = __instance.addrTrans;
addrTrans.offsetMax -= new Vector2(num, 0f);
}
UIButton component = val2.GetComponent<UIButton>();
if ((Object)(object)component != (Object)null)
{
component.tips.tipTitle = "Blueprint sort order";
component.tips.tipText = "Click to switch between name, last updated and date created.";
}
sortButton = val2.GetComponent<Button>();
sortButton.onClick = new ButtonClickedEvent();
((UnityEvent)sortButton.onClick).AddListener((UnityAction)delegate
{
Cycle(__instance);
});
sortLabel = val2.GetComponentInChildren<Text>(true);
UpdateLabel();
}
private static bool IsShowInExplorer(Button b)
{
for (int i = 0; i < ((UnityEventBase)b.onClick).GetPersistentEventCount(); i++)
{
if (((UnityEventBase)b.onClick).GetPersistentMethodName(i) == "ShowInExplorer")
{
return true;
}
}
return false;
}
[HarmonyPostfix]
[HarmonyPatch("_OnOpen")]
private static void OnOpen()
{
UpdateLabel();
}
private static void Cycle(UIBlueprintBrowser browser)
{
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
Plugin.Mode.Value = (SortMode)((int)(Plugin.Mode.Value + 1) % 3);
UpdateLabel();
if (browser.currentDirectoryInfo != null)
{
browser.SetCurrentDirectory(browser.currentDirectoryInfo.FullName);
}
VFAudio.Create("ui-click-1", (Transform)null, Vector3.zero, true, 1, -1, -1L);
}
private static void UpdateLabel()
{
if (!((Object)(object)sortLabel == (Object)null))
{
switch (Plugin.Mode.Value)
{
case SortMode.Updated:
sortLabel.text = "Sort: Updated";
break;
case SortMode.Created:
sortLabel.text = "Sort: Created";
break;
default:
sortLabel.text = "Sort: Name";
break;
}
}
}
}
}