mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 10:17:22 +01:00
fix a crash on non-ascii file paths, sqpack file swapping
This commit is contained in:
parent
21758a8c85
commit
76269ba64a
6 changed files with 71 additions and 15 deletions
|
|
@ -1,3 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Penumbra.Models
|
||||
{
|
||||
public class ModMeta
|
||||
|
|
@ -5,5 +7,7 @@ namespace Penumbra.Models
|
|||
public string Name { get; set; }
|
||||
public string Author { get; set; }
|
||||
public string Description { get; set; }
|
||||
|
||||
public Dictionary< string, string > FileSwaps { get; } = new();
|
||||
}
|
||||
}
|
||||
|
|
@ -7,11 +7,10 @@ namespace Penumbra.Mods
|
|||
public class ModManager
|
||||
{
|
||||
public readonly Dictionary< string, FileInfo > ResolvedFiles = new();
|
||||
public readonly Dictionary< string, string > SwappedFiles = new();
|
||||
|
||||
public ModCollection Mods { get; set; }
|
||||
|
||||
public ResourceMod[] AvailableMods => Mods?.EnabledMods;
|
||||
|
||||
private DirectoryInfo _basePath;
|
||||
|
||||
public void DiscoverMods()
|
||||
|
|
@ -81,6 +80,20 @@ namespace Penumbra.Mods
|
|||
mod.AddConflict( modName, path );
|
||||
}
|
||||
}
|
||||
|
||||
foreach( var swap in mod.Meta.FileSwaps )
|
||||
{
|
||||
// just assume people put not fucked paths in here lol
|
||||
if( !SwappedFiles.ContainsKey( swap.Value ) )
|
||||
{
|
||||
SwappedFiles[ swap.Key ] = swap.Value;
|
||||
registeredFiles[ swap.Key ] = mod.Meta.Name;
|
||||
}
|
||||
else if( registeredFiles.TryGetValue( swap.Key, out var modName ) )
|
||||
{
|
||||
mod.AddConflict( modName, swap.Key );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -99,7 +112,23 @@ namespace Penumbra.Mods
|
|||
|
||||
public FileInfo GetCandidateForGameFile( string resourcePath )
|
||||
{
|
||||
return ResolvedFiles.TryGetValue( resourcePath.ToLowerInvariant(), out var fileInfo ) ? fileInfo : null;
|
||||
var val = ResolvedFiles.TryGetValue( resourcePath.ToLowerInvariant(), out var candidate );
|
||||
if( !val )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if( candidate.FullName.Length >= 260 || !candidate.Exists )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return candidate;
|
||||
}
|
||||
|
||||
public string GetSwappedFilePath( string originalPath )
|
||||
{
|
||||
return SwappedFiles.TryGetValue( originalPath, out var swappedPath ) ? swappedPath : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -13,7 +13,7 @@ namespace Penumbra.Mods
|
|||
|
||||
public List< FileInfo > ModFiles { get; } = new();
|
||||
|
||||
public Dictionary< string, List< string > > FileConflicts { get; set; } = new();
|
||||
public Dictionary< string, List< string > > FileConflicts { get; } = new();
|
||||
|
||||
public void RefreshModFiles()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -23,27 +23,27 @@
|
|||
|
||||
<ItemGroup>
|
||||
<Reference Include="Dalamud">
|
||||
<HintPath>$(DALAMUD_ROOT)\Dalamud.dll</HintPath>
|
||||
<HintPath>..\libs\Dalamud.dll</HintPath>
|
||||
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\Dalamud.dll</HintPath>
|
||||
<HintPath>$(DALAMUD_ROOT)\Dalamud.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="ImGui.NET">
|
||||
<HintPath>$(DALAMUD_ROOT)\ImGui.NET.dll</HintPath>
|
||||
<HintPath>..\libs\ImGui.NET.dll</HintPath>
|
||||
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\ImGui.NET.dll</HintPath>
|
||||
<HintPath>$(DALAMUD_ROOT)\ImGui.NET.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="ImGuiScene">
|
||||
<HintPath>$(DALAMUD_ROOT)\ImGuiScene.dll</HintPath>
|
||||
<HintPath>..\libs\ImGuiScene.dll</HintPath>
|
||||
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\ImGuiScene.dll</HintPath>
|
||||
<HintPath>$(DALAMUD_ROOT)\ImGuiScene.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Lumina">
|
||||
<HintPath>$(DALAMUD_ROOT)\Lumina.dll</HintPath>
|
||||
<HintPath>..\libs\Lumina.dll</HintPath>
|
||||
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\Lumina.dll</HintPath>
|
||||
<HintPath>$(DALAMUD_ROOT)\Lumina.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
|
|
|||
|
|
@ -158,23 +158,27 @@ namespace Penumbra
|
|||
PluginLog.Log( "[GetResourceHandler] {0}", gameFsPath );
|
||||
}
|
||||
|
||||
|
||||
var candidate = Plugin.ModManager.GetCandidateForGameFile( gameFsPath );
|
||||
var swappedFilePath = Plugin.ModManager.GetSwappedFilePath( gameFsPath );
|
||||
|
||||
var path = candidate?.FullName ?? swappedFilePath;
|
||||
|
||||
// path must be < 260 because statically defined array length :(
|
||||
if( candidate == null || candidate.FullName.Length >= 260 || !candidate.Exists )
|
||||
if( path == null || path.Length < 260 )
|
||||
{
|
||||
return CallOriginalHandler( isSync, pFileManager, pCategoryId, pResourceType, pResourceHash, pPath, pUnknown, isUnknown );
|
||||
}
|
||||
|
||||
var cleanPath = candidate.FullName.Replace( '\\', '/' );
|
||||
var asciiPath = Encoding.ASCII.GetBytes( cleanPath );
|
||||
var cleanPath = path.Replace( '\\', '/' );
|
||||
var utfPath = Encoding.UTF8.GetBytes( cleanPath );
|
||||
|
||||
var bPath = stackalloc byte[asciiPath.Length + 1];
|
||||
Marshal.Copy( asciiPath, 0, new IntPtr( bPath ), asciiPath.Length );
|
||||
var bPath = stackalloc byte[utfPath.Length + 1];
|
||||
Marshal.Copy( utfPath, 0, new IntPtr( bPath ), utfPath.Length );
|
||||
pPath = ( char* )bPath;
|
||||
|
||||
Crc32.Init();
|
||||
Crc32.Update( asciiPath );
|
||||
Crc32.Update( utfPath );
|
||||
*pResourceHash = Crc32.Checksum;
|
||||
|
||||
return CallOriginalHandler( isSync, pFileManager, pCategoryId, pResourceType, pResourceHash, pPath, pUnknown, isUnknown );
|
||||
|
|
@ -198,7 +202,7 @@ namespace Penumbra
|
|||
|
||||
pFileDesc->FileMode = FileMode.LoadUnpackedResource;
|
||||
|
||||
var utfPath = Encoding.Unicode.GetBytes( gameFsPath );
|
||||
var utfPath = Encoding.UTF8.GetBytes( gameFsPath );
|
||||
|
||||
Marshal.Copy( utfPath, 0, new IntPtr( &pFileDesc->UtfFileName ), utfPath.Length );
|
||||
|
||||
|
|
|
|||
|
|
@ -414,6 +414,25 @@ namespace Penumbra.UI
|
|||
ImGui.EndTabItem();
|
||||
}
|
||||
|
||||
if( _selectedMod.Mod.Meta.FileSwaps.Any() )
|
||||
{
|
||||
if( ImGui.BeginTabItem( "File Swaps" ) )
|
||||
{
|
||||
ImGui.SetNextItemWidth( -1 );
|
||||
if( ImGui.ListBoxHeader( "##", AutoFillSize ) )
|
||||
{
|
||||
foreach( var file in _selectedMod.Mod.Meta.FileSwaps )
|
||||
{
|
||||
// todo: fucking gross alloc every frame * items
|
||||
ImGui.Selectable( $"{file.Key} -> {file.Value}" );
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.ListBoxFooter();
|
||||
ImGui.EndTabItem();
|
||||
}
|
||||
}
|
||||
|
||||
if( _selectedMod.Mod.FileConflicts.Any() )
|
||||
{
|
||||
if( ImGui.BeginTabItem( "File Conflicts" ) )
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue