diff --git a/Penumbra.GameData/Actors/ActorManager.Identifiers.cs b/Penumbra.GameData/Actors/ActorManager.Identifiers.cs index 49af09c1..ad3af449 100644 --- a/Penumbra.GameData/Actors/ActorManager.Identifiers.cs +++ b/Penumbra.GameData/Actors/ActorManager.Identifiers.cs @@ -121,7 +121,8 @@ public partial class ActorManager if (idx is >= (ushort)SpecialActor.CharacterScreen and <= (ushort)SpecialActor.Portrait) return CreateIndividualUnchecked(IdentifierType.Special, ByteString.Empty, idx, ObjectKind.None, uint.MaxValue); - switch ((ObjectKind)actor->ObjectKind) + var kind = (ObjectKind)actor->ObjectKind; + switch (kind) { case ObjectKind.Player: { @@ -193,7 +194,6 @@ public partial class ActorManager var dataId = GetCompanionId(actor, owner); var name = new ByteString(owner->Name); var homeWorld = ((Character*)owner)->HomeWorld; - var kind = (ObjectKind)actor->ObjectKind; return check ? CreateOwned(name, homeWorld, kind, dataId) : CreateIndividualUnchecked(IdentifierType.Owned, name, homeWorld, kind, dataId); diff --git a/Penumbra/Api/PenumbraApi.cs b/Penumbra/Api/PenumbraApi.cs index d9e92eda..49ad61cd 100644 --- a/Penumbra/Api/PenumbraApi.cs +++ b/Penumbra/Api/PenumbraApi.cs @@ -333,7 +333,7 @@ public class PenumbraApi : IDisposable, IPenumbraApi public (string, bool) GetCharacterCollection( string characterName, ushort worldId ) { CheckInitialized(); - return Penumbra.CollectionManager.Individuals.TryGetCollection( NameToIdentifier( characterName, worldId ), out var collection, out _ ) + return Penumbra.CollectionManager.Individuals.TryGetCollection( NameToIdentifier( characterName, worldId ), out var collection ) ? ( collection.Name, true ) : ( Penumbra.CollectionManager.Default.Name, false ); } @@ -807,7 +807,7 @@ public class PenumbraApi : IDisposable, IPenumbraApi { CheckInitialized(); var identifier = NameToIdentifier( characterName, worldId ); - var collection = Penumbra.TempMods.Collections.TryGetCollection( identifier, out var c, out _ ) + var collection = Penumbra.TempMods.Collections.TryGetCollection( identifier, out var c ) ? c : Penumbra.CollectionManager.Individual( identifier ); var set = collection.MetaCache?.Manipulations.ToArray() ?? Array.Empty< MetaManipulation >(); diff --git a/Penumbra/Collections/CollectionManager.Active.cs b/Penumbra/Collections/CollectionManager.Active.cs index 7f23eae0..355c9297 100644 --- a/Penumbra/Collections/CollectionManager.Active.cs +++ b/Penumbra/Collections/CollectionManager.Active.cs @@ -42,7 +42,7 @@ public partial class ModCollection public readonly IndividualCollections Individuals = new(Penumbra.Actors); public ModCollection Individual( ActorIdentifier identifier ) - => Individuals.TryGetCollection( identifier, out var c, out _ ) ? c : Default; + => Individuals.TryGetCollection( identifier, out var c ) ? c : Default; // Special Collections private readonly ModCollection?[] _specialCollections = new ModCollection?[Enum.GetValues< CollectionType >().Length - 4]; @@ -64,7 +64,7 @@ public partial class ModCollection CollectionType.Default => Default, CollectionType.Interface => Interface, CollectionType.Current => Current, - CollectionType.Individual => identifier.IsValid ? Individuals.TryGetCollection( identifier, out var c, out _ ) ? c : null : null, + CollectionType.Individual => identifier.IsValid ? Individuals.TryGetCollection( identifier, out var c ) ? c : null : null, _ => null, }; } diff --git a/Penumbra/Collections/IndividualCollections.Access.cs b/Penumbra/Collections/IndividualCollections.Access.cs index 79561243..1c02c19c 100644 --- a/Penumbra/Collections/IndividualCollections.Access.cs +++ b/Penumbra/Collections/IndividualCollections.Access.cs @@ -23,9 +23,8 @@ public sealed partial class IndividualCollections : IReadOnlyList< (string Displ public (string DisplayName, ModCollection Collection) this[ int index ] => ( _assignments[ index ].DisplayName, _assignments[ index ].Collection ); - public bool TryGetCollection( ActorIdentifier identifier, [NotNullWhen( true )] out ModCollection? collection, out ActorIdentifier specialIdentifier ) + public bool TryGetCollection( ActorIdentifier identifier, [NotNullWhen( true )] out ModCollection? collection ) { - specialIdentifier = ActorIdentifier.Invalid; if( Count == 0 ) { collection = null; @@ -72,35 +71,53 @@ public sealed partial class IndividualCollections : IReadOnlyList< (string Displ return false; } - case IdentifierType.Npc: return _individuals.TryGetValue( identifier, out collection ); - case IdentifierType.Special: - switch( identifier.Special ) - { - case SpecialActor.CharacterScreen when Penumbra.Config.UseCharacterCollectionInMainWindow: - case SpecialActor.FittingRoom when Penumbra.Config.UseCharacterCollectionInTryOn: - case SpecialActor.DyePreview when Penumbra.Config.UseCharacterCollectionInTryOn: - case SpecialActor.Portrait when Penumbra.Config.UseCharacterCollectionsInCards: - return CheckWorlds( specialIdentifier = _actorManager.GetCurrentPlayer(), out collection ); - case SpecialActor.ExamineScreen: - { - return CheckWorlds( specialIdentifier = _actorManager.GetInspectPlayer(), out collection! ) - || CheckWorlds( specialIdentifier = _actorManager.GetCardPlayer(), out collection! ) - || CheckWorlds( specialIdentifier = _actorManager.GetGlamourPlayer(), out collection! ); - } - } - - break; + case IdentifierType.Npc: return _individuals.TryGetValue( identifier, out collection ); + case IdentifierType.Special: return CheckWorlds( ConvertSpecialIdentifier( identifier ), out collection ); } collection = null; return false; } - public bool TryGetCollection( GameObject? gameObject, out ModCollection? collection, out ActorIdentifier specialIdentifier ) - => TryGetCollection( _actorManager.FromObject( gameObject, false ), out collection, out specialIdentifier ); + public ActorIdentifier ConvertSpecialIdentifier( ActorIdentifier identifier ) + { + if( identifier.Type != IdentifierType.Special ) + { + return identifier; + } - public unsafe bool TryGetCollection( FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject* gameObject, out ModCollection? collection, out ActorIdentifier specialIdentifier ) - => TryGetCollection( _actorManager.FromObject( gameObject, out _, false ), out collection, out specialIdentifier ); + switch( identifier.Special ) + { + case SpecialActor.CharacterScreen when Penumbra.Config.UseCharacterCollectionInMainWindow: + case SpecialActor.FittingRoom when Penumbra.Config.UseCharacterCollectionInTryOn: + case SpecialActor.DyePreview when Penumbra.Config.UseCharacterCollectionInTryOn: + case SpecialActor.Portrait when Penumbra.Config.UseCharacterCollectionsInCards: + return _actorManager.GetCurrentPlayer(); + case SpecialActor.ExamineScreen: + { + identifier = _actorManager.GetInspectPlayer(); + if( identifier.IsValid ) + { + return identifier; + } + + identifier = _actorManager.GetCardPlayer(); + if( identifier.IsValid ) + { + return identifier; + } + + return _actorManager.GetGlamourPlayer(); + } + default: return identifier; + } + } + + public bool TryGetCollection( GameObject? gameObject, out ModCollection? collection ) + => TryGetCollection( _actorManager.FromObject( gameObject, false ), out collection ); + + public unsafe bool TryGetCollection( FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject* gameObject, out ModCollection? collection ) + => TryGetCollection( _actorManager.FromObject( gameObject, out _, false ), out collection ); private bool CheckWorlds( ActorIdentifier identifier, out ModCollection? collection ) { diff --git a/Penumbra/Interop/Resolver/PathResolver.Identification.cs b/Penumbra/Interop/Resolver/PathResolver.Identification.cs index 973fad13..9b0e04b8 100644 --- a/Penumbra/Interop/Resolver/PathResolver.Identification.cs +++ b/Penumbra/Interop/Resolver/PathResolver.Identification.cs @@ -44,8 +44,9 @@ public unsafe partial class PathResolver else { var identifier = Penumbra.Actors.FromObject( gameObject, out var owner, false ); - var collection = CollectionByIdentifier( identifier, out var specialIdentifier ) - ?? CheckYourself( identifier.Type == IdentifierType.Special ? specialIdentifier : identifier, gameObject ) + identifier = Penumbra.CollectionManager.Individuals.ConvertSpecialIdentifier( identifier ); + var collection = CollectionByIdentifier( identifier ) + ?? CheckYourself( identifier, gameObject ) ?? CollectionByAttributes( gameObject ) ?? CheckOwnedCollection( identifier, owner ) ?? Penumbra.CollectionManager.Default; @@ -71,16 +72,16 @@ public unsafe partial class PathResolver } var player = Penumbra.Actors.GetCurrentPlayer(); - return CollectionByIdentifier( player, out _ ) + return CollectionByIdentifier( player ) ?? CheckYourself( player, gameObject ) ?? CollectionByAttributes( gameObject ) ?? Penumbra.CollectionManager.Default; } // Check both temporary and permanent character collections. Temporary first. - private static ModCollection? CollectionByIdentifier( ActorIdentifier identifier, out ActorIdentifier specialIdentifier ) - => Penumbra.TempMods.Collections.TryGetCollection( identifier, out var collection, out specialIdentifier ) - || Penumbra.CollectionManager.Individuals.TryGetCollection( identifier, out collection, out specialIdentifier ) + private static ModCollection? CollectionByIdentifier( ActorIdentifier identifier ) + => Penumbra.TempMods.Collections.TryGetCollection( identifier, out var collection ) + || Penumbra.CollectionManager.Individuals.TryGetCollection( identifier, out collection ) ? collection : null; @@ -143,7 +144,7 @@ public unsafe partial class PathResolver { var sheet = gameData.GetExcelSheet< ModelChara >()!; var ret = new BitArray( ( int )sheet.RowCount, false ); - foreach( var (row, idx) in sheet.WithIndex().Where( p => p.Value.Type == ( byte )CharacterBase.ModelType.Human ) ) + foreach( var (_, idx) in sheet.WithIndex().Where( p => p.Value.Type == ( byte )CharacterBase.ModelType.Human ) ) { ret[ idx ] = true; }