Skip to content
This repository has been archived by the owner on Aug 28, 2024. It is now read-only.

Commit

Permalink
feat: Auto load rotations
Browse files Browse the repository at this point in the history
Checks if file has been modified. Less resource-intensive than checking MD5. Due to the way RotationUpdater and RotationHelper loads files we limit this to every 2 seconds to prevent any noticeable FPS decrease.
  • Loading branch information
RiotNOR committed May 15, 2023
1 parent cf9d9d4 commit 5cc14f3
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 11 deletions.
1 change: 1 addition & 0 deletions RotationSolver.Basic/Configuration/PluginConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ public class PluginConfiguration : IPluginConfiguration
public int MaxPing = 300;

public bool ShowStatusWindow = false;
public bool AutoLoadCustomRotations = false;

public void Save()
{
Expand Down
3 changes: 2 additions & 1 deletion RotationSolver.Basic/Data/RSCommandType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ public enum SettingsCommand : byte
UseAOEAction,
UseAOEWhenManual,
PreventActions,
PreventActionsDuty
PreventActionsDuty,
AutoLoadCustomRotations,
}

public static class SettingsCommandExtension
Expand Down
33 changes: 33 additions & 0 deletions RotationSolver/RotationHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,28 @@
using FFXIVClientStructs.Interop;
using Lumina.Excel;
using Lumina.Excel.CustomSheets;

using RotationSolver.Updaters;

using System.Diagnostics;
using System.Runtime.Loader;
using System.Security.Cryptography;
using System.Text;

namespace RotationSolver;

internal record AssemblyInfo(string Name, string Author, string Path, string Support, string Help, string ChangeLog, string Donate);

internal class LoadedAssembly
{
public string Path { get; set; }
public string LastModified { get; set; }
}

internal static class RotationHelper
{
public static List<LoadedAssembly> LoadedCustomRotations = new();

private class RotationLoadContext : AssemblyLoadContext
{
readonly DirectoryInfo _directory;
Expand All @@ -24,6 +36,8 @@ public RotationLoadContext(DirectoryInfo directoryInfo) : base(true)
_directory = directoryInfo;
}



static RotationLoadContext()
{
var assemblies = new Assembly[]
Expand Down Expand Up @@ -152,12 +166,31 @@ public static string GetAuthor(string path, string name)
public static Assembly LoadFrom(string filePath)
{
var loadContext = new RotationLoadContext(new FileInfo(filePath).Directory);

var assembly = loadContext.LoadFromFile(filePath);

var name = assembly.GetName().Name;

var attr = assembly.GetCustomAttribute<AssemblyLinkAttribute>();
_assemblyInfos[assembly] = new AssemblyInfo(name, GetAuthor(filePath, name), filePath, attr?.SupportLink, attr?.HelpLink, attr?.ChangeLog, attr?.Donate);

var loaded = new LoadedAssembly();
loaded.Path = filePath;
loaded.LastModified = File.GetLastWriteTimeUtc(filePath).ToString();
LoadedCustomRotations.Add(loaded);

return assembly;
}

public static string GetFileMD5Hash(string filePath)
{
using (var md5 = MD5.Create())
{
using (var stream = File.OpenRead(filePath))
{
byte[] hashBytes = md5.ComputeHash(stream);
return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
}
}
}
}
3 changes: 3 additions & 0 deletions RotationSolver/UI/RotationConfigWindow_List.cs
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,9 @@ private void DrawListTab()
ImGuiHelper.Spacing();

ImGui.TextWrapped("Third-party Rotation Libraries");

ImGui.Checkbox("Auto load rotations",
ref Service.Config.AutoLoadCustomRotations);
});

ImGui.EndTabBar();
Expand Down
8 changes: 8 additions & 0 deletions RotationSolver/Updaters/MajorUpdater.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,14 @@ private static void UpdateWork()
{
PreviewUpdater.UpdateCastBarState();
TargetUpdater.UpdateTarget();

if (Service.Config.AutoLoadCustomRotations)
{
RotationUpdater.LocalRotationWatcher();
}

RotationUpdater.UpdateRotation();


ActionSequencerUpdater.UpdateActionSequencerAction();
ActionUpdater.UpdateNextAction();
Expand All @@ -119,6 +125,8 @@ private static void UpdateWork()
_work = false;
}



public static void Dispose()
{
Service.Framework.Update -= FrameworkUpdate;
Expand Down
69 changes: 59 additions & 10 deletions RotationSolver/Updaters/RotationUpdater.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ public record CustomRotationGroup(ClassJobID JobId, ClassJobID[] ClassJobIds, IC
internal static SortedList<string, string> AuthorHashes { get; private set; } = new SortedList<string, string>();
static CustomRotationGroup[] CustomRotations { get; set; } = Array.Empty<CustomRotationGroup>();

//public static List<string> LoadedPlugins = new List<string>();

[Flags]
public enum DownloadOption : byte
{
Expand Down Expand Up @@ -143,19 +145,31 @@ private static Assembly LoadOne(string filePath)
private static void LoadRotationsFromLocal(string relayFolder)
{
var directories = Service.Config.OtherLibs
#if DEBUG
.Append(relayFolder)
#else
.Append(relayFolder)
#endif
.Where(Directory.Exists);

var assemblies = from dir in directories
where Directory.Exists(dir)
from l in Directory.GetFiles(dir, "*.dll")
select LoadOne(l) into a
where a != null
select a;
var assemblies = new List<Assembly>();

foreach (var dir in directories)
{
if (Directory.Exists(dir))
{
var dlls = Directory.GetFiles(dir, "*.dll");
foreach (var dll in dlls)
{
var assembly = LoadOne(dll);

if (assembly != null)
{
assemblies.Add(assembly);
}
else
{
return;
}
}
}
}

AuthorHashes = new SortedList<string, string>(
(from a in assemblies
Expand All @@ -180,6 +194,41 @@ group rotation by rotation.JobIDs[0] into rotationGrp
.ToDictionary(set => set.Key, set => set.OrderBy(i => i.JobId).ToArray()));
}

private static DateTime LastRunTime;
public static void LocalRotationWatcher()
{
// This will cripple FPS is run on every frame.
if (DateTime.Now < LastRunTime.AddSeconds(2)) return;

var dirs = Service.Config.OtherLibs;

foreach (var dir in dirs)
{
var dlls = Directory.GetFiles(dir, "*.dll");

foreach (var dll in dlls)
{
var loaded = new LoadedAssembly();
loaded.Path = dll;
loaded.LastModified = File.GetLastWriteTimeUtc(dll).ToString();

int index = RotationHelper.LoadedCustomRotations.FindIndex(item => item.LastModified == loaded.LastModified);

if (index == -1)
{
PluginLog.LogWarning("Loading: " + dll);
GetAllCustomRotations(DownloadOption.Local);
}
else
{
PluginLog.LogWarning("Already loaded: " + dll);
}
}
}

LastRunTime = DateTime.Now;
}

private static Type[] TryGetTypes(Assembly assembly)
{
try
Expand Down

0 comments on commit 5cc14f3

Please sign in to comment.