mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
209 lines
No EOL
6.6 KiB
C#
209 lines
No EOL
6.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using Dalamud.Plugin;
|
|
using Newtonsoft.Json;
|
|
using Penumbra.Models;
|
|
|
|
namespace Penumbra.Mods
|
|
{
|
|
public class ModCollection
|
|
{
|
|
private readonly DirectoryInfo _basePath;
|
|
|
|
public List< ModInfo > ModSettings { get; set; }
|
|
public ResourceMod[] EnabledMods { get; set; }
|
|
|
|
|
|
public ModCollection( DirectoryInfo basePath )
|
|
{
|
|
_basePath = basePath;
|
|
}
|
|
|
|
public void Load( bool invertOrder = false )
|
|
{
|
|
// find the collection json
|
|
var collectionPath = Path.Combine( _basePath.FullName, "collection.json" );
|
|
if( File.Exists( collectionPath ) )
|
|
{
|
|
try
|
|
{
|
|
ModSettings = JsonConvert.DeserializeObject< List< ModInfo > >( File.ReadAllText( collectionPath ) );
|
|
ModSettings = ModSettings.OrderBy( x => x.Priority ).ToList();
|
|
}
|
|
catch( Exception e )
|
|
{
|
|
PluginLog.Error( $"failed to read log collection information, failed path: {collectionPath}, err: {e.Message}" );
|
|
}
|
|
}
|
|
|
|
#if DEBUG
|
|
if( ModSettings != null )
|
|
{
|
|
foreach( var ms in ModSettings )
|
|
{
|
|
PluginLog.Information(
|
|
"mod: {ModName} Enabled: {Enabled} Priority: {Priority}",
|
|
ms.FolderName, ms.Enabled, ms.Priority
|
|
);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
ModSettings ??= new();
|
|
var foundMods = new List< string >();
|
|
|
|
foreach( var modDir in _basePath.EnumerateDirectories() )
|
|
{
|
|
var metaFile = modDir.EnumerateFiles().FirstOrDefault( f => f.Name == "meta.json" );
|
|
|
|
if( metaFile == null )
|
|
{
|
|
PluginLog.LogError( "mod meta is missing for resource mod: {ResourceModLocation}", modDir );
|
|
continue;
|
|
}
|
|
|
|
var meta = JsonConvert.DeserializeObject< ModMeta >( File.ReadAllText( metaFile.FullName ) );
|
|
|
|
var mod = new ResourceMod
|
|
{
|
|
Meta = meta,
|
|
ModBasePath = modDir
|
|
};
|
|
|
|
var modEntry = FindOrCreateModSettings( mod );
|
|
foundMods.Add( modDir.Name );
|
|
mod.RefreshModFiles();
|
|
}
|
|
|
|
// remove any mods from the collection we didn't find
|
|
ModSettings = ModSettings.Where(
|
|
x =>
|
|
foundMods.Any(
|
|
fm => string.Equals( x.FolderName, fm, StringComparison.InvariantCultureIgnoreCase )
|
|
)
|
|
).ToList();
|
|
|
|
// if anything gets removed above, the priority ordering gets fucked, so we need to resort and reindex them otherwise BAD THINGS HAPPEN
|
|
ModSettings = ModSettings.OrderBy( x => x.Priority ).ToList();
|
|
var p = 0;
|
|
foreach( var modSetting in ModSettings )
|
|
{
|
|
modSetting.Priority = p++;
|
|
}
|
|
|
|
// reorder the resourcemods list so we can just directly iterate
|
|
EnabledMods = GetOrderedAndEnabledModList( invertOrder ).ToArray();
|
|
|
|
// write the collection metadata back to disk
|
|
Save();
|
|
}
|
|
|
|
public void Save()
|
|
{
|
|
var collectionPath = Path.Combine( _basePath.FullName, "collection.json" );
|
|
|
|
try
|
|
{
|
|
var data = JsonConvert.SerializeObject( ModSettings.OrderBy( x => x.Priority ).ToList() );
|
|
File.WriteAllText( collectionPath, data );
|
|
}
|
|
catch( Exception e )
|
|
{
|
|
PluginLog.Error( $"failed to write log collection information, failed path: {collectionPath}, err: {e.Message}" );
|
|
}
|
|
}
|
|
|
|
public void ReorderMod( ModInfo info, bool up )
|
|
{
|
|
// todo: certified fucked tier
|
|
|
|
var prio = info.Priority;
|
|
var swapPrio = up ? prio + 1 : prio - 1;
|
|
var swapMeta = ModSettings.FirstOrDefault( x => x.Priority == swapPrio );
|
|
|
|
if( swapMeta == null )
|
|
{
|
|
return;
|
|
}
|
|
|
|
info.Priority = swapPrio;
|
|
swapMeta.Priority = prio;
|
|
|
|
// reorder mods list
|
|
ModSettings = ModSettings.OrderBy( x => x.Priority ).ToList();
|
|
EnabledMods = GetOrderedAndEnabledModList().ToArray();
|
|
|
|
// save new prios
|
|
Save();
|
|
}
|
|
|
|
|
|
public ModInfo FindModSettings( string name )
|
|
{
|
|
var settings = ModSettings.FirstOrDefault(
|
|
x => string.Equals( x.FolderName, name, StringComparison.InvariantCultureIgnoreCase )
|
|
);
|
|
#if DEBUG
|
|
PluginLog.Information( "finding mod {ModName} - found: {ModSettingsExist}", name, settings != null );
|
|
#endif
|
|
return settings;
|
|
}
|
|
|
|
public ModInfo AddModSettings( ResourceMod mod )
|
|
{
|
|
var entry = new ModInfo
|
|
{
|
|
Priority = ModSettings.Count,
|
|
FolderName = mod.ModBasePath.Name,
|
|
Enabled = true,
|
|
Mod = mod
|
|
};
|
|
|
|
#if DEBUG
|
|
PluginLog.Information( "creating mod settings {ModName}", entry.FolderName );
|
|
#endif
|
|
|
|
ModSettings.Add( entry );
|
|
return entry;
|
|
}
|
|
|
|
public ModInfo FindOrCreateModSettings( ResourceMod mod )
|
|
{
|
|
var settings = FindModSettings( mod.ModBasePath.Name );
|
|
if( settings != null )
|
|
{
|
|
settings.Mod = mod;
|
|
return settings;
|
|
}
|
|
|
|
return AddModSettings( mod );
|
|
}
|
|
|
|
public IEnumerable<ModInfo> GetOrderedAndEnabledModSettings( bool invertOrder = false )
|
|
{
|
|
var query = ModSettings
|
|
.Where( x => x.Enabled );
|
|
|
|
if( !invertOrder )
|
|
{
|
|
return query.OrderBy( x => x.Priority );
|
|
}
|
|
|
|
return query.OrderByDescending( x => x.Priority );
|
|
}
|
|
|
|
public IEnumerable<ResourceMod> GetOrderedAndEnabledModList( bool invertOrder = false )
|
|
{
|
|
return GetOrderedAndEnabledModSettings( invertOrder )
|
|
.Select( x => x.Mod );
|
|
}
|
|
|
|
public IEnumerable<(ResourceMod, ModInfo)> GetOrderedAndEnabledModListWithSettings( bool invertOrder = false )
|
|
{
|
|
return GetOrderedAndEnabledModSettings( invertOrder )
|
|
.Select( x => (x.Mod, x) );
|
|
}
|
|
}
|
|
} |