Add changelog, improve Support Info, fix bug with folder checking, remove obsolete ownership settings.

This commit is contained in:
Ottermandias 2022-11-19 21:16:38 +01:00
parent 893e0a13bd
commit c8edd87df8
6 changed files with 99 additions and 70 deletions

View file

@ -170,7 +170,7 @@ public partial class ModCollection
} }
// Wrappers around Individual Collection handling. // Wrappers around Individual Collection handling.
public void CreateIndividualCollection( ActorIdentifier[] identifiers ) public void CreateIndividualCollection( params ActorIdentifier[] identifiers )
{ {
if( Individuals.Add( identifiers, Default ) ) if( Individuals.Add( identifiers, Default ) )
{ {

View file

@ -37,8 +37,6 @@ public partial class Configuration : IPluginConfiguration
public bool UseCharacterCollectionInInspect { get; set; } = true; public bool UseCharacterCollectionInInspect { get; set; } = true;
public bool UseCharacterCollectionInTryOn { get; set; } = true; public bool UseCharacterCollectionInTryOn { get; set; } = true;
public bool UseOwnerNameForCharacterCollection { get; set; } = true; public bool UseOwnerNameForCharacterCollection { get; set; } = true;
public bool PreferNamedCollectionsOverOwners { get; set; } = true;
public bool UseDefaultCollectionForRetainers { get; set; } = false;
public bool HideRedrawBar { get; set; } = false; public bool HideRedrawBar { get; set; } = false;

View file

@ -28,6 +28,7 @@ using Penumbra.GameData.Actors;
using Penumbra.Interop.Loader; using Penumbra.Interop.Loader;
using Penumbra.Interop.Resolver; using Penumbra.Interop.Resolver;
using Penumbra.Mods; using Penumbra.Mods;
using Penumbra.String;
using CharacterUtility = Penumbra.Interop.CharacterUtility; using CharacterUtility = Penumbra.Interop.CharacterUtility;
using ResidentResourceManager = Penumbra.Interop.ResidentResourceManager; using ResidentResourceManager = Penumbra.Interop.ResidentResourceManager;
@ -337,7 +338,7 @@ public class Penumbra : IDalamudPlugin
var split = collectionName.Split( '|', 2, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries ); var split = collectionName.Split( '|', 2, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries );
if( split.Length < 2 || split[ 0 ].Length == 0 || split[ 1 ].Length == 0 ) if( split.Length < 2 || split[ 0 ].Length == 0 || split[ 1 ].Length == 0 )
{ {
Dalamud.Chat.Print( "You need to provide a collection and a character name in the form of 'collection | character' to set a character collection." ); Dalamud.Chat.Print( "You need to provide a collection and a character name in the form of 'collection | name' to set an individual collection." );
return false; return false;
} }
@ -355,27 +356,33 @@ public class Penumbra : IDalamudPlugin
return false; return false;
} }
// TODO var identifier = Actors.CreatePlayer( ByteString.FromStringUnsafe( characterName, false ), ushort.MaxValue );
//var oldCollection = CollectionManager.ByType( type, characterName ); if( !identifier.IsValid )
//if( collection == oldCollection ) {
//{ Dalamud.Chat.Print( $"{characterName} is not a valid character name." );
// Dalamud.Chat.Print( $"{collection.Name} already is the {type.ToName()} Collection." ); return false;
// return false; }
//}
// var oldCollection = CollectionManager.ByType( type, identifier );
//if( oldCollection == null ) if( collection == oldCollection )
//{ {
// if( type.IsSpecial() ) Dalamud.Chat.Print( $"{collection.Name} already is the {type.ToName()} Collection." );
// { return false;
// CollectionManager.CreateSpecialCollection( type ); }
// }
// else if( type is CollectionType.Individual ) if( oldCollection == null )
// { {
// CollectionManager.CreateIndividualCollection( characterName! ); if( type.IsSpecial() )
// } {
//} CollectionManager.CreateSpecialCollection( type );
// }
//CollectionManager.SetCollection( collection, type, characterName ); else if( type is CollectionType.Individual )
{
CollectionManager.CreateIndividualCollection( identifier );
}
}
CollectionManager.SetCollection( collection, type, CollectionManager.Individuals.Count - 1 );
Dalamud.Chat.Print( $"Set {collection.Name} as {type.ToName()} Collection{( characterName != null ? $" for {characterName}." : "." )}" ); Dalamud.Chat.Print( $"Set {collection.Name} as {type.ToName()} Collection{( characterName != null ? $" for {characterName}." : "." )}" );
return true; return true;
} }
@ -490,62 +497,61 @@ public class Penumbra : IDalamudPlugin
var exists = Config.ModDirectory.Length > 0 && Directory.Exists( Config.ModDirectory ); var exists = Config.ModDirectory.Length > 0 && Directory.Exists( Config.ModDirectory );
var drive = exists ? new DriveInfo( new DirectoryInfo( Config.ModDirectory ).Root.FullName ) : null; var drive = exists ? new DriveInfo( new DirectoryInfo( Config.ModDirectory ).Root.FullName ) : null;
sb.AppendLine( "**Settings**" ); sb.AppendLine( "**Settings**" );
sb.AppendFormat( "> **`Plugin Version: `** {0}\n", Version ); sb.Append( $"> **`Plugin Version: `** {Version}\n" );
sb.AppendFormat( "> **`Commit Hash: `** {0}\n", CommitHash ); sb.Append( $"> **`Commit Hash: `** {CommitHash}\n" );
sb.AppendFormat( "> **`Enable Mods: `** {0}\n", Config.EnableMods ); sb.Append( $"> **`Enable Mods: `** {Config.EnableMods}\n" );
sb.AppendFormat( "> **`Enable HTTP API: `** {0}\n", Config.EnableHttpApi ); sb.Append( $"> **`Enable HTTP API: `** {Config.EnableHttpApi}\n" );
sb.AppendFormat( "> **`Root Directory: `** `{0}`, {1}\n", Config.ModDirectory, exists ? "Exists" : "Not Existing" ); sb.Append( $"> **`Root Directory: `** `{Config.ModDirectory}`, {( exists ? "Exists" : "Not Existing" )}\n" );
sb.AppendFormat( "> **`Free Drive Space: `** {0}\n", sb.Append( $"> **`Free Drive Space: `** {( drive != null ? Functions.HumanReadableSize( drive.AvailableFreeSpace ) : "Unknown" )}\n" );
drive != null ? Functions.HumanReadableSize( drive.AvailableFreeSpace ) : "Unknown" ); sb.Append( $"> **`Auto-Deduplication: `** {Config.AutoDeduplicateOnImport}\n" );
sb.Append( $"> **`Debug Mode: `** {Config.DebugMode}\n" );
sb.Append( $"> **`Logging: `** Full: {Config.EnableFullResourceLogging}, Resource: {Config.EnableResourceLogging}\n" );
sb.Append( $"> **`Use Ownership: `** {Config.UseOwnerNameForCharacterCollection}\n" );
sb.AppendLine( "**Mods**" ); sb.AppendLine( "**Mods**" );
sb.AppendFormat( "> **`Installed Mods: `** {0}\n", ModManager.Count ); sb.Append( $"> **`Installed Mods: `** {ModManager.Count}\n" );
sb.AppendFormat( "> **`Mods with Config: `** {0}\n", ModManager.Count( m => m.HasOptions ) ); sb.Append( $"> **`Mods with Config: `** {ModManager.Count( m => m.HasOptions )}\n" );
sb.AppendFormat( "> **`Mods with File Redirections: `** {0}, Total: {1}\n", ModManager.Count( m => m.TotalFileCount > 0 ), sb.Append( $"> **`Mods with File Redirections: `** {ModManager.Count( m => m.TotalFileCount > 0 )}, Total: {ModManager.Sum( m => m.TotalFileCount )}\n" );
ModManager.Sum( m => m.TotalFileCount ) ); sb.Append( $"> **`Mods with FileSwaps: `** {ModManager.Count( m => m.TotalSwapCount > 0 )}, Total: {ModManager.Sum( m => m.TotalSwapCount )}\n" );
sb.AppendFormat( "> **`Mods with FileSwaps: `** {0}, Total: {1}\n", ModManager.Count( m => m.TotalSwapCount > 0 ), sb.Append( $"> **`Mods with Meta Manipulations:`** {ModManager.Count( m => m.TotalManipulations > 0 )}, Total {ModManager.Sum( m => m.TotalManipulations )}\n" );
ModManager.Sum( m => m.TotalSwapCount ) ); sb.Append( $"> **`IMC Exceptions Thrown: `** {ImcExceptions.Count}\n" );
sb.AppendFormat( "> **`Mods with Meta Manipulations:`** {0}, Total {1}\n", ModManager.Count( m => m.TotalManipulations > 0 ), sb.Append( $"> **`#Temp Mods: `** {TempMods.Mods.Sum( kvp => kvp.Value.Count ) + TempMods.ModsForAllCollections.Count}\n" );
ModManager.Sum( m => m.TotalManipulations ) );
sb.AppendFormat( "> **`IMC Exceptions Thrown: `** {0}\n", ImcExceptions );
string CharacterName( ActorIdentifier id, string name ) string CharacterName( ActorIdentifier id, string name )
{ {
if( id.Type is IdentifierType.Player or IdentifierType.Owned ) if( id.Type is IdentifierType.Player or IdentifierType.Owned )
{ {
return string.Join( " ", name.Split( ' ', 3 ).Select( n => $"{n[ 0 ]}." ) ) + ':'; var parts = name.Split( ' ', 3 );
return string.Join( " ", parts.Length != 3 ? parts.Select( n => $"{n[ 0 ]}." ) : parts[ ..2 ].Select( n => $"{n[ 0 ]}." ).Append( parts[2] ) );
} }
return name + ':'; return name + ':';
} }
void PrintCollection( ModCollection c ) void PrintCollection( ModCollection c )
=> sb.AppendFormat( "**Collection {0}**\n" => sb.Append( $"**Collection {c.AnonymizedName}**\n"
+ "> **`Inheritances: `** {1}\n" + $"> **`Inheritances: `** {c.Inheritance.Count}\n"
+ "> **`Enabled Mods: `** {2}\n" + $"> **`Enabled Mods: `** {c.ActualSettings.Count( s => s is { Enabled: true } )}\n"
+ "> **`Total Conflicts: `** {3}\n" + $"> **`Conflicts (Solved/Total): `** {c.AllConflicts.SelectMany( x => x ).Sum( x => x.HasPriority ? 0 : x.Conflicts.Count )}/{c.AllConflicts.SelectMany( x => x ).Sum( x => x.HasPriority || !x.Solved ? 0 : x.Conflicts.Count )}\n" );
+ "> **`Solved Conflicts: `** {4}\n",
c.AnonymizedName, c.Inheritance.Count, c.ActualSettings.Count( s => s is { Enabled: true } ),
c.AllConflicts.SelectMany( x => x ).Sum( x => x.HasPriority ? 0 : x.Conflicts.Count ),
c.AllConflicts.SelectMany( x => x ).Sum( x => x.HasPriority || !x.Solved ? 0 : x.Conflicts.Count ) );
sb.AppendLine( "**Collections**" ); sb.AppendLine( "**Collections**" );
sb.AppendFormat( "> **`#Collections: `** {0}\n", CollectionManager.Count - 1 ); sb.Append( $"> **`#Collections: `** {CollectionManager.Count - 1}\n" );
sb.AppendFormat( "> **`Active Collections: `** {0}\n", CollectionManager.Count( c => c.HasCache ) ); sb.Append( $"> **`#Temp Collections: `** {TempMods.CustomCollections.Count}\n" );
sb.AppendFormat( "> **`Base Collection: `** {0}\n", CollectionManager.Default.AnonymizedName ); sb.Append( $"> **`Active Collections: `** {CollectionManager.Count( c => c.HasCache )}\n" );
sb.AppendFormat( "> **`Interface Collection: `** {0}\n", CollectionManager.Interface.AnonymizedName ); sb.Append( $"> **`Base Collection: `** {CollectionManager.Default.AnonymizedName}\n" );
sb.AppendFormat( "> **`Selected Collection: `** {0}\n", CollectionManager.Current.AnonymizedName ); sb.Append( $"> **`Interface Collection: `** {CollectionManager.Interface.AnonymizedName}\n" );
sb.Append( $"> **`Selected Collection: `** {CollectionManager.Current.AnonymizedName}\n" );
foreach( var (type, name, _) in CollectionTypeExtensions.Special ) foreach( var (type, name, _) in CollectionTypeExtensions.Special )
{ {
var collection = CollectionManager.ByType( type ); var collection = CollectionManager.ByType( type );
if( collection != null ) if( collection != null )
{ {
sb.AppendFormat( "> **`{0,-29}`** {1}\n", name, collection.AnonymizedName ); sb.Append( $"> **`{name,-30}`** {collection.AnonymizedName}\n" );
} }
} }
foreach( var (name, id, collection) in CollectionManager.Individuals.Assignments ) foreach( var (name, id, collection) in CollectionManager.Individuals.Assignments )
{ {
sb.AppendFormat( "> **`{1,-29}`** {0}\n", collection.AnonymizedName, CharacterName( id[ 0 ], name ) ); sb.Append( $"> **`{CharacterName( id[ 0 ], name ),-30}`** {collection.AnonymizedName}\n" );
} }
foreach( var collection in CollectionManager.Where( c => c.HasCache ) ) foreach( var collection in CollectionManager.Where( c => c.HasCache ) )

View file

@ -24,10 +24,38 @@ public partial class ConfigWindow
Add5_10_0( ret ); Add5_10_0( ret );
Add5_11_0( ret ); Add5_11_0( ret );
Add5_11_1( ret ); Add5_11_1( ret );
Add6_0_0( ret );
return ret; return ret;
} }
private static void Add6_0_0( Changelog log )
=> log.NextVersion( "Version 0.6.0.0" )
.RegisterEntry( "Revamped Individual Collections:" )
.RegisterEntry( "You can now specify individual collections for players (by name) of specific worlds or any world.", 1 )
.RegisterEntry( "You can also specify NPCs (by grouped name and type of NPC), and owned NPCs (by specifying an NPC and a Player).", 1 )
.RegisterHighlight(
"Migration should move all current names that correspond to NPCs to the appropriate NPC group and all names that can be valid Player names to a Player of any world.",
1 )
.RegisterHighlight(
"Please look through your Individual Collections to verify everything migrated correctly and corresponds to the game object you want. You might also want to change the 'Player (Any World)' collections to your specific homeworld.",
1 )
.RegisterEntry( "You can also manually sort your Individual Collections by drag and drop now.", 1 )
.RegisterEntry( "This new system is a pretty big rework, so please report any discrepancies or bugs you find.", 1 )
.RegisterEntry( "These changes made the specific ownership settings for Retainers and for preferring named over ownership obsolete.", 1 )
.RegisterEntry( "General ownership can still be toggled and should apply in order of: Owned NPC > Owner (if enabled) > General NPC.", 1 )
.RegisterEntry( "Added Dye Previews for in-game dyes and dyeing templates in Material Editing." )
.RegisterEntry( "Added Export buttons to .mdl and .mtrl previews in Advanced Editing." )
.RegisterEntry( "Collection selectors can now be filtered by name." )
.RegisterEntry( "Try to use Unicode normalization before replacing invalid path symbols on import for somewhat nicer paths." )
.RegisterEntry( "Improved interface for group settings (minimally)." )
.RegisterEntry( "Prevent a bug that allowed IPC to add Mods from outside the Penumbra root folder." )
.RegisterEntry( "Improved Support Info somewhat." )
.RegisterEntry( "Fixed a bug when dragging options during mod edit." )
.RegisterEntry( "Fixed a bug where sometimes the valid folder check caused issues." )
.RegisterEntry( "Fixed a bug where the /penumbra enable/disable command displayed the wrong message (functionality unchanged)." )
.RegisterEntry( "A lot of big backend changes." );
private static void Add5_11_1( Changelog log ) private static void Add5_11_1( Changelog log )
=> log.NextVersion( "Version 0.5.11.1" ) => log.NextVersion( "Version 0.5.11.1" )
.RegisterEntry( .RegisterEntry(

View file

@ -63,28 +63,20 @@ public partial class ConfigWindow
Penumbra.Config.HideRedrawBar, v => Penumbra.Config.HideRedrawBar = v ); Penumbra.Config.HideRedrawBar, v => Penumbra.Config.HideRedrawBar = v );
ImGui.Dummy( _window._defaultSpace ); ImGui.Dummy( _window._defaultSpace );
Checkbox( $"Use {AssignedCollections} in Character Window", Checkbox( $"Use {AssignedCollections} in Character Window",
"Use the character collection for your characters name or the Your Character collection in your main character window, if it is set.", "Use the individual collection for your characters name or the Your Character collection in your main character window, if it is set.",
Penumbra.Config.UseCharacterCollectionInMainWindow, v => Penumbra.Config.UseCharacterCollectionInMainWindow = v ); Penumbra.Config.UseCharacterCollectionInMainWindow, v => Penumbra.Config.UseCharacterCollectionInMainWindow = v );
Checkbox( $"Use {AssignedCollections} in Adventurer Cards", Checkbox( $"Use {AssignedCollections} in Adventurer Cards",
"Use the appropriate character collection for the adventurer card you are currently looking at, based on the adventurer's name.", "Use the appropriate individual collection for the adventurer card you are currently looking at, based on the adventurer's name.",
Penumbra.Config.UseCharacterCollectionsInCards, v => Penumbra.Config.UseCharacterCollectionsInCards = v ); Penumbra.Config.UseCharacterCollectionsInCards, v => Penumbra.Config.UseCharacterCollectionsInCards = v );
Checkbox( $"Use {AssignedCollections} in Try-On Window", Checkbox( $"Use {AssignedCollections} in Try-On Window",
"Use the character collection for your character's name in your try-on, dye preview or glamour plate window, if it is set.", "Use the individual collection for your character's name in your try-on, dye preview or glamour plate window, if it is set.",
Penumbra.Config.UseCharacterCollectionInTryOn, v => Penumbra.Config.UseCharacterCollectionInTryOn = v ); Penumbra.Config.UseCharacterCollectionInTryOn, v => Penumbra.Config.UseCharacterCollectionInTryOn = v );
Checkbox( $"Use {AssignedCollections} in Inspect Windows", Checkbox( $"Use {AssignedCollections} in Inspect Windows",
"Use the appropriate character collection for the character you are currently inspecting, based on their name.", "Use the appropriate individual collection for the character you are currently inspecting, based on their name.",
Penumbra.Config.UseCharacterCollectionInInspect, v => Penumbra.Config.UseCharacterCollectionInInspect = v ); Penumbra.Config.UseCharacterCollectionInInspect, v => Penumbra.Config.UseCharacterCollectionInInspect = v );
Checkbox( $"Use {AssignedCollections} based on Ownership", Checkbox( $"Use {AssignedCollections} based on Ownership",
"Use the owner's name to determine the appropriate character collection for mounts, companions and combat pets.", "Use the owner's name to determine the appropriate individual collection for mounts, companions, accessories and combat pets.",
Penumbra.Config.UseOwnerNameForCharacterCollection, v => Penumbra.Config.UseOwnerNameForCharacterCollection = v ); Penumbra.Config.UseOwnerNameForCharacterCollection, v => Penumbra.Config.UseOwnerNameForCharacterCollection = v );
Checkbox( "Prefer Named Collections over Ownership",
"If you have a character collection set to a specific name for a companion or combat pet, prefer this collection over the owners collection.\n"
+ "That is, if you have a 'Topaz Carbuncle' collection, it will use this one instead of the one for its owner.",
Penumbra.Config.PreferNamedCollectionsOverOwners, v => Penumbra.Config.PreferNamedCollectionsOverOwners = v );
Checkbox( $"Use {DefaultCollection} for Housing Retainers",
$"Housing Retainers use the name of their owner instead of their own, you can decide to let them use their owners character collection or the {DefaultCollection}.\n"
+ "It is not possible to make them have their own collection, since they have no connection to their actual name.",
Penumbra.Config.UseDefaultCollectionForRetainers, v => Penumbra.Config.UseDefaultCollectionForRetainers = v );
ImGui.Dummy( _window._defaultSpace ); ImGui.Dummy( _window._defaultSpace );
DrawFolderSortType(); DrawFolderSortType();
DrawAbsoluteSizeSelector(); DrawAbsoluteSizeSelector();

View file

@ -85,6 +85,11 @@ public partial class ConfigWindow
{ {
static bool IsSubPathOf( string basePath, string subPath ) static bool IsSubPathOf( string basePath, string subPath )
{ {
if( basePath.Length == 0 )
{
return false;
}
var rel = Path.GetRelativePath( basePath, subPath ); var rel = Path.GetRelativePath( basePath, subPath );
return rel == "." || !rel.StartsWith( '.' ) && !Path.IsPathRooted( rel ); return rel == "." || !rel.StartsWith( '.' ) && !Path.IsPathRooted( rel );
} }