mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-13 12:14:17 +01:00
Add ResolvePlayerPaths.
This commit is contained in:
parent
58c74e839c
commit
fe561f39c2
6 changed files with 126 additions and 37 deletions
|
|
@ -1 +1 @@
|
||||||
Subproject commit b65f0a4e2a761a3142a07587a6c0f8657f1361ee
|
Subproject commit 97dc16ba32bf78c4d3a4d210a08010cd6d4eec3c
|
||||||
|
|
@ -678,6 +678,32 @@ public class IpcTester : IDisposable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DrawIntro( Ipc.ResolvePlayerPaths.Label, "Resolved Paths (Player)" );
|
||||||
|
if( _currentResolvePath.Length > 0 || _currentReversePath.Length > 0 )
|
||||||
|
{
|
||||||
|
var forwardArray = _currentResolvePath.Length > 0 ? new[] { _currentResolvePath } : Array.Empty< string >();
|
||||||
|
var reverseArray = _currentReversePath.Length > 0 ? new[] { _currentReversePath } : Array.Empty< string >();
|
||||||
|
var ret = Ipc.ResolvePlayerPaths.Subscriber( _pi ).Invoke( forwardArray, reverseArray );
|
||||||
|
var text = string.Empty;
|
||||||
|
if( ret.Item1.Length > 0 )
|
||||||
|
{
|
||||||
|
if( ret.Item2.Length > 0 )
|
||||||
|
{
|
||||||
|
text = $"Forward: {ret.Item1[ 0 ]} | Reverse: {string.Join( "; ", ret.Item2[ 0 ] )}.";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
text = $"Forward: {ret.Item1[ 0 ]}.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( ret.Item2.Length > 0 )
|
||||||
|
{
|
||||||
|
text = $"Reverse: {string.Join( "; ", ret.Item2[ 0 ] )}.";
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.TextUnformatted( text );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -766,8 +792,11 @@ public class IpcTester : IDisposable
|
||||||
{
|
{
|
||||||
( _returnCode, _oldCollection ) = Ipc.SetCollectionForObject.Subscriber( _pi ).Invoke( _objectIdx, _collectionName, _allowCreation, _allowDeletion );
|
( _returnCode, _oldCollection ) = Ipc.SetCollectionForObject.Subscriber( _pi ).Invoke( _objectIdx, _collectionName, _allowCreation, _allowDeletion );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( _returnCode == PenumbraApiEc.NothingChanged && _oldCollection.IsNullOrEmpty() )
|
if( _returnCode == PenumbraApiEc.NothingChanged && _oldCollection.IsNullOrEmpty() )
|
||||||
|
{
|
||||||
_oldCollection = null;
|
_oldCollection = null;
|
||||||
|
}
|
||||||
|
|
||||||
DrawIntro( Ipc.GetChangedItems.Label, "Changed Item List" );
|
DrawIntro( Ipc.GetChangedItems.Label, "Changed Item List" );
|
||||||
ImGui.SetNextItemWidth( 200 * ImGuiHelpers.GlobalScale );
|
ImGui.SetNextItemWidth( 200 * ImGuiHelpers.GlobalScale );
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ using System.Diagnostics.CodeAnalysis;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using Penumbra.Api.Enums;
|
using Penumbra.Api.Enums;
|
||||||
using Penumbra.GameData.Actors;
|
using Penumbra.GameData.Actors;
|
||||||
using Penumbra.String;
|
using Penumbra.String;
|
||||||
|
|
@ -23,7 +24,7 @@ namespace Penumbra.Api;
|
||||||
public class PenumbraApi : IDisposable, IPenumbraApi
|
public class PenumbraApi : IDisposable, IPenumbraApi
|
||||||
{
|
{
|
||||||
public (int, int) ApiVersion
|
public (int, int) ApiVersion
|
||||||
=> ( 4, 18 );
|
=> ( 4, 19 );
|
||||||
|
|
||||||
private Penumbra? _penumbra;
|
private Penumbra? _penumbra;
|
||||||
private Lumina.GameData? _lumina;
|
private Lumina.GameData? _lumina;
|
||||||
|
|
@ -271,6 +272,20 @@ public class PenumbraApi : IDisposable, IPenumbraApi
|
||||||
return ret.Select( r => r.ToString() ).ToArray();
|
return ret.Select( r => r.ToString() ).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public (string[], string[][]) ResolvePlayerPaths( string[] forward, string[] reverse )
|
||||||
|
{
|
||||||
|
CheckInitialized();
|
||||||
|
if( !Penumbra.Config.EnableMods )
|
||||||
|
{
|
||||||
|
return ( forward, reverse.Select( p => new[] { p } ).ToArray() );
|
||||||
|
}
|
||||||
|
|
||||||
|
var playerCollection = PathResolver.PlayerCollection();
|
||||||
|
var resolved = forward.Select( p => ResolvePath( p, Penumbra.ModManager, playerCollection ) ).ToArray();
|
||||||
|
var reverseResolved = playerCollection.ReverseResolvePaths( reverse );
|
||||||
|
return ( resolved, reverseResolved.Select( a => a.Select( p => p.ToString() ).ToArray() ).ToArray() );
|
||||||
|
}
|
||||||
|
|
||||||
public T? GetFile< T >( string gamePath ) where T : FileResource
|
public T? GetFile< T >( string gamePath ) where T : FileResource
|
||||||
=> GetFileIntern< T >( ResolveDefaultPath( gamePath ) );
|
=> GetFileIntern< T >( ResolveDefaultPath( gamePath ) );
|
||||||
|
|
||||||
|
|
@ -306,17 +321,21 @@ public class PenumbraApi : IDisposable, IPenumbraApi
|
||||||
{
|
{
|
||||||
CheckInitialized();
|
CheckInitialized();
|
||||||
if( !Enum.IsDefined( type ) )
|
if( !Enum.IsDefined( type ) )
|
||||||
|
{
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
var collection = Penumbra.CollectionManager.ByType( ( CollectionType )type );
|
var collection = Penumbra.CollectionManager.ByType( ( CollectionType )type );
|
||||||
return collection?.Name ?? string.Empty;
|
return collection?.Name ?? string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
public (PenumbraApiEc, string OldCollection) SetCollectionForType( Enums.ApiCollectionType type, string collectionName, bool allowCreateNew, bool allowDelete )
|
public (PenumbraApiEc, string OldCollection) SetCollectionForType( ApiCollectionType type, string collectionName, bool allowCreateNew, bool allowDelete )
|
||||||
{
|
{
|
||||||
CheckInitialized();
|
CheckInitialized();
|
||||||
if( !Enum.IsDefined( type ) )
|
if( !Enum.IsDefined( type ) )
|
||||||
|
{
|
||||||
return ( PenumbraApiEc.InvalidArgument, string.Empty );
|
return ( PenumbraApiEc.InvalidArgument, string.Empty );
|
||||||
|
}
|
||||||
|
|
||||||
var oldCollection = Penumbra.CollectionManager.ByType( ( CollectionType )type )?.Name ?? string.Empty;
|
var oldCollection = Penumbra.CollectionManager.ByType( ( CollectionType )type )?.Name ?? string.Empty;
|
||||||
|
|
||||||
|
|
@ -327,7 +346,7 @@ public class PenumbraApi : IDisposable, IPenumbraApi
|
||||||
return ( PenumbraApiEc.NothingChanged, oldCollection );
|
return ( PenumbraApiEc.NothingChanged, oldCollection );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !allowDelete || type is Enums.ApiCollectionType.Current or Enums.ApiCollectionType.Default or Enums.ApiCollectionType.Interface )
|
if( !allowDelete || type is ApiCollectionType.Current or ApiCollectionType.Default or ApiCollectionType.Interface )
|
||||||
{
|
{
|
||||||
return ( PenumbraApiEc.AssignmentDeletionDisallowed, oldCollection );
|
return ( PenumbraApiEc.AssignmentDeletionDisallowed, oldCollection );
|
||||||
}
|
}
|
||||||
|
|
@ -399,6 +418,7 @@ public class PenumbraApi : IDisposable, IPenumbraApi
|
||||||
{
|
{
|
||||||
return ( PenumbraApiEc.AssignmentDeletionDisallowed, oldCollection );
|
return ( PenumbraApiEc.AssignmentDeletionDisallowed, oldCollection );
|
||||||
}
|
}
|
||||||
|
|
||||||
var idx = Penumbra.CollectionManager.Individuals.Index( id );
|
var idx = Penumbra.CollectionManager.Individuals.Index( id );
|
||||||
Penumbra.CollectionManager.RemoveIndividualCollection( idx );
|
Penumbra.CollectionManager.RemoveIndividualCollection( idx );
|
||||||
return ( PenumbraApiEc.Success, oldCollection );
|
return ( PenumbraApiEc.Success, oldCollection );
|
||||||
|
|
@ -983,6 +1003,7 @@ public class PenumbraApi : IDisposable, IPenumbraApi
|
||||||
=> ChangedItemClicked?.Invoke( button, it );
|
=> ChangedItemClicked?.Invoke( button, it );
|
||||||
|
|
||||||
|
|
||||||
|
[MethodImpl( MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization )]
|
||||||
private void CheckInitialized()
|
private void CheckInitialized()
|
||||||
{
|
{
|
||||||
if( !Valid )
|
if( !Valid )
|
||||||
|
|
@ -993,6 +1014,7 @@ public class PenumbraApi : IDisposable, IPenumbraApi
|
||||||
|
|
||||||
// Return the collection associated to a current game object. If it does not exist, return the default collection.
|
// Return the collection associated to a current game object. If it does not exist, return the default collection.
|
||||||
// If the index is invalid, returns false and the default collection.
|
// If the index is invalid, returns false and the default collection.
|
||||||
|
[MethodImpl( MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization )]
|
||||||
private static unsafe bool AssociatedCollection( int gameObjectIdx, out ModCollection collection )
|
private static unsafe bool AssociatedCollection( int gameObjectIdx, out ModCollection collection )
|
||||||
{
|
{
|
||||||
collection = Penumbra.CollectionManager.Default;
|
collection = Penumbra.CollectionManager.Default;
|
||||||
|
|
@ -1011,17 +1033,20 @@ public class PenumbraApi : IDisposable, IPenumbraApi
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl( MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization )]
|
||||||
private static unsafe ActorIdentifier AssociatedIdentifier( int gameObjectIdx )
|
private static unsafe ActorIdentifier AssociatedIdentifier( int gameObjectIdx )
|
||||||
{
|
{
|
||||||
if( gameObjectIdx < 0 || gameObjectIdx >= Dalamud.Objects.Length )
|
if( gameObjectIdx < 0 || gameObjectIdx >= Dalamud.Objects.Length )
|
||||||
{
|
{
|
||||||
return ActorIdentifier.Invalid;
|
return ActorIdentifier.Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
var ptr = ( FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject* )Dalamud.Objects.GetObjectAddress( gameObjectIdx );
|
var ptr = ( FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject* )Dalamud.Objects.GetObjectAddress( gameObjectIdx );
|
||||||
return Penumbra.Actors.FromObject( ptr, out _, false, true );
|
return Penumbra.Actors.FromObject( ptr, out _, false, true );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve a path given by string for a specific collection.
|
// Resolve a path given by string for a specific collection.
|
||||||
|
[MethodImpl( MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization )]
|
||||||
private static string ResolvePath( string path, Mod.Manager _, ModCollection collection )
|
private static string ResolvePath( string path, Mod.Manager _, ModCollection collection )
|
||||||
{
|
{
|
||||||
if( !Penumbra.Config.EnableMods )
|
if( !Penumbra.Config.EnableMods )
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@ public class PenumbraIpcProviders : IDisposable
|
||||||
internal readonly FuncProvider< string, string, string[] > ReverseResolvePath;
|
internal readonly FuncProvider< string, string, string[] > ReverseResolvePath;
|
||||||
internal readonly FuncProvider< string, int, string[] > ReverseResolveGameObjectPath;
|
internal readonly FuncProvider< string, int, string[] > ReverseResolveGameObjectPath;
|
||||||
internal readonly FuncProvider< string, string[] > ReverseResolvePlayerPath;
|
internal readonly FuncProvider< string, string[] > ReverseResolvePlayerPath;
|
||||||
|
internal readonly FuncProvider< string[], string[], (string[], string[][]) > ResolvePlayerPaths;
|
||||||
|
|
||||||
// Collections
|
// Collections
|
||||||
internal readonly FuncProvider< IList< string > > GetCollections;
|
internal readonly FuncProvider< IList< string > > GetCollections;
|
||||||
|
|
@ -160,6 +161,7 @@ public class PenumbraIpcProviders : IDisposable
|
||||||
ReverseResolvePath = Ipc.ReverseResolvePath.Provider( pi, Api.ReverseResolvePath );
|
ReverseResolvePath = Ipc.ReverseResolvePath.Provider( pi, Api.ReverseResolvePath );
|
||||||
ReverseResolveGameObjectPath = Ipc.ReverseResolveGameObjectPath.Provider( pi, Api.ReverseResolveGameObjectPath );
|
ReverseResolveGameObjectPath = Ipc.ReverseResolveGameObjectPath.Provider( pi, Api.ReverseResolveGameObjectPath );
|
||||||
ReverseResolvePlayerPath = Ipc.ReverseResolvePlayerPath.Provider( pi, Api.ReverseResolvePlayerPath );
|
ReverseResolvePlayerPath = Ipc.ReverseResolvePlayerPath.Provider( pi, Api.ReverseResolvePlayerPath );
|
||||||
|
ResolvePlayerPaths = Ipc.ResolvePlayerPaths.Provider( pi, Api.ResolvePlayerPaths );
|
||||||
|
|
||||||
// Collections
|
// Collections
|
||||||
GetCollections = Ipc.GetCollections.Provider( pi, Api.GetCollections );
|
GetCollections = Ipc.GetCollections.Provider( pi, Api.GetCollections );
|
||||||
|
|
@ -263,6 +265,7 @@ public class PenumbraIpcProviders : IDisposable
|
||||||
ReverseResolvePath.Dispose();
|
ReverseResolvePath.Dispose();
|
||||||
ReverseResolveGameObjectPath.Dispose();
|
ReverseResolveGameObjectPath.Dispose();
|
||||||
ReverseResolvePlayerPath.Dispose();
|
ReverseResolvePlayerPath.Dispose();
|
||||||
|
ResolvePlayerPaths.Dispose();
|
||||||
|
|
||||||
// Collections
|
// Collections
|
||||||
GetCollections.Dispose();
|
GetCollections.Dispose();
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ using Penumbra.Meta.Manager;
|
||||||
using Penumbra.Mods;
|
using Penumbra.Mods;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Penumbra.Interop;
|
using Penumbra.Interop;
|
||||||
|
|
@ -68,6 +69,9 @@ public partial class ModCollection
|
||||||
public IEnumerable< Utf8GamePath > ReverseResolvePath( FullPath path )
|
public IEnumerable< Utf8GamePath > ReverseResolvePath( FullPath path )
|
||||||
=> _cache?.ReverseResolvePath( path ) ?? Array.Empty< Utf8GamePath >();
|
=> _cache?.ReverseResolvePath( path ) ?? Array.Empty< Utf8GamePath >();
|
||||||
|
|
||||||
|
public HashSet< Utf8GamePath >[] ReverseResolvePaths( string[] paths )
|
||||||
|
=> _cache?.ReverseResolvePaths( paths ) ?? paths.Select( _ => new HashSet< Utf8GamePath >() ).ToArray();
|
||||||
|
|
||||||
public FullPath? ResolvePath( Utf8GamePath path )
|
public FullPath? ResolvePath( Utf8GamePath path )
|
||||||
=> _cache?.ResolvePath( path );
|
=> _cache?.ResolvePath( path );
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ using Penumbra.Meta.Manipulations;
|
||||||
using Penumbra.Mods;
|
using Penumbra.Mods;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Penumbra.Api.Enums;
|
using Penumbra.Api.Enums;
|
||||||
using Penumbra.String.Classes;
|
using Penumbra.String.Classes;
|
||||||
|
|
@ -104,6 +105,33 @@ public partial class ModCollection
|
||||||
return iterator;
|
return iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reverse resolve multiple paths at once for efficiency.
|
||||||
|
public HashSet< Utf8GamePath >[] ReverseResolvePaths( IReadOnlyCollection< string > fullPaths )
|
||||||
|
{
|
||||||
|
if( fullPaths.Count == 0 )
|
||||||
|
return Array.Empty< HashSet< Utf8GamePath > >();
|
||||||
|
|
||||||
|
var ret = new HashSet< Utf8GamePath >[fullPaths.Count];
|
||||||
|
var dict = new Dictionary< FullPath, int >( fullPaths.Count );
|
||||||
|
foreach( var (path, idx) in fullPaths.WithIndex() )
|
||||||
|
{
|
||||||
|
dict[ new FullPath(path) ] = idx;
|
||||||
|
ret[ idx ] = !Path.IsPathRooted( path ) && Utf8GamePath.FromString( path, out var utf8 )
|
||||||
|
? new HashSet< Utf8GamePath > { utf8 }
|
||||||
|
: new HashSet< Utf8GamePath >();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach( var (game, full) in ResolvedFiles )
|
||||||
|
{
|
||||||
|
if( dict.TryGetValue( full.Path, out var idx ) )
|
||||||
|
{
|
||||||
|
ret[ idx ].Add( game );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
private void OnModSettingChange( ModSettingChange type, int modIdx, int oldValue, int groupIdx, bool _ )
|
private void OnModSettingChange( ModSettingChange type, int modIdx, int oldValue, int groupIdx, bool _ )
|
||||||
{
|
{
|
||||||
switch( type )
|
switch( type )
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue