mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 10:17:22 +01:00
cleanup some garbage, make loading less brittle
This commit is contained in:
parent
729ef7fea7
commit
00af098d66
4 changed files with 129 additions and 113 deletions
|
|
@ -54,13 +54,13 @@ namespace Penumbra.Importer
|
|||
{
|
||||
case ".ttmp":
|
||||
ImportV1ModPack( modPackFile );
|
||||
return;
|
||||
break;
|
||||
|
||||
case ".ttmp2":
|
||||
ImportV2ModPack( modPackFile );
|
||||
return;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new ArgumentException( $"Unrecognized modpack format: {modPackFile.Extension}", nameof(modPackFile) );
|
||||
}
|
||||
|
||||
|
|
@ -249,13 +249,13 @@ namespace Penumbra.Importer
|
|||
OptionFiles = new Dictionary<string, HashSet<string>>()
|
||||
};
|
||||
var optDir = new DirectoryInfo(Path.Combine( groupFolder.FullName, opt.Name));
|
||||
if (optDir.Exists)
|
||||
if (optDir.Exists)
|
||||
{
|
||||
foreach ( var file in optDir.EnumerateFiles("*.*", SearchOption.AllDirectories) )
|
||||
{
|
||||
optio.AddFile(file.FullName.Substring(baseFolder.FullName.Length).TrimStart('\\'), file.FullName.Substring(optDir.FullName.Length).TrimStart('\\').Replace('\\','/'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Inf.Options.Add( optio );
|
||||
}
|
||||
meta.Groups.Add( group.GroupName, Inf );
|
||||
|
|
|
|||
|
|
@ -65,6 +65,11 @@ namespace Penumbra.Mods
|
|||
}
|
||||
|
||||
var meta = ModMeta.LoadFromFile( metaFile.FullName );
|
||||
if( meta == null )
|
||||
{
|
||||
PluginLog.LogError( "mod meta is invalid for resource mod: {ResourceModFile}", metaFile.FullName );
|
||||
continue;
|
||||
}
|
||||
|
||||
var mod = new ResourceMod
|
||||
{
|
||||
|
|
|
|||
|
|
@ -99,9 +99,6 @@ namespace Penumbra.Mods
|
|||
Mods.Save();
|
||||
|
||||
CalculateEffectiveFileList();
|
||||
|
||||
// Needed to reload body textures with mods
|
||||
//_plugin.GameUtils.ReloadPlayerResources();
|
||||
}
|
||||
|
||||
public void CalculateEffectiveFileList()
|
||||
|
|
@ -114,115 +111,133 @@ namespace Penumbra.Mods
|
|||
foreach( var (mod, settings) in Mods.GetOrderedAndEnabledModListWithSettings( _plugin.Configuration.InvertModListOrder ) )
|
||||
{
|
||||
mod.FileConflicts?.Clear();
|
||||
|
||||
// fixup path
|
||||
var baseDir = mod.ModBasePath.FullName;
|
||||
|
||||
if( settings.Conf == null )
|
||||
{
|
||||
settings.Conf = new();
|
||||
_plugin.ModManager.Mods.Save();
|
||||
}
|
||||
|
||||
foreach( var file in mod.ModFiles )
|
||||
{
|
||||
var relativeFilePath = file.FullName.Substring( baseDir.Length ).TrimStart( '\\' );
|
||||
|
||||
bool doNotAdd = false;
|
||||
|
||||
void AddFiles( HashSet< string > gamePaths )
|
||||
{
|
||||
doNotAdd = true;
|
||||
foreach( var gamePath in gamePaths )
|
||||
{
|
||||
if( !ResolvedFiles.ContainsKey( gamePath ) )
|
||||
{
|
||||
ResolvedFiles[ gamePath.ToLowerInvariant() ] = file;
|
||||
registeredFiles[ gamePath ] = mod.Meta.Name;
|
||||
}
|
||||
else if( registeredFiles.TryGetValue( gamePath, out var modName ) )
|
||||
{
|
||||
mod.AddConflict( modName, gamePath );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HashSet< string > paths;
|
||||
foreach( var group in mod.Meta.Groups.Select( G => G.Value ) )
|
||||
{
|
||||
if( !settings.Conf.TryGetValue( group.GroupName, out var setting )
|
||||
|| ( group.SelectionType == SelectType.Single && settings.Conf[ group.GroupName ] >= group.Options.Count ) )
|
||||
{
|
||||
settings.Conf[ group.GroupName ] = 0;
|
||||
_plugin.ModManager.Mods.Save();
|
||||
setting = 0;
|
||||
}
|
||||
|
||||
if( group.Options.Count == 0 )
|
||||
continue;
|
||||
|
||||
if( group.SelectionType == SelectType.Multi )
|
||||
settings.Conf[ group.GroupName ] &= ( ( 1 << group.Options.Count ) - 1 );
|
||||
|
||||
switch( group.SelectionType )
|
||||
{
|
||||
case SelectType.Single:
|
||||
if( group.Options[ setting ].OptionFiles.TryGetValue( relativeFilePath, out paths ) )
|
||||
AddFiles( paths );
|
||||
else
|
||||
{
|
||||
for( var i = 0; i < group.Options.Count; ++i )
|
||||
{
|
||||
if( i == setting )
|
||||
continue;
|
||||
if( group.Options[ i ].OptionFiles.ContainsKey( relativeFilePath ) )
|
||||
{
|
||||
doNotAdd = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case SelectType.Multi:
|
||||
for( var i = 0; i < group.Options.Count; ++i )
|
||||
{
|
||||
if( ( setting & ( 1 << i ) ) != 0 )
|
||||
{
|
||||
if( group.Options[ i ].OptionFiles.TryGetValue( relativeFilePath, out paths ) )
|
||||
AddFiles( paths );
|
||||
}
|
||||
else if( group.Options[ i ].OptionFiles.ContainsKey( relativeFilePath ) )
|
||||
doNotAdd = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( !doNotAdd )
|
||||
AddFiles( new() { relativeFilePath.Replace( '\\', '/' ) } );
|
||||
}
|
||||
|
||||
|
||||
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.ToLowerInvariant() ] = swap.Value;
|
||||
registeredFiles[ swap.Key ] = mod.Meta.Name;
|
||||
}
|
||||
else if( registeredFiles.TryGetValue( swap.Key, out var modName ) )
|
||||
{
|
||||
mod.AddConflict( modName, swap.Key );
|
||||
}
|
||||
}
|
||||
ProcessModFiles( registeredFiles, mod, settings );
|
||||
ProcessSwappedFiles( registeredFiles, mod, settings );
|
||||
}
|
||||
|
||||
_plugin.GameUtils.ReloadPlayerResources();
|
||||
}
|
||||
|
||||
private void ProcessSwappedFiles( Dictionary< string, string > registeredFiles, ResourceMod mod, ModInfo settings )
|
||||
{
|
||||
if( mod?.Meta?.FileSwaps == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
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.ToLowerInvariant() ] = swap.Value;
|
||||
registeredFiles[ swap.Key ] = mod.Meta.Name;
|
||||
}
|
||||
else if( registeredFiles.TryGetValue( swap.Key, out var modName ) )
|
||||
{
|
||||
mod.AddConflict( modName, swap.Key );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessModFiles( Dictionary< string, string > registeredFiles, ResourceMod mod, ModInfo settings )
|
||||
{
|
||||
var baseDir = mod.ModBasePath.FullName;
|
||||
|
||||
foreach( var file in mod.ModFiles )
|
||||
{
|
||||
var relativeFilePath = file.FullName.Substring( baseDir.Length ).TrimStart( '\\' );
|
||||
|
||||
bool doNotAdd = false;
|
||||
|
||||
HashSet< string > paths;
|
||||
foreach( var group in mod.Meta.Groups.Select( G => G.Value ) )
|
||||
{
|
||||
if( !settings.Conf.TryGetValue( group.GroupName, out var setting )
|
||||
|| ( group.SelectionType == SelectType.Single && settings.Conf[ group.GroupName ] >= group.Options.Count ) )
|
||||
{
|
||||
settings.Conf[ group.GroupName ] = 0;
|
||||
_plugin.ModManager.Mods.Save();
|
||||
setting = 0;
|
||||
}
|
||||
|
||||
if( group.Options.Count == 0 )
|
||||
continue;
|
||||
|
||||
if( group.SelectionType == SelectType.Multi )
|
||||
settings.Conf[ group.GroupName ] &= ( ( 1 << group.Options.Count ) - 1 );
|
||||
|
||||
switch( group.SelectionType )
|
||||
{
|
||||
case SelectType.Single:
|
||||
if( group.Options[ setting ].OptionFiles.TryGetValue( relativeFilePath, out paths ) )
|
||||
{
|
||||
AddFiles( paths, out doNotAdd, file, registeredFiles, mod );
|
||||
}
|
||||
else
|
||||
{
|
||||
for( var i = 0; i < group.Options.Count; ++i )
|
||||
{
|
||||
if( i == setting )
|
||||
continue;
|
||||
if( group.Options[ i ].OptionFiles.ContainsKey( relativeFilePath ) )
|
||||
{
|
||||
doNotAdd = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case SelectType.Multi:
|
||||
for( var i = 0; i < group.Options.Count; ++i )
|
||||
{
|
||||
if( ( setting & ( 1 << i ) ) != 0 )
|
||||
{
|
||||
if( group.Options[ i ].OptionFiles.TryGetValue( relativeFilePath, out paths ) )
|
||||
{
|
||||
AddFiles( paths, out doNotAdd, file, registeredFiles, mod );
|
||||
}
|
||||
}
|
||||
else if( group.Options[ i ].OptionFiles.ContainsKey( relativeFilePath ) )
|
||||
doNotAdd = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( !doNotAdd )
|
||||
{
|
||||
AddFiles( new() { relativeFilePath.Replace( '\\', '/' ) }, out doNotAdd, file, registeredFiles, mod );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void AddFiles( HashSet< string > gamePaths, out bool doNotAdd, FileInfo file, Dictionary< string, string > registeredFiles,
|
||||
ResourceMod mod )
|
||||
{
|
||||
doNotAdd = true;
|
||||
foreach( var gamePath in gamePaths )
|
||||
{
|
||||
if( !ResolvedFiles.ContainsKey( gamePath ) )
|
||||
{
|
||||
ResolvedFiles[ gamePath.ToLowerInvariant() ] = file;
|
||||
registeredFiles[ gamePath ] = mod.Meta.Name;
|
||||
}
|
||||
else if( registeredFiles.TryGetValue( gamePath, out var modName ) )
|
||||
{
|
||||
mod.AddConflict( modName, gamePath );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ChangeModPriority( ModInfo info, bool up = false )
|
||||
{
|
||||
Mods.ReorderMod( info, up );
|
||||
|
|
|
|||
|
|
@ -16,8 +16,4 @@ We're working towards a 1.0 release, and you can follow it's progress [here](htt
|
|||
Contributions are welcome, but please make an issue first before writing any code. It's possible what you want to implement is out of scope for this project, or could be reworked so that it would provide greater benefit.
|
||||
|
||||
## TexTools Mods
|
||||
Penumbra has support for some types of TexTools modpacks, however no support will be given. This is aimed as an interim measure while better tooling is developed, but note that there is no ETA for this.
|
||||
|
||||
### Why not support TexTools?
|
||||
|
||||
Because it sucks. It's slow to use, the workflow is awful and the codebase is so far gone any notable improvements or support for new features would mean throwing out significant portions of the existing codebase.
|
||||
Penumbra has support for most TexTools modpacks however this is provided on a best-effort basis and support is not guaranteed. Built in tooling will be added to Penumbra over time to avoid many common TexTools use cases as
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue