Move MetaList out of CharacterUtility and remove static CollectionManager.

This commit is contained in:
Ottermandias 2023-04-22 00:11:47 +02:00
parent 2c55701cbf
commit c49454fc25
15 changed files with 237 additions and 247 deletions

View file

@ -21,7 +21,7 @@ public struct CmpCache : IDisposable
public void SetFiles(MetaFileManager manager) public void SetFiles(MetaFileManager manager)
=> manager.SetFile(_cmpFile, MetaIndex.HumanCmp); => manager.SetFile(_cmpFile, MetaIndex.HumanCmp);
public CharacterUtility.MetaList.MetaReverter TemporarilySetFiles(MetaFileManager manager) public MetaList.MetaReverter TemporarilySetFiles(MetaFileManager manager)
=> manager.TemporarilySetFile(_cmpFile, MetaIndex.HumanCmp); => manager.TemporarilySetFile(_cmpFile, MetaIndex.HumanCmp);
public void Reset() public void Reset()

View file

@ -34,7 +34,7 @@ public readonly struct EqdpCache : IDisposable
manager.SetFile(_eqdpFiles[i], index); manager.SetFile(_eqdpFiles[i], index);
} }
public CharacterUtility.MetaList.MetaReverter TemporarilySetFiles(MetaFileManager manager, GenderRace genderRace, bool accessory) public MetaList.MetaReverter TemporarilySetFiles(MetaFileManager manager, GenderRace genderRace, bool accessory)
{ {
var idx = CharacterUtilityData.EqdpIdx(genderRace, accessory); var idx = CharacterUtilityData.EqdpIdx(genderRace, accessory);
Debug.Assert(idx >= 0, $"Invalid Gender, Race or Accessory for EQDP file {genderRace}, {accessory}."); Debug.Assert(idx >= 0, $"Invalid Gender, Race or Accessory for EQDP file {genderRace}, {accessory}.");

View file

@ -24,7 +24,7 @@ public struct EqpCache : IDisposable
public static void ResetFiles(MetaFileManager manager) public static void ResetFiles(MetaFileManager manager)
=> manager.SetFile( null, MetaIndex.Eqp ); => manager.SetFile( null, MetaIndex.Eqp );
public CharacterUtility.MetaList.MetaReverter TemporarilySetFiles(MetaFileManager manager) public MetaList.MetaReverter TemporarilySetFiles(MetaFileManager manager)
=> manager.TemporarilySetFile( _eqpFile, MetaIndex.Eqp ); => manager.TemporarilySetFile( _eqpFile, MetaIndex.Eqp );
public void Reset() public void Reset()

View file

@ -49,7 +49,7 @@ public struct EstCache : IDisposable
} }
} }
public CharacterUtility.MetaList.MetaReverter TemporarilySetFiles(MetaFileManager manager, EstManipulation.EstType type) public MetaList.MetaReverter TemporarilySetFiles(MetaFileManager manager, EstManipulation.EstType type)
{ {
var (file, idx) = type switch var (file, idx) = type switch
{ {

View file

@ -21,7 +21,7 @@ public struct GmpCache : IDisposable
public void SetFiles(MetaFileManager manager) public void SetFiles(MetaFileManager manager)
=> manager.SetFile( _gmpFile, MetaIndex.Gmp ); => manager.SetFile( _gmpFile, MetaIndex.Gmp );
public CharacterUtility.MetaList.MetaReverter TemporarilySetFiles(MetaFileManager manager) public MetaList.MetaReverter TemporarilySetFiles(MetaFileManager manager)
=> manager.TemporarilySetFile( _gmpFile, MetaIndex.Gmp ); => manager.TemporarilySetFile( _gmpFile, MetaIndex.Gmp );
public void Reset() public void Reset()

View file

@ -159,19 +159,19 @@ public class MetaCache : IDisposable, IEnumerable<KeyValuePair<MetaManipulation,
public void SetImcFiles() public void SetImcFiles()
=> _imcCache.SetFiles(_collection); => _imcCache.SetFiles(_collection);
public CharacterUtility.MetaList.MetaReverter TemporarilySetEqpFile() public MetaList.MetaReverter TemporarilySetEqpFile()
=> _eqpCache.TemporarilySetFiles(_manager); => _eqpCache.TemporarilySetFiles(_manager);
public CharacterUtility.MetaList.MetaReverter TemporarilySetEqdpFile(GenderRace genderRace, bool accessory) public MetaList.MetaReverter TemporarilySetEqdpFile(GenderRace genderRace, bool accessory)
=> _eqdpCache.TemporarilySetFiles(_manager, genderRace, accessory); => _eqdpCache.TemporarilySetFiles(_manager, genderRace, accessory);
public CharacterUtility.MetaList.MetaReverter TemporarilySetGmpFile() public MetaList.MetaReverter TemporarilySetGmpFile()
=> _gmpCache.TemporarilySetFiles(_manager); => _gmpCache.TemporarilySetFiles(_manager);
public CharacterUtility.MetaList.MetaReverter TemporarilySetCmpFile() public MetaList.MetaReverter TemporarilySetCmpFile()
=> _cmpCache.TemporarilySetFiles(_manager); => _cmpCache.TemporarilySetFiles(_manager);
public CharacterUtility.MetaList.MetaReverter TemporarilySetEstFile(EstManipulation.EstType type) public MetaList.MetaReverter TemporarilySetEstFile(EstManipulation.EstType type)
=> _estCache.TemporarilySetFiles(_manager, type); => _estCache.TemporarilySetFiles(_manager, type);

View file

@ -5,14 +5,13 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices;
using Penumbra.Interop.Structs; using Penumbra.Interop.Structs;
using Penumbra.Meta.Files; using Penumbra.Meta.Files;
using Penumbra.Meta.Manipulations; using Penumbra.Meta.Manipulations;
using Penumbra.String.Classes; using Penumbra.String.Classes;
using CharacterUtility = Penumbra.Interop.Services.CharacterUtility; using Penumbra.Collections.Cache;
using Penumbra.Collections.Cache; using Penumbra.Interop.Services;
namespace Penumbra.Collections; namespace Penumbra.Collections;
public partial class ModCollection public partial class ModCollection
@ -94,28 +93,23 @@ public partial class ModCollection
} }
// Used for short periods of changed files. // Used for short periods of changed files.
public CharacterUtility.MetaList.MetaReverter TemporarilySetEqdpFile(GenderRace genderRace, bool accessory) public MetaList.MetaReverter TemporarilySetEqdpFile(GenderRace genderRace, bool accessory)
=> _cache?.Meta.TemporarilySetEqdpFile(genderRace, accessory) => _cache?.Meta.TemporarilySetEqdpFile(genderRace, accessory)
?? Penumbra.CharacterUtility.TemporarilyResetResource(Interop.Structs.CharacterUtilityData.EqdpIdx(genderRace, accessory)); ?? Penumbra.CharacterUtility.TemporarilyResetResource(Interop.Structs.CharacterUtilityData.EqdpIdx(genderRace, accessory));
public CharacterUtility.MetaList.MetaReverter TemporarilySetEqpFile() public MetaList.MetaReverter TemporarilySetEqpFile()
=> _cache?.Meta.TemporarilySetEqpFile() => _cache?.Meta.TemporarilySetEqpFile()
?? Penumbra.CharacterUtility.TemporarilyResetResource(MetaIndex.Eqp); ?? Penumbra.CharacterUtility.TemporarilyResetResource(MetaIndex.Eqp);
public CharacterUtility.MetaList.MetaReverter TemporarilySetGmpFile() public MetaList.MetaReverter TemporarilySetGmpFile()
=> _cache?.Meta.TemporarilySetGmpFile() => _cache?.Meta.TemporarilySetGmpFile()
?? Penumbra.CharacterUtility.TemporarilyResetResource(MetaIndex.Gmp); ?? Penumbra.CharacterUtility.TemporarilyResetResource(MetaIndex.Gmp);
public CharacterUtility.MetaList.MetaReverter TemporarilySetCmpFile() public MetaList.MetaReverter TemporarilySetCmpFile()
=> _cache?.Meta.TemporarilySetCmpFile() => _cache?.Meta.TemporarilySetCmpFile()
?? Penumbra.CharacterUtility.TemporarilyResetResource(MetaIndex.HumanCmp); ?? Penumbra.CharacterUtility.TemporarilyResetResource(MetaIndex.HumanCmp);
public CharacterUtility.MetaList.MetaReverter TemporarilySetEstFile(EstManipulation.EstType type) public MetaList.MetaReverter TemporarilySetEstFile(EstManipulation.EstType type)
=> _cache?.Meta.TemporarilySetEstFile(type) => _cache?.Meta.TemporarilySetEstFile(type)
?? Penumbra.CharacterUtility.TemporarilyResetResource((MetaIndex)type); ?? Penumbra.CharacterUtility.TemporarilyResetResource((MetaIndex)type);
}
public static class CollectionCacheExtensions
{
} }

View file

@ -10,6 +10,7 @@ using OtterGui.Filesystem;
using OtterGui.Widgets; using OtterGui.Widgets;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.Import.Structs; using Penumbra.Import.Structs;
using Penumbra.Interop.Services;
using Penumbra.Mods; using Penumbra.Mods;
using Penumbra.Services; using Penumbra.Services;
using Penumbra.UI; using Penumbra.UI;
@ -101,14 +102,14 @@ public class Configuration : IPluginConfiguration, ISavable
/// Load the current configuration. /// Load the current configuration.
/// Includes adding new colors and migrating from old versions. /// Includes adding new colors and migrating from old versions.
/// </summary> /// </summary>
public Configuration(FilenameService fileNames, ConfigMigrationService migrator, SaveService saveService) public Configuration(CharacterUtility utility, FilenameService fileNames, ConfigMigrationService migrator, SaveService saveService)
{ {
_saveService = saveService; _saveService = saveService;
Load(fileNames, migrator); Load(utility, fileNames, migrator);
UI.Classes.Colors.SetColors(this); UI.Classes.Colors.SetColors(this);
} }
public void Load(FilenameService fileNames, ConfigMigrationService migrator) public void Load(CharacterUtility utility, FilenameService fileNames, ConfigMigrationService migrator)
{ {
static void HandleDeserializationError(object? sender, ErrorEventArgs errorArgs) static void HandleDeserializationError(object? sender, ErrorEventArgs errorArgs)
{ {
@ -126,7 +127,7 @@ public class Configuration : IPluginConfiguration, ISavable
}); });
} }
migrator.Migrate(this); migrator.Migrate(utility, this);
} }
/// <summary> Save the current configuration. </summary> /// <summary> Save the current configuration. </summary>

View file

@ -1,166 +0,0 @@
using System;
using System.Collections.Generic;
using Penumbra.Interop.Structs;
namespace Penumbra.Interop.Services;
public unsafe partial class CharacterUtility
{
public class MetaList : IDisposable
{
private readonly LinkedList<MetaReverter> _entries = new();
public readonly InternalIndex Index;
public readonly MetaIndex GlobalMetaIndex;
public IReadOnlyCollection<MetaReverter> Entries
=> _entries;
private nint _defaultResourceData = nint.Zero;
private int _defaultResourceSize = 0;
public bool Ready { get; private set; } = false;
public MetaList(InternalIndex index)
{
Index = index;
GlobalMetaIndex = RelevantIndices[index.Value];
}
public void SetDefaultResource(nint data, int size)
{
if (Ready)
return;
_defaultResourceData = data;
_defaultResourceSize = size;
Ready = _defaultResourceData != nint.Zero && size != 0;
if (_entries.Count <= 0)
return;
var first = _entries.First!.Value;
SetResource(first.Data, first.Length);
}
public (nint Address, int Size) DefaultResource
=> (_defaultResourceData, _defaultResourceSize);
public MetaReverter TemporarilySetResource(nint data, int length)
{
#if false
Penumbra.Log.Verbose($"Temporarily set resource {GlobalMetaIndex} to 0x{(ulong)data:X} ({length} bytes).");
#endif
var reverter = new MetaReverter(this, data, length);
_entries.AddFirst(reverter);
SetResourceInternal(data, length);
return reverter;
}
public MetaReverter TemporarilyResetResource()
{
#if false
Penumbra.Log.Verbose(
$"Temporarily reset resource {GlobalMetaIndex} to default at 0x{_defaultResourceData:X} ({_defaultResourceSize} bytes).");
#endif
var reverter = new MetaReverter(this);
_entries.AddFirst(reverter);
ResetResourceInternal();
return reverter;
}
public void SetResource(nint data, int length)
{
#if false
Penumbra.Log.Verbose($"Set resource {GlobalMetaIndex} to 0x{(ulong)data:X} ({length} bytes).");
#endif
SetResourceInternal(data, length);
}
public void ResetResource()
{
#if false
Penumbra.Log.Verbose($"Reset resource {GlobalMetaIndex} to default at 0x{_defaultResourceData:X} ({_defaultResourceSize} bytes).");
#endif
ResetResourceInternal();
}
/// <summary> Set the currently stored data of this resource to new values. </summary>
private void SetResourceInternal(nint data, int length)
{
if (!Ready)
return;
var resource = Penumbra.CharacterUtility.Address->Resource(GlobalMetaIndex);
resource->SetData(data, length);
}
/// <summary> Reset the currently stored data of this resource to its default values. </summary>
private void ResetResourceInternal()
=> SetResourceInternal(_defaultResourceData, _defaultResourceSize);
private void SetResourceToDefaultCollection()
=> Penumbra.CollectionManager.Active.Default.SetMetaFile(GlobalMetaIndex);
public void Dispose()
{
if (_entries.Count > 0)
{
foreach (var entry in _entries)
entry.Disposed = true;
_entries.Clear();
}
ResetResourceInternal();
}
public sealed class MetaReverter : IDisposable
{
public readonly MetaList MetaList;
public readonly nint Data;
public readonly int Length;
public readonly bool Resetter;
public bool Disposed;
public MetaReverter(MetaList metaList, nint data, int length)
{
MetaList = metaList;
Data = data;
Length = length;
}
public MetaReverter(MetaList metaList)
{
MetaList = metaList;
Data = nint.Zero;
Length = 0;
Resetter = true;
}
public void Dispose()
{
if (Disposed)
return;
var list = MetaList._entries;
var wasCurrent = ReferenceEquals(this, list.First?.Value);
list.Remove(this);
if (!wasCurrent)
return;
if (list.Count == 0)
{
MetaList.SetResourceToDefaultCollection();
}
else
{
var next = list.First!.Value;
if (next.Resetter)
MetaList.ResetResourceInternal();
else
MetaList.SetResourceInternal(next.Data, next.Length);
}
Disposed = true;
}
}
}
}

View file

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using Dalamud.Game; using Dalamud.Game;
using Dalamud.Utility.Signatures; using Dalamud.Utility.Signatures;
using Penumbra.Collections.Manager;
using Penumbra.GameData; using Penumbra.GameData;
using Penumbra.Interop.Structs; using Penumbra.Interop.Structs;
@ -45,9 +46,7 @@ public unsafe partial class CharacterUtility : IDisposable
.Select(i => new InternalIndex(Array.IndexOf(RelevantIndices, (MetaIndex)i))) .Select(i => new InternalIndex(Array.IndexOf(RelevantIndices, (MetaIndex)i)))
.ToArray(); .ToArray();
private readonly MetaList[] _lists = Enumerable.Range(0, RelevantIndices.Length) private readonly MetaList[] _lists;
.Select(idx => new MetaList(new InternalIndex(idx)))
.ToArray();
public IReadOnlyList<MetaList> Lists public IReadOnlyList<MetaList> Lists
=> _lists; => _lists;
@ -55,12 +54,17 @@ public unsafe partial class CharacterUtility : IDisposable
public (nint Address, int Size) DefaultResource(InternalIndex idx) public (nint Address, int Size) DefaultResource(InternalIndex idx)
=> _lists[idx.Value].DefaultResource; => _lists[idx.Value].DefaultResource;
private readonly Framework _framework; private readonly Framework _framework;
public readonly ActiveCollectionData Active;
public CharacterUtility(Framework framework) public CharacterUtility(Framework framework, ActiveCollectionData active)
{ {
SignatureHelper.Initialise(this); SignatureHelper.Initialise(this);
_lists = Enumerable.Range(0, RelevantIndices.Length)
.Select(idx => new MetaList(this, new InternalIndex(idx)))
.ToArray();
_framework = framework; _framework = framework;
Active = active;
LoadingFinished += () => Penumbra.Log.Debug("Loading of CharacterUtility finished."); LoadingFinished += () => Penumbra.Log.Debug("Loading of CharacterUtility finished.");
LoadDefaultResources(null!); LoadDefaultResources(null!);
if (!Ready) if (!Ready)

View file

@ -0,0 +1,157 @@
using System;
using System.Collections.Generic;
using Penumbra.Interop.Structs;
namespace Penumbra.Interop.Services;
public unsafe class MetaList : IDisposable
{
private readonly CharacterUtility _utility;
private readonly LinkedList<MetaReverter> _entries = new();
public readonly CharacterUtility.InternalIndex Index;
public readonly MetaIndex GlobalMetaIndex;
public IReadOnlyCollection<MetaReverter> Entries
=> _entries;
private nint _defaultResourceData = nint.Zero;
private int _defaultResourceSize = 0;
public bool Ready { get; private set; } = false;
public MetaList(CharacterUtility utility, CharacterUtility.InternalIndex index)
{
_utility = utility;
Index = index;
GlobalMetaIndex = CharacterUtility.RelevantIndices[index.Value];
}
public void SetDefaultResource(nint data, int size)
{
if (Ready)
return;
_defaultResourceData = data;
_defaultResourceSize = size;
Ready = _defaultResourceData != nint.Zero && size != 0;
if (_entries.Count <= 0)
return;
var first = _entries.First!.Value;
SetResource(first.Data, first.Length);
}
public (nint Address, int Size) DefaultResource
=> (_defaultResourceData, _defaultResourceSize);
public MetaReverter TemporarilySetResource(nint data, int length)
{
Penumbra.Log.Excessive($"Temporarily set resource {GlobalMetaIndex} to 0x{(ulong)data:X} ({length} bytes).");
var reverter = new MetaReverter(this, data, length);
_entries.AddFirst(reverter);
SetResourceInternal(data, length);
return reverter;
}
public MetaReverter TemporarilyResetResource()
{
Penumbra.Log.Excessive(
$"Temporarily reset resource {GlobalMetaIndex} to default at 0x{_defaultResourceData:X} ({_defaultResourceSize} bytes).");
var reverter = new MetaReverter(this);
_entries.AddFirst(reverter);
ResetResourceInternal();
return reverter;
}
public void SetResource(nint data, int length)
{
Penumbra.Log.Excessive($"Set resource {GlobalMetaIndex} to 0x{(ulong)data:X} ({length} bytes).");
SetResourceInternal(data, length);
}
public void ResetResource()
{
Penumbra.Log.Excessive($"Reset resource {GlobalMetaIndex} to default at 0x{_defaultResourceData:X} ({_defaultResourceSize} bytes).");
ResetResourceInternal();
}
/// <summary> Set the currently stored data of this resource to new values. </summary>
private void SetResourceInternal(nint data, int length)
{
if (!Ready)
return;
var resource = _utility.Address->Resource(GlobalMetaIndex);
resource->SetData(data, length);
}
/// <summary> Reset the currently stored data of this resource to its default values. </summary>
private void ResetResourceInternal()
=> SetResourceInternal(_defaultResourceData, _defaultResourceSize);
private void SetResourceToDefaultCollection()
=> _utility.Active.Default.SetMetaFile(GlobalMetaIndex);
public void Dispose()
{
if (_entries.Count > 0)
{
foreach (var entry in _entries)
entry.Disposed = true;
_entries.Clear();
}
ResetResourceInternal();
}
public sealed class MetaReverter : IDisposable
{
public readonly MetaList MetaList;
public readonly nint Data;
public readonly int Length;
public readonly bool Resetter;
public bool Disposed;
public MetaReverter(MetaList metaList, nint data, int length)
{
MetaList = metaList;
Data = data;
Length = length;
}
public MetaReverter(MetaList metaList)
{
MetaList = metaList;
Data = nint.Zero;
Length = 0;
Resetter = true;
}
public void Dispose()
{
if (Disposed)
return;
var list = MetaList._entries;
var wasCurrent = ReferenceEquals(this, list.First?.Value);
list.Remove(this);
if (!wasCurrent)
return;
if (list.Count == 0)
{
MetaList.SetResourceToDefaultCollection();
}
else
{
var next = list.First!.Value;
if (next.Resetter)
MetaList.ResetResourceInternal();
else
MetaList.SetResourceInternal(next.Data, next.Length);
}
Disposed = true;
}
}
}

View file

@ -78,7 +78,7 @@ public unsafe class MetaFileManager
} }
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public CharacterUtility.MetaList.MetaReverter TemporarilySetFile(MetaBaseFile? file, MetaIndex metaIndex) public MetaList.MetaReverter TemporarilySetFile(MetaBaseFile? file, MetaIndex metaIndex)
=> file == null => file == null
? CharacterUtility.TemporarilyResetResource(metaIndex) ? CharacterUtility.TemporarilyResetResource(metaIndex)
: CharacterUtility.TemporarilySetResource(metaIndex, (nint)file.Data, file.Length); : CharacterUtility.TemporarilySetResource(metaIndex, (nint)file.Data, file.Length);

View file

@ -15,12 +15,8 @@ using Penumbra.UI;
using Penumbra.Util; using Penumbra.Util;
using Penumbra.Collections; using Penumbra.Collections;
using Penumbra.Collections.Cache; using Penumbra.Collections.Cache;
using Penumbra.GameData.Actors;
using Penumbra.Interop.ResourceLoading; using Penumbra.Interop.ResourceLoading;
using Penumbra.Interop.PathResolving; using Penumbra.Interop.PathResolving;
using CharacterUtility = Penumbra.Interop.Services.CharacterUtility;
using DalamudUtil = Dalamud.Utility.Util;
using ResidentResourceManager = Penumbra.Interop.Services.ResidentResourceManager;
using Penumbra.Services; using Penumbra.Services;
using Penumbra.Interop.Services; using Penumbra.Interop.Services;
using Penumbra.Mods.Manager; using Penumbra.Mods.Manager;
@ -34,11 +30,10 @@ public class Penumbra : IDalamudPlugin
public string Name public string Name
=> "Penumbra"; => "Penumbra";
public static Logger Log { get; private set; } = null!; public static Logger Log { get; private set; } = null!;
public static ChatService ChatService { get; private set; } = null!; public static ChatService ChatService { get; private set; } = null!;
public static CharacterUtility CharacterUtility { get; private set; } = null!; public static CharacterUtility CharacterUtility { get; private set; } = null!;
public static CollectionManager CollectionManager { get; private set; } = null!;
public readonly RedrawService RedrawService; public readonly RedrawService RedrawService;
public readonly ModFileSystem ModFileSystem; public readonly ModFileSystem ModFileSystem;
@ -50,7 +45,9 @@ public class Penumbra : IDalamudPlugin
private readonly TempModManager _tempMods; private readonly TempModManager _tempMods;
private readonly TempCollectionManager _tempCollections; private readonly TempCollectionManager _tempCollections;
private readonly ModManager _modManager; private readonly ModManager _modManager;
private readonly CollectionManager _collectionManager;
private readonly Configuration _config; private readonly Configuration _config;
private readonly CharacterUtility _characterUtility;
private PenumbraWindowSystem? _windowSystem; private PenumbraWindowSystem? _windowSystem;
private bool _disposed; private bool _disposed;
@ -65,16 +62,17 @@ public class Penumbra : IDalamudPlugin
ChatService = _tmp.Services.GetRequiredService<ChatService>(); ChatService = _tmp.Services.GetRequiredService<ChatService>();
_validityChecker = _tmp.Services.GetRequiredService<ValidityChecker>(); _validityChecker = _tmp.Services.GetRequiredService<ValidityChecker>();
_tmp.Services.GetRequiredService<BackupService>(); _tmp.Services.GetRequiredService<BackupService>();
_config = _tmp.Services.GetRequiredService<Configuration>(); _config = _tmp.Services.GetRequiredService<Configuration>();
CharacterUtility = _tmp.Services.GetRequiredService<CharacterUtility>(); _characterUtility = _tmp.Services.GetRequiredService<CharacterUtility>();
CharacterUtility = _characterUtility;
_tempMods = _tmp.Services.GetRequiredService<TempModManager>(); _tempMods = _tmp.Services.GetRequiredService<TempModManager>();
_residentResources = _tmp.Services.GetRequiredService<ResidentResourceManager>(); _residentResources = _tmp.Services.GetRequiredService<ResidentResourceManager>();
_tmp.Services.GetRequiredService<ResourceManagerService>(); _tmp.Services.GetRequiredService<ResourceManagerService>();
_modManager = _tmp.Services.GetRequiredService<ModManager>(); _modManager = _tmp.Services.GetRequiredService<ModManager>();
CollectionManager = _tmp.Services.GetRequiredService<CollectionManager>(); _collectionManager = _tmp.Services.GetRequiredService<CollectionManager>();
_tempCollections = _tmp.Services.GetRequiredService<TempCollectionManager>(); _tempCollections = _tmp.Services.GetRequiredService<TempCollectionManager>();
ModFileSystem = _tmp.Services.GetRequiredService<ModFileSystem>(); ModFileSystem = _tmp.Services.GetRequiredService<ModFileSystem>();
RedrawService = _tmp.Services.GetRequiredService<RedrawService>(); RedrawService = _tmp.Services.GetRequiredService<RedrawService>();
_tmp.Services.GetRequiredService<ResourceService>(); // Initialize because not required anywhere else. _tmp.Services.GetRequiredService<ResourceService>(); // Initialize because not required anywhere else.
_tmp.Services.GetRequiredService<ModCacheManager>(); // Initialize because not required anywhere else. _tmp.Services.GetRequiredService<ModCacheManager>(); // Initialize because not required anywhere else.
using (var t = _tmp.Services.GetRequiredService<StartTracker>().Measure(StartTimeType.PathResolver)) using (var t = _tmp.Services.GetRequiredService<StartTracker>().Measure(StartTimeType.PathResolver))
@ -91,7 +89,7 @@ public class Penumbra : IDalamudPlugin
OtterTex.NativeDll.Initialize(pluginInterface.AssemblyLocation.DirectoryName); OtterTex.NativeDll.Initialize(pluginInterface.AssemblyLocation.DirectoryName);
Log.Information($"Loading native OtterTex assembly from {OtterTex.NativeDll.Directory}."); Log.Information($"Loading native OtterTex assembly from {OtterTex.NativeDll.Directory}.");
if (CharacterUtility.Ready) if (_characterUtility.Ready)
_residentResources.Reload(); _residentResources.Reload();
} }
catch catch
@ -149,18 +147,18 @@ public class Penumbra : IDalamudPlugin
_config.EnableMods = enabled; _config.EnableMods = enabled;
if (enabled) if (enabled)
{ {
if (CharacterUtility.Ready) if (_characterUtility.Ready)
{ {
CollectionManager.Active.Default.SetFiles(); _collectionManager.Active.Default.SetFiles();
_residentResources.Reload(); _residentResources.Reload();
RedrawService.RedrawAll(RedrawType.Redraw); RedrawService.RedrawAll(RedrawType.Redraw);
} }
} }
else else
{ {
if (CharacterUtility.Ready) if (_characterUtility.Ready)
{ {
CharacterUtility.ResetAll(); _characterUtility.ResetAll();
_residentResources.Reload(); _residentResources.Reload();
RedrawService.RedrawAll(RedrawType.Redraw); RedrawService.RedrawAll(RedrawType.Redraw);
} }
@ -194,7 +192,7 @@ public class Penumbra : IDalamudPlugin
sb.Append($"> **`Commit Hash: `** {_validityChecker.CommitHash}\n"); sb.Append($"> **`Commit Hash: `** {_validityChecker.CommitHash}\n");
sb.Append($"> **`Enable Mods: `** {_config.EnableMods}\n"); sb.Append($"> **`Enable Mods: `** {_config.EnableMods}\n");
sb.Append($"> **`Enable HTTP API: `** {_config.EnableHttpApi}\n"); sb.Append($"> **`Enable HTTP API: `** {_config.EnableHttpApi}\n");
sb.Append($"> **`Operating System: `** {(DalamudUtil.IsLinux() ? "Mac/Linux (Wine)" : "Windows")}\n"); sb.Append($"> **`Operating System: `** {(Dalamud.Utility.Util.IsLinux() ? "Mac/Linux (Wine)" : "Windows")}\n");
sb.Append($"> **`Root Directory: `** `{_config.ModDirectory}`, {(exists ? "Exists" : "Not Existing")}\n"); sb.Append($"> **`Root Directory: `** `{_config.ModDirectory}`, {(exists ? "Exists" : "Not Existing")}\n");
sb.Append( sb.Append(
$"> **`Free Drive Space: `** {(drive != null ? Functions.HumanReadableSize(drive.AvailableFreeSpace) : "Unknown")}\n"); $"> **`Free Drive Space: `** {(drive != null ? Functions.HumanReadableSize(drive.AvailableFreeSpace) : "Unknown")}\n");
@ -225,23 +223,23 @@ public class Penumbra : IDalamudPlugin
+ $"> **`Conflicts (Solved/Total): `** {c.AllConflicts.SelectMany(x => x).Sum(x => x.HasPriority && x.Solved ? x.Conflicts.Count : 0)}/{c.AllConflicts.SelectMany(x => x).Sum(x => x.HasPriority ? x.Conflicts.Count : 0)}\n"); + $"> **`Conflicts (Solved/Total): `** {c.AllConflicts.SelectMany(x => x).Sum(x => x.HasPriority && x.Solved ? x.Conflicts.Count : 0)}/{c.AllConflicts.SelectMany(x => x).Sum(x => x.HasPriority ? x.Conflicts.Count : 0)}\n");
sb.AppendLine("**Collections**"); sb.AppendLine("**Collections**");
sb.Append($"> **`#Collections: `** {CollectionManager.Storage.Count - 1}\n"); sb.Append($"> **`#Collections: `** {_collectionManager.Storage.Count - 1}\n");
sb.Append($"> **`#Temp Collections: `** {_tempCollections.Count}\n"); sb.Append($"> **`#Temp Collections: `** {_tempCollections.Count}\n");
sb.Append($"> **`Active Collections: `** {CollectionManager.Caches.Count - _tempCollections.Count}\n"); sb.Append($"> **`Active Collections: `** {_collectionManager.Caches.Count - _tempCollections.Count}\n");
sb.Append($"> **`Base Collection: `** {CollectionManager.Active.Default.AnonymizedName}\n"); sb.Append($"> **`Base Collection: `** {_collectionManager.Active.Default.AnonymizedName}\n");
sb.Append($"> **`Interface Collection: `** {CollectionManager.Active.Interface.AnonymizedName}\n"); sb.Append($"> **`Interface Collection: `** {_collectionManager.Active.Interface.AnonymizedName}\n");
sb.Append($"> **`Selected Collection: `** {CollectionManager.Active.Current.AnonymizedName}\n"); sb.Append($"> **`Selected Collection: `** {_collectionManager.Active.Current.AnonymizedName}\n");
foreach (var (type, name, _) in CollectionTypeExtensions.Special) foreach (var (type, name, _) in CollectionTypeExtensions.Special)
{ {
var collection = CollectionManager.Active.ByType(type); var collection = _collectionManager.Active.ByType(type);
if (collection != null) if (collection != null)
sb.Append($"> **`{name,-30}`** {collection.AnonymizedName}\n"); sb.Append($"> **`{name,-30}`** {collection.AnonymizedName}\n");
} }
foreach (var (name, id, collection) in CollectionManager.Active.Individuals.Assignments) foreach (var (name, id, collection) in _collectionManager.Active.Individuals.Assignments)
sb.Append($"> **`{id[0].Incognito(name) + ':',-30}`** {collection.AnonymizedName}\n"); sb.Append($"> **`{id[0].Incognito(name) + ':',-30}`** {collection.AnonymizedName}\n");
foreach (var (collection, cache) in CollectionManager.Caches.Active) foreach (var (collection, cache) in _collectionManager.Caches.Active)
PrintCollection(collection, cache); PrintCollection(collection, cache);
return sb.ToString(); return sb.ToString();

View file

@ -2,17 +2,16 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using Dalamud.Plugin;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using OtterGui.Filesystem; using OtterGui.Filesystem;
using Penumbra.Collections; using Penumbra.Collections;
using Penumbra.Collections.Manager; using Penumbra.Collections.Manager;
using Penumbra.Interop.Services;
using Penumbra.Mods; using Penumbra.Mods;
using Penumbra.Mods.Manager; using Penumbra.Mods.Manager;
using Penumbra.UI.Classes; using Penumbra.UI.Classes;
using Penumbra.Util; using Penumbra.Util;
using SixLabors.ImageSharp;
namespace Penumbra.Services; namespace Penumbra.Services;
@ -50,7 +49,7 @@ public class ConfigMigrationService
config.Save(); config.Save();
} }
public void Migrate(Configuration config) public void Migrate(CharacterUtility utility, Configuration config)
{ {
_config = config; _config = config;
// Do this on every migration from now on for a while // Do this on every migration from now on for a while
@ -67,7 +66,7 @@ public class ConfigMigrationService
CreateBackup(); CreateBackup();
Version0To1(); Version0To1();
Version1To2(); Version1To2(utility);
Version2To3(); Version2To3();
Version3To4(); Version3To4();
Version4To5(); Version4To5();
@ -149,14 +148,15 @@ public class ConfigMigrationService
// Sort Order was moved to a separate file and may contain empty folders. // Sort Order was moved to a separate file and may contain empty folders.
// Active collections in general were moved to their own file. // Active collections in general were moved to their own file.
// Delete the penumbrametatmp folder if it exists. // Delete the penumbrametatmp folder if it exists.
private void Version1To2() private void Version1To2(CharacterUtility utility)
{ {
if (_config.Version != 1) if (_config.Version != 1)
return; return;
// Ensure the right meta files are loaded. // Ensure the right meta files are loaded.
DeleteMetaTmp(); DeleteMetaTmp();
Penumbra.CharacterUtility.LoadCharacterResources(); if (utility.Ready)
utility.LoadCharacterResources();
ResettleSortOrder(); ResettleSortOrder();
ResettleCollectionSettings(); ResettleCollectionSettings();
ResettleForcedCollection(); ResettleForcedCollection();

View file

@ -9,13 +9,13 @@ using Dalamud.Interface.Windowing;
using ImGuiNET; using ImGuiNET;
using OtterGui; using OtterGui;
using OtterGui.Raii; using OtterGui.Raii;
using Penumbra.Collections.Manager;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Files; using Penumbra.GameData.Files;
using Penumbra.Import.Textures; using Penumbra.Import.Textures;
using Penumbra.Interop.ResourceTree; using Penumbra.Interop.ResourceTree;
using Penumbra.Meta; using Penumbra.Meta;
using Penumbra.Mods; using Penumbra.Mods;
using Penumbra.Mods.Manager;
using Penumbra.Services; using Penumbra.Services;
using Penumbra.String.Classes; using Penumbra.String.Classes;
using Penumbra.UI.Classes; using Penumbra.UI.Classes;
@ -33,6 +33,7 @@ public partial class ModEditWindow : Window, IDisposable
private readonly ItemSwapTab _itemSwapTab; private readonly ItemSwapTab _itemSwapTab;
private readonly DataManager _gameData; private readonly DataManager _gameData;
private readonly MetaFileManager _metaFileManager; private readonly MetaFileManager _metaFileManager;
private readonly ActiveCollections _activeCollections;
private readonly StainService _stainService; private readonly StainService _stainService;
private Mod? _mod; private Mod? _mod;
@ -56,7 +57,7 @@ public partial class ModEditWindow : Window, IDisposable
_modelTab.Reset(); _modelTab.Reset();
_materialTab.Reset(); _materialTab.Reset();
_shaderPackageTab.Reset(); _shaderPackageTab.Reset();
_itemSwapTab.UpdateMod(mod, Penumbra.CollectionManager.Active.Current[mod.Index].Settings); _itemSwapTab.UpdateMod(mod, _activeCollections.Current[mod.Index].Settings);
} }
public void ChangeOption(SubMod? subMod) public void ChangeOption(SubMod? subMod)
@ -479,7 +480,7 @@ public partial class ModEditWindow : Window, IDisposable
/// </remarks> /// </remarks>
private FullPath FindBestMatch(Utf8GamePath path) private FullPath FindBestMatch(Utf8GamePath path)
{ {
var currentFile = Penumbra.CollectionManager.Active.Current.ResolvePath(path); var currentFile = _activeCollections.Current.ResolvePath(path);
if (currentFile != null) if (currentFile != null)
return currentFile.Value; return currentFile.Value;
@ -497,17 +498,18 @@ public partial class ModEditWindow : Window, IDisposable
public ModEditWindow(PerformanceTracker performance, FileDialogService fileDialog, ItemSwapTab itemSwapTab, DataManager gameData, public ModEditWindow(PerformanceTracker performance, FileDialogService fileDialog, ItemSwapTab itemSwapTab, DataManager gameData,
Configuration config, ModEditor editor, ResourceTreeFactory resourceTreeFactory, MetaFileManager metaFileManager, Configuration config, ModEditor editor, ResourceTreeFactory resourceTreeFactory, MetaFileManager metaFileManager,
StainService stainService) StainService stainService, ActiveCollections activeCollections)
: base(WindowBaseLabel) : base(WindowBaseLabel)
{ {
_performance = performance; _performance = performance;
_itemSwapTab = itemSwapTab; _itemSwapTab = itemSwapTab;
_config = config; _config = config;
_editor = editor; _editor = editor;
_metaFileManager = metaFileManager; _metaFileManager = metaFileManager;
_stainService = stainService; _stainService = stainService;
_gameData = gameData; _activeCollections = activeCollections;
_fileDialog = fileDialog; _gameData = gameData;
_fileDialog = fileDialog;
_materialTab = new FileEditor<MtrlTab>(this, gameData, config, _fileDialog, "Materials", ".mtrl", _materialTab = new FileEditor<MtrlTab>(this, gameData, config, _fileDialog, "Materials", ".mtrl",
() => _editor.Files.Mtrl, DrawMaterialPanel, () => _mod?.ModPath.FullName ?? string.Empty, () => _editor.Files.Mtrl, DrawMaterialPanel, () => _mod?.ModPath.FullName ?? string.Empty,
bytes => new MtrlTab(this, new MtrlFile(bytes))); bytes => new MtrlTab(this, new MtrlFile(bytes)));