You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

163 lines
6.9 KiB

using IPA.Loader;
using IPA.Utilities;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace BSIPA_ModList.UI
{
internal struct WarningEntry
{
public string ModName;
public string[] MissingDependencies;
public string[] IgnoredDependencies;
public string[] DisabledDependencies;
public WarningEntry(string modName, string[] missingDependencies, string[] ignoredDependencies, string[] disabledDependencies)
{
ModName = modName;
MissingDependencies = missingDependencies;
IgnoredDependencies = ignoredDependencies;
DisabledDependencies = disabledDependencies;
}
}
internal class WarningUI : MonoBehaviour
{ // TODO: rework this to just use disable/ignore reason
internal static WarningUI Instance;
internal static bool firstShow = true;
public void Awake()
{
DontDestroyOnLoad(gameObject);
SceneManager.activeSceneChanged += this.SceneManager_activeSceneChanged;
}
private void SceneManager_activeSceneChanged(Scene from, Scene to)
{
if (to.name == "EmptyTransition")
{
if (Instance != null)
{
Instance.StopAllCoroutines();
Destroy(Instance.gameObject);
_mainFlow = null;
}
Instance = null;
}
}
public void Init()
{
Instance = this;
Logger.log.Debug("Warning UI Awake");
if (firstShow)
{
firstShow = false;
StartCoroutine(LookForUnmetDependencies());
}
}
private static MainFlowCoordinator _mainFlow;
private static SimpleDialogPromptViewController _warningDialog;
private static Queue<WarningEntry> _warningsQueue = new Queue<WarningEntry>();
private static IEnumerator LookForUnmetDependencies()
{
Logger.log.Debug("Waiting for MainFlowCoordinator to appear...");
yield return new WaitWhile(() => FindObjectOfType<MainFlowCoordinator>() == null);
Logger.log.Debug("Looking for unmet dependencies...");
lock (Instance)
{
if (_mainFlow == null)
{
_mainFlow = FindObjectOfType<MainFlowCoordinator>();
_warningDialog = _mainFlow.GetPrivateField<SimpleDialogPromptViewController>("_simpleDialogPromptViewController");
}
_warningsQueue.Clear();
var enabledPlugins = PluginManager.AllPlugins.Select(p => p.Metadata).Where(x => x.Id != null).ToDictionary(x => x.Id, y => y.Version);
var ignoredPlugins = PluginLoader.ignoredPlugins.Where(x => x.Id != null).ToDictionary(x => x.Id, y => y.Version);
var disabledPlugins = PluginManager.DisabledPlugins.Where(x => x.Id != null).ToDictionary(x => x.Id, y => y.Version);
// iterate only disabled and ignored, as thats where missing deps can end up
foreach (var meta in PluginManager.DisabledPlugins.Concat(PluginLoader.ignoredPlugins))
{
List<string> disabledDependencies = new List<string>();
List<string> ignoredDependencies = new List<string>();
List<string> missingDependencies = new List<string>();
foreach (var dep in meta.Manifest.Dependencies)
{
#if DEBUG
Logger.log.Debug($"Looking for dependency {dep.Key} with version range {dep.Value.Intersect(new SemVer.Range("*.*.*"))}");
#endif
if (disabledPlugins.TryGetValue(dep.Key, out var version) && dep.Value.IsSatisfied(version))
{
Logger.log.Debug($"Dependency {dep.Key} was found, but disabled.");
disabledDependencies.Add($"{dep.Key} {dep.Value.ToString()}");
}
else if (ignoredPlugins.TryGetValue(dep.Key, out version) && dep.Value.IsSatisfied(version))
{
Logger.log.Debug($"Dependency {dep.Key} was found, but was ignored, likely due to a missing dependency.");
ignoredDependencies.Add($"{dep.Key} {dep.Value.ToString()}");
}
else if (enabledPlugins.TryGetValue(dep.Key, out version) && dep.Value.IsSatisfied(version))
{
// do nothing, this was probably user disabled
}
else
{
Logger.log.Debug($"{meta.Name} is missing dependency {dep.Key} {dep.Value}");
missingDependencies.Add($"{dep.Key} {dep.Value.ToString()}");
}
}
if(disabledDependencies.Count > 0 || ignoredDependencies.Count > 0 || missingDependencies.Count > 0)
_warningsQueue.Enqueue(new WarningEntry(meta.Name, missingDependencies.ToArray(), ignoredDependencies.ToArray(), disabledDependencies.ToArray()));
}
if (_warningsQueue.Count > 0)
{
yield return new WaitWhile(() => !_mainFlow.isActivated);
ShowWarningDialog();
}
yield break;
}
}
private static void ShowWarningDialog()
{
WarningEntry warning = _warningsQueue.Dequeue();
_warningDialog.Init("Unmet Dependencies", $"Mod <b>{warning.ModName}</b> has unmet dependencies!" +
(warning.MissingDependencies.Length > 0 ? $"\nMissing:\n<color=red>{string.Join("\n", warning.MissingDependencies)}</color>" : "") +
(warning.IgnoredDependencies.Length > 0 ? $"\nIgnored:\n<color=#C2B2B2>{string.Join("\n", warning.IgnoredDependencies)}</color>" : "") +
(warning.DisabledDependencies.Length > 0 ? $"\nDisabled:\n<color=#C2C2C2>{string.Join("\n", warning.DisabledDependencies)}</color>" : "")
, "Okay", WarningDialogDidFinish);
_mainFlow.InvokePrivateMethod("PresentViewController", _warningDialog, null, true);
}
private static void WarningDialogDidFinish(int button)
{
_mainFlow.InvokePrivateMethod("DismissViewController", _warningDialog, null, (_warningsQueue.Count > 0));
if (_warningsQueue.Count > 0)
{
ShowWarningDialog();
}
}
}
}