Change moddata to list.

This commit is contained in:
Ottermandias 2022-03-22 16:11:59 +01:00
parent 2cece9c422
commit 4a4d93baf3
4 changed files with 96 additions and 93 deletions

View file

@ -7,10 +7,8 @@ using System.Linq;
using System.Security.Cryptography; using System.Security.Cryptography;
using Dalamud.Logging; using Dalamud.Logging;
using Penumbra.GameData.ByteString; using Penumbra.GameData.ByteString;
using Penumbra.GameData.Util;
using Penumbra.Importer; using Penumbra.Importer;
using Penumbra.Mods; using Penumbra.Mods;
using Penumbra.Util;
namespace Penumbra.Mod; namespace Penumbra.Mod;
@ -62,8 +60,8 @@ public class ModCleanup
private static ModData CreateNewMod( DirectoryInfo newDir, string newSortOrder ) private static ModData CreateNewMod( DirectoryInfo newDir, string newSortOrder )
{ {
Penumbra.ModManager.AddMod( newDir ); var idx = Penumbra.ModManager.AddMod( newDir );
var newMod = Penumbra.ModManager.Mods[ newDir.Name ]; var newMod = Penumbra.ModManager.Mods[idx];
newMod.Move( newSortOrder ); newMod.Move( newSortOrder );
newMod.ComputeChangedItems(); newMod.ComputeChangedItems();
ModFileSystem.InvokeChange(); ModFileSystem.InvokeChange();

View file

@ -6,20 +6,36 @@ using Dalamud.Logging;
using Penumbra.GameData.ByteString; using Penumbra.GameData.ByteString;
using Penumbra.Meta; using Penumbra.Meta;
using Penumbra.Mod; using Penumbra.Mod;
using Penumbra.Util;
namespace Penumbra.Mods; namespace Penumbra.Mods;
public enum ModChangeType
{
Added,
Removed,
Changed,
}
public delegate void ModChangeDelegate( ModChangeType type, int modIndex, ModData modData );
// The ModManager handles the basic mods installed to the mod directory. // The ModManager handles the basic mods installed to the mod directory.
// It also contains the CollectionManager that handles all collections. // It also contains the CollectionManager that handles all collections.
public class ModManager public class ModManager
{ {
public DirectoryInfo BasePath { get; private set; } = null!; public DirectoryInfo BasePath { get; private set; } = null!;
public Dictionary< string, ModData > Mods { get; } = new(); private List< ModData > ModsInternal { get; init; } = new();
public IReadOnlyList< ModData > Mods
=> ModsInternal;
public ModFolder StructuredMods { get; } = ModFileSystem.Root; public ModFolder StructuredMods { get; } = ModFileSystem.Root;
public CollectionManager Collections { get; } public CollectionManager Collections { get; }
public event ModChangeDelegate? ModChange;
public bool Valid { get; private set; } public bool Valid { get; private set; }
public Configuration Config public Configuration Config
@ -38,7 +54,7 @@ public class ModManager
return; return;
} }
if( !newPath.Any() ) if( newPath.Length == 0 )
{ {
Valid = false; Valid = false;
BasePath = new DirectoryInfo( "." ); BasePath = new DirectoryInfo( "." );
@ -84,7 +100,7 @@ public class ModManager
{ {
mod.Move( path ); mod.Move( path );
var fixedPath = mod.SortOrder.FullPath; var fixedPath = mod.SortOrder.FullPath;
if( !fixedPath.Any() || string.Equals( fixedPath, mod.Meta.Name, StringComparison.InvariantCultureIgnoreCase ) ) if( fixedPath.Length == 0 || string.Equals( fixedPath, mod.Meta.Name, StringComparison.InvariantCultureIgnoreCase ) )
{ {
Config.ModSortOrder.Remove( mod.BasePath.Name ); Config.ModSortOrder.Remove( mod.BasePath.Name );
return true; return true;
@ -103,16 +119,16 @@ public class ModManager
{ {
var changes = false; var changes = false;
foreach( var kvp in Config.ModSortOrder.ToArray() ) foreach( var (folder, path) in Config.ModSortOrder.ToArray() )
{ {
if( kvp.Value.Any() && Mods.TryGetValue( kvp.Key, out var mod ) ) if( path.Length > 0 && ModsInternal.FindFirst( m => m.BasePath.Name == folder, out var mod ) )
{ {
changes |= SetSortOrderPath( mod, kvp.Value ); changes |= SetSortOrderPath( mod, path );
} }
else if( removeOldPaths ) else if( removeOldPaths )
{ {
changes = true; changes = true;
Config.ModSortOrder.Remove( kvp.Key ); Config.ModSortOrder.Remove( folder );
} }
} }
@ -124,7 +140,7 @@ public class ModManager
public void DiscoverMods() public void DiscoverMods()
{ {
Mods.Clear(); ModsInternal.Clear();
BasePath.Refresh(); BasePath.Refresh();
StructuredMods.SubFolders.Clear(); StructuredMods.SubFolders.Clear();
@ -139,7 +155,7 @@ public class ModManager
continue; continue;
} }
Mods.Add( modFolder.Name, mod ); ModsInternal.Add( mod );
} }
SetModStructure(); SetModStructure();
@ -151,8 +167,7 @@ public class ModManager
public void DeleteMod( DirectoryInfo modFolder ) public void DeleteMod( DirectoryInfo modFolder )
{ {
modFolder.Refresh(); if( Directory.Exists( modFolder.FullName ) )
if( modFolder.Exists )
{ {
try try
{ {
@ -162,22 +177,25 @@ public class ModManager
{ {
PluginLog.Error( $"Could not delete the mod {modFolder.Name}:\n{e}" ); PluginLog.Error( $"Could not delete the mod {modFolder.Name}:\n{e}" );
} }
}
if( Mods.TryGetValue( modFolder.Name, out var mod ) ) var idx = ModsInternal.FindIndex( m => m.BasePath.Name == modFolder.Name );
{ if( idx >= 0 )
mod.SortOrder.ParentFolder.RemoveMod( mod ); {
Mods.Remove( modFolder.Name ); var mod = ModsInternal[ idx ];
Collections.RemoveModFromCaches( modFolder ); mod.SortOrder.ParentFolder.RemoveMod( mod );
} ModsInternal.RemoveAt( idx );
Collections.RemoveModFromCaches( modFolder );
ModChange?.Invoke( ModChangeType.Removed, idx, mod );
} }
} }
public bool AddMod( DirectoryInfo modFolder ) public int AddMod( DirectoryInfo modFolder )
{ {
var mod = ModData.LoadMod( StructuredMods, modFolder ); var mod = ModData.LoadMod( StructuredMods, modFolder );
if( mod == null ) if( mod == null )
{ {
return false; return -1;
} }
if( Config.ModSortOrder.TryGetValue( mod.BasePath.Name, out var sortOrder ) ) if( Config.ModSortOrder.TryGetValue( mod.BasePath.Name, out var sortOrder ) )
@ -188,22 +206,24 @@ public class ModManager
} }
} }
if( Mods.ContainsKey( modFolder.Name ) ) if( ModsInternal.Any( m => m.BasePath.Name == modFolder.Name ) )
{ {
return false; return -1;
} }
Mods.Add( modFolder.Name, mod ); ModsInternal.Add( mod );
ModChange?.Invoke( ModChangeType.Added, ModsInternal.Count - 1, mod );
foreach( var collection in Collections.Collections.Values ) foreach( var collection in Collections.Collections.Values )
{ {
collection.AddMod( mod ); collection.AddMod( mod );
} }
return true; return ModsInternal.Count - 1;
} }
public bool UpdateMod( ModData mod, bool reloadMeta = false, bool recomputeMeta = false, bool force = false ) public bool UpdateMod( int idx, bool reloadMeta = false, bool recomputeMeta = false, bool force = false )
{ {
var mod = Mods[ idx ];
var oldName = mod.Meta.Name; var oldName = mod.Meta.Name;
var metaChanges = mod.Meta.RefreshFromFile( mod.MetaFile ) || force; var metaChanges = mod.Meta.RefreshFromFile( mod.MetaFile ) || force;
var fileChanges = mod.Resources.RefreshModFiles( mod.BasePath ); var fileChanges = mod.Resources.RefreshModFiles( mod.BasePath );
@ -242,60 +262,17 @@ public class ModManager
} }
Collections.UpdateCollections( mod, metaChanges, fileChanges, nameChange, reloadMeta ); Collections.UpdateCollections( mod, metaChanges, fileChanges, nameChange, reloadMeta );
ModChange?.Invoke( ModChangeType.Changed, idx, mod );
return true; return true;
} }
public bool UpdateMod( ModData mod, bool reloadMeta = false, bool recomputeMeta = false, bool force = false )
=> UpdateMod( Mods.IndexOf( mod ), reloadMeta, recomputeMeta, force );
public FullPath? ResolveSwappedOrReplacementPath( Utf8GamePath gameResourcePath ) public FullPath? ResolveSwappedOrReplacementPath( Utf8GamePath gameResourcePath )
{ {
var ret = Collections.DefaultCollection.ResolveSwappedOrReplacementPath( gameResourcePath ); var ret = Collections.DefaultCollection.ResolveSwappedOrReplacementPath( gameResourcePath );
ret ??= Collections.ForcedCollection.ResolveSwappedOrReplacementPath( gameResourcePath ); ret ??= Collections.ForcedCollection.ResolveSwappedOrReplacementPath( gameResourcePath );
return ret; return ret;
} }
// private void FileSystemWatcherOnChanged( object sender, FileSystemEventArgs e )
// {
// #if DEBUG
// PluginLog.Verbose( "file changed: {FullPath}", e.FullPath );
// #endif
//
// if( _plugin.ImportInProgress )
// {
// return;
// }
//
// if( _plugin.Configuration.DisableFileSystemNotifications )
// {
// return;
// }
//
// var file = e.FullPath;
//
// if( !ResolvedFiles.Any( x => x.Value.FullName == file ) )
// {
// return;
// }
//
// PluginLog.Log( "a loaded file has been modified - file: {FullPath}", file );
// _plugin.GameUtils.ReloadPlayerResources();
// }
//
// private void FileSystemPasta()
// {
// haha spaghet
// _fileSystemWatcher?.Dispose();
// _fileSystemWatcher = new FileSystemWatcher( _basePath.FullName )
// {
// NotifyFilter = NotifyFilters.LastWrite |
// NotifyFilters.FileName |
// NotifyFilters.DirectoryName,
// IncludeSubdirectories = true,
// EnableRaisingEvents = true
// };
//
// _fileSystemWatcher.Changed += FileSystemWatcherOnChanged;
// _fileSystemWatcher.Created += FileSystemWatcherOnChanged;
// _fileSystemWatcher.Deleted += FileSystemWatcherOnChanged;
// _fileSystemWatcher.Renamed += FileSystemWatcherOnChanged;
// }
} }

View file

@ -70,9 +70,6 @@ public static class ModManagerEditExtensions
} }
} }
manager.Mods.Remove( mod.BasePath.Name );
manager.Mods[ newDir.Name ] = mod;
var oldBasePath = mod.BasePath; var oldBasePath = mod.BasePath;
mod.BasePath = newDir; mod.BasePath = newDir;
mod.MetaFile = ModData.MetaFileInfo( newDir ); mod.MetaFile = ModData.MetaFileInfo( newDir );

View file

@ -1,28 +1,16 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
namespace Penumbra.Util; namespace Penumbra.Util;
public static class ArrayExtensions public static class ArrayExtensions
{ {
public static int IndexOf< T >( this T[] array, Predicate< T > match ) public static int IndexOf< T >( this IReadOnlyList< T > array, Predicate< T > predicate )
{
for( var i = 0; i < array.Length; ++i )
{
if( match( array[ i ] ) )
{
return i;
}
}
return -1;
}
public static int IndexOf< T >( this IList< T > array, Func< T, bool > predicate )
{ {
for( var i = 0; i < array.Count; ++i ) for( var i = 0; i < array.Count; ++i )
{ {
if( predicate.Invoke( array[ i ] ) ) if( predicate( array[ i ] ) )
{ {
return i; return i;
} }
@ -30,4 +18,47 @@ public static class ArrayExtensions
return -1; return -1;
} }
public static int IndexOf< T >( this IReadOnlyList< T > array, T needle )
{
for( var i = 0; i < array.Count; ++i )
{
if( needle!.Equals( array[i] ) )
{
return i;
}
}
return -1;
}
public static bool FindFirst< T >( this IReadOnlyList< T > array, Predicate< T > predicate, [NotNullWhen( true )] out T? result )
{
foreach( var obj in array )
{
if( predicate( obj ) )
{
result = obj!;
return true;
}
}
result = default;
return false;
}
public static bool FindFirst< T >( this IReadOnlyList< T > array, T needle, [NotNullWhen( true )] out T? result ) where T : IEquatable< T >
{
foreach( var obj in array )
{
if( obj.Equals( needle ) )
{
result = obj!;
return true;
}
}
result = default;
return false;
}
} }