Rework special actor identification again.

This commit is contained in:
Ottermandias 2022-12-04 16:25:38 +01:00
parent 63a22198aa
commit 9af7e9d948
5 changed files with 55 additions and 37 deletions

View file

@ -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);

View file

@ -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 >();

View file

@ -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,
};
}

View file

@ -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 )
{

View file

@ -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;
}