diff --git a/Penumbra/Api/PenumbraApi.cs b/Penumbra/Api/PenumbraApi.cs
index 8e609cb7..be3a01ac 100644
--- a/Penumbra/Api/PenumbraApi.cs
+++ b/Penumbra/Api/PenumbraApi.cs
@@ -829,7 +829,7 @@ public class PenumbraApi : IDisposable, IPenumbraApi
public PenumbraApiEc CreateNamedTemporaryCollection( string name )
{
CheckInitialized();
- if( name.Length == 0 || Mod.ReplaceBadXivSymbols( name ) != name )
+ if( name.Length == 0 || Mod.Creator.ReplaceBadXivSymbols( name ) != name )
{
return PenumbraApiEc.InvalidArgument;
}
diff --git a/Penumbra/Import/TexToolsImporter.Archives.cs b/Penumbra/Import/TexToolsImporter.Archives.cs
index a6403027..a00d042c 100644
--- a/Penumbra/Import/TexToolsImporter.Archives.cs
+++ b/Penumbra/Import/TexToolsImporter.Archives.cs
@@ -44,7 +44,7 @@ public partial class TexToolsImporter
};
Penumbra.Log.Information( $" -> Importing {archive.Type} Archive." );
- _currentModDirectory = Mod.CreateModFolder( _baseDirectory, Path.GetRandomFileName() );
+ _currentModDirectory = Mod.Creator.CreateModFolder( _baseDirectory, Path.GetRandomFileName() );
var options = new ExtractionOptions()
{
ExtractFullPath = true,
@@ -99,13 +99,13 @@ public partial class TexToolsImporter
// Use either the top-level directory as the mods base name, or the (fixed for path) name in the json.
if( leadDir )
{
- _currentModDirectory = Mod.CreateModFolder( _baseDirectory, baseName, false );
+ _currentModDirectory = Mod.Creator.CreateModFolder( _baseDirectory, baseName, false );
Directory.Move( Path.Combine( oldName, baseName ), _currentModDirectory.FullName );
Directory.Delete( oldName );
}
else
{
- _currentModDirectory = Mod.CreateModFolder( _baseDirectory, name, false );
+ _currentModDirectory = Mod.Creator.CreateModFolder( _baseDirectory, name, false );
Directory.Move( oldName, _currentModDirectory.FullName );
}
@@ -114,6 +114,7 @@ public partial class TexToolsImporter
return _currentModDirectory;
}
+
// Search the archive for the meta.json file which needs to exist.
private static string FindArchiveModMeta( IArchive archive, out bool leadDir )
{
diff --git a/Penumbra/Import/TexToolsImporter.ModPack.cs b/Penumbra/Import/TexToolsImporter.ModPack.cs
index e2edfe92..2fb79390 100644
--- a/Penumbra/Import/TexToolsImporter.ModPack.cs
+++ b/Penumbra/Import/TexToolsImporter.ModPack.cs
@@ -34,14 +34,14 @@ public partial class TexToolsImporter
var modList = modListRaw.Select( m => JsonConvert.DeserializeObject< SimpleMod >( m, JsonSettings )! ).ToList();
- _currentModDirectory = Mod.CreateModFolder( _baseDirectory, Path.GetFileNameWithoutExtension( modPackFile.Name ) );
+ _currentModDirectory = Mod.Creator.CreateModFolder( _baseDirectory, Path.GetFileNameWithoutExtension( modPackFile.Name ) );
// Create a new ModMeta from the TTMP mod list info
- Mod.CreateMeta( _currentModDirectory, _currentModName, DefaultTexToolsData.Author, DefaultTexToolsData.Description, null, null );
+ Mod.Creator.CreateMeta( _currentModDirectory, _currentModName, DefaultTexToolsData.Author, DefaultTexToolsData.Description, null, null );
// Open the mod data file from the mod pack as a SqPackStream
_streamDisposer = GetSqPackStreamStream( extractedModPack, "TTMPD.mpd" );
ExtractSimpleModList( _currentModDirectory, modList );
- Mod.CreateDefaultFiles( _currentModDirectory );
+ Mod.Creator.CreateDefaultFiles( _currentModDirectory );
ResetStreamDisposer();
return _currentModDirectory;
}
@@ -90,15 +90,15 @@ public partial class TexToolsImporter
_currentOptionName = DefaultTexToolsData.DefaultOption;
Penumbra.Log.Information( " -> Importing Simple V2 ModPack" );
- _currentModDirectory = Mod.CreateModFolder( _baseDirectory, _currentModName );
- Mod.CreateMeta( _currentModDirectory, _currentModName, modList.Author, string.IsNullOrEmpty( modList.Description )
+ _currentModDirectory = Mod.Creator.CreateModFolder( _baseDirectory, _currentModName );
+ Mod.Creator.CreateMeta( _currentModDirectory, _currentModName, modList.Author, string.IsNullOrEmpty( modList.Description )
? "Mod imported from TexTools mod pack"
: modList.Description, modList.Version, modList.Url );
// Open the mod data file from the mod pack as a SqPackStream
_streamDisposer = GetSqPackStreamStream( extractedModPack, "TTMPD.mpd" );
ExtractSimpleModList( _currentModDirectory, modList.SimpleModsList );
- Mod.CreateDefaultFiles( _currentModDirectory );
+ Mod.Creator.CreateDefaultFiles( _currentModDirectory );
ResetStreamDisposer();
return _currentModDirectory;
}
@@ -135,8 +135,8 @@ public partial class TexToolsImporter
_currentNumOptions = GetOptionCount( modList );
_currentModName = modList.Name;
- _currentModDirectory = Mod.CreateModFolder( _baseDirectory, _currentModName );
- Mod.CreateMeta( _currentModDirectory, _currentModName, modList.Author, modList.Description, modList.Version, modList.Url );
+ _currentModDirectory = Mod.Creator.CreateModFolder( _baseDirectory, _currentModName );
+ Mod.Creator.CreateMeta( _currentModDirectory, _currentModName, modList.Author, modList.Description, modList.Version, modList.Url );
if( _currentNumOptions == 0 )
{
@@ -173,7 +173,7 @@ public partial class TexToolsImporter
{
var name = numGroups == 1 ? _currentGroupName : $"{_currentGroupName}, Part {groupId + 1}";
options.Clear();
- var groupFolder = Mod.NewSubFolderName( _currentModDirectory, name )
+ var groupFolder = Mod.Creator.NewSubFolderName( _currentModDirectory, name )
?? new DirectoryInfo( Path.Combine( _currentModDirectory.FullName,
numGroups == 1 ? $"Group {groupPriority + 1}" : $"Group {groupPriority + 1}, Part {groupId + 1}" ) );
@@ -183,10 +183,10 @@ public partial class TexToolsImporter
var option = allOptions[ i + optionIdx ];
_token.ThrowIfCancellationRequested();
_currentOptionName = option.Name;
- var optionFolder = Mod.NewSubFolderName( groupFolder, option.Name )
+ var optionFolder = Mod.Creator.NewSubFolderName( groupFolder, option.Name )
?? new DirectoryInfo( Path.Combine( groupFolder.FullName, $"Option {i + optionIdx + 1}" ) );
ExtractSimpleModList( optionFolder, option.ModsJsons );
- options.Add( Mod.CreateSubMod( _currentModDirectory, optionFolder, option ) );
+ options.Add( Mod.Creator.CreateSubMod( _currentModDirectory, optionFolder, option ) );
if( option.IsChecked )
{
defaultSettings = group.SelectionType == GroupType.Multi
@@ -207,12 +207,12 @@ public partial class TexToolsImporter
if( empty != null )
{
_currentOptionName = empty.Name;
- options.Insert( 0, Mod.CreateEmptySubMod( empty.Name ) );
+ options.Insert( 0, Mod.Creator.CreateEmptySubMod( empty.Name ) );
defaultSettings = defaultSettings == null ? 0 : defaultSettings.Value + 1;
}
}
- Mod.CreateOptionGroup( _currentModDirectory, group.SelectionType, name, groupPriority, groupPriority,
+ Mod.Creator.CreateOptionGroup( _currentModDirectory, group.SelectionType, name, groupPriority, groupPriority,
defaultSettings ?? 0, group.Description, options );
++groupPriority;
}
@@ -220,7 +220,7 @@ public partial class TexToolsImporter
}
ResetStreamDisposer();
- Mod.CreateDefaultFiles( _currentModDirectory );
+ Mod.Creator.CreateDefaultFiles( _currentModDirectory );
return _currentModDirectory;
}
diff --git a/Penumbra/Mods/Editor/Mod.Normalization.cs b/Penumbra/Mods/Editor/Mod.Normalization.cs
index 73a92a09..0696271d 100644
--- a/Penumbra/Mods/Editor/Mod.Normalization.cs
+++ b/Penumbra/Mods/Editor/Mod.Normalization.cs
@@ -150,11 +150,11 @@ public partial class Mod
foreach( var (group, groupIdx) in _mod.Groups.WithIndex() )
{
_redirections[ groupIdx + 1 ] = new Dictionary< Utf8GamePath, FullPath >[group.Count];
- var groupDir = CreateModFolder( directory, group.Name );
+ var groupDir = Creator.CreateModFolder( directory, group.Name );
foreach( var option in group.OfType< SubMod >() )
{
- var optionDir = CreateModFolder( groupDir, option.Name );
+ var optionDir = Creator.CreateModFolder( groupDir, option.Name );
newDict = new Dictionary< Utf8GamePath, FullPath >( option.FileData.Count );
_redirections[ groupIdx + 1 ][ option.OptionIdx ] = newDict;
foreach( var (gamePath, fullPath) in option.FileData )
diff --git a/Penumbra/Mods/ItemSwap/EquipmentSwap.cs b/Penumbra/Mods/ItemSwap/EquipmentSwap.cs
index a1de7b7a..51b3dea0 100644
--- a/Penumbra/Mods/ItemSwap/EquipmentSwap.cs
+++ b/Penumbra/Mods/ItemSwap/EquipmentSwap.cs
@@ -64,12 +64,6 @@ public static class EquipmentSwap
var imcFileTo = new ImcFile( imcManip);
var isAccessory = slot.IsAccessory();
- var estType = slot switch
- {
- EquipSlot.Head => EstManipulation.EstType.Head,
- EquipSlot.Body => EstManipulation.EstType.Body,
- _ => ( EstManipulation.EstType )0,
- };
var skipFemale = false;
var skipMale = false;
@@ -89,12 +83,6 @@ public static class EquipmentSwap
continue;
}
- var est = ItemSwap.CreateEst( redirections, manips, estType, gr, idFrom, idTo );
- if( est != null )
- {
- swaps.Add( est );
- }
-
try
{
var eqdp = CreateEqdp( redirections, manips, slot, gr, idFrom, idTo, mtrlVariantTo );
@@ -140,6 +128,19 @@ public static class EquipmentSwap
{
var mdl = CreateMdl( redirections, slot, gr, idFrom, idTo, mtrlTo );
meta.ChildSwaps.Add( mdl );
+
+ var estType = slot switch
+ {
+ EquipSlot.Head => EstManipulation.EstType.Head,
+ EquipSlot.Body => EstManipulation.EstType.Body,
+ _ => ( EstManipulation.EstType )0,
+ };
+
+ var est = ItemSwap.CreateEst( redirections, manips, estType, gr, idFrom, idTo );
+ if( est != null )
+ {
+ meta.ChildSwaps.Add( est );
+ }
}
else if( !ownMtrl && meta.SwapAppliedIsDefault )
{
diff --git a/Penumbra/Mods/Manager/Mod.Manager.BasePath.cs b/Penumbra/Mods/Manager/Mod.Manager.BasePath.cs
index 8f092ed4..3712831f 100644
--- a/Penumbra/Mods/Manager/Mod.Manager.BasePath.cs
+++ b/Penumbra/Mods/Manager/Mod.Manager.BasePath.cs
@@ -175,7 +175,7 @@ public partial class Mod
return NewDirectoryState.Identical;
}
- var fixedNewName = ReplaceBadXivSymbols( newName );
+ var fixedNewName = Creator.ReplaceBadXivSymbols( newName );
if( fixedNewName != newName )
{
return NewDirectoryState.ContainsInvalidSymbols;
diff --git a/Penumbra/Mods/Mod.Creation.cs b/Penumbra/Mods/Mod.Creation.cs
deleted file mode 100644
index 13cd4ab7..00000000
--- a/Penumbra/Mods/Mod.Creation.cs
+++ /dev/null
@@ -1,187 +0,0 @@
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-using Dalamud.Utility;
-using OtterGui.Classes;
-using OtterGui.Filesystem;
-using Penumbra.Api.Enums;
-using Penumbra.Import;
-using Penumbra.String.Classes;
-
-namespace Penumbra.Mods;
-
-public partial class Mod
-{
- ///
- /// Create and return a new directory based on the given directory and name, that is
- /// - Not Empty.
- /// - Unique, by appending (digit) for duplicates.
- /// - Containing no symbols invalid for FFXIV or windows paths.
- ///
- ///
- ///
- ///
- ///
- ///
- internal static DirectoryInfo CreateModFolder( DirectoryInfo outDirectory, string modListName, bool create = true )
- {
- var name = modListName;
- if( name.Length == 0 )
- {
- name = "_";
- }
-
- var newModFolderBase = NewOptionDirectory( outDirectory, name );
- var newModFolder = newModFolderBase.FullName.ObtainUniqueFile();
- if( newModFolder.Length == 0 )
- {
- throw new IOException( "Could not create mod folder: too many folders of the same name exist." );
- }
-
- if( create )
- {
- Directory.CreateDirectory( newModFolder );
- }
-
- return new DirectoryInfo( newModFolder );
- }
-
- ///
- /// Create the name for a group or option subfolder based on its parent folder and given name.
- /// subFolderName should never be empty, and the result is unique and contains no invalid symbols.
- ///
- internal static DirectoryInfo? NewSubFolderName( DirectoryInfo parentFolder, string subFolderName )
- {
- var newModFolderBase = NewOptionDirectory( parentFolder, subFolderName );
- var newModFolder = newModFolderBase.FullName.ObtainUniqueFile();
- return newModFolder.Length == 0 ? null : new DirectoryInfo( newModFolder );
- }
-
- // Create the file containing the meta information about a mod from scratch.
- internal static void CreateMeta( DirectoryInfo directory, string? name, string? author, string? description, string? version,
- string? website )
- {
- var mod = new Mod( directory );
- mod.Name = name.IsNullOrEmpty() ? mod.Name : new LowerString( name! );
- mod.Author = author != null ? new LowerString( author ) : mod.Author;
- mod.Description = description ?? mod.Description;
- mod.Version = version ?? mod.Version;
- mod.Website = website ?? mod.Website;
- mod.SaveMetaFile(); // Not delayed.
- }
-
- // Create a file for an option group from given data.
- internal static void CreateOptionGroup( DirectoryInfo baseFolder, GroupType type, string name,
- int priority, int index, uint defaultSettings, string desc, IEnumerable< ISubMod > subMods )
- {
- switch( type )
- {
- case GroupType.Multi:
- {
- var group = new MultiModGroup()
- {
- Name = name,
- Description = desc,
- Priority = priority,
- DefaultSettings = defaultSettings,
- };
- group.PrioritizedOptions.AddRange( subMods.OfType< SubMod >().Select( ( s, idx ) => ( s, idx ) ) );
- IModGroup.Save( group, baseFolder, index );
- break;
- }
- case GroupType.Single:
- {
- var group = new SingleModGroup()
- {
- Name = name,
- Description = desc,
- Priority = priority,
- DefaultSettings = defaultSettings,
- };
- group.OptionData.AddRange( subMods.OfType< SubMod >() );
- IModGroup.Save( group, baseFolder, index );
- break;
- }
- }
- }
-
- // Create the data for a given sub mod from its data and the folder it is based on.
- internal static ISubMod CreateSubMod( DirectoryInfo baseFolder, DirectoryInfo optionFolder, OptionList option )
- {
- var list = optionFolder.EnumerateFiles( "*.*", SearchOption.AllDirectories )
- .Select( f => ( Utf8GamePath.FromFile( f, optionFolder, out var gamePath, true ), gamePath, new FullPath( f ) ) )
- .Where( t => t.Item1 );
-
- var mod = new SubMod( null! ) // Mod is irrelevant here, only used for saving.
- {
- Name = option.Name,
- Description = option.Description,
- };
- foreach( var (_, gamePath, file) in list )
- {
- mod.FileData.TryAdd( gamePath, file );
- }
-
- mod.IncorporateMetaChanges( baseFolder, true );
- return mod;
- }
-
- // Create an empty sub mod for single groups with None options.
- internal static ISubMod CreateEmptySubMod( string name )
- => new SubMod( null! ) // Mod is irrelevant here, only used for saving.
- {
- Name = name,
- };
-
- // Create the default data file from all unused files that were not handled before
- // and are used in sub mods.
- internal static void CreateDefaultFiles( DirectoryInfo directory )
- {
- var mod = new Mod( directory );
- mod.Reload( false, out _ );
- foreach( var file in mod.FindUnusedFiles() )
- {
- if( Utf8GamePath.FromFile( new FileInfo( file.FullName ), directory, out var gamePath, true ) )
- {
- mod._default.FileData.TryAdd( gamePath, file );
- }
- }
-
- mod._default.IncorporateMetaChanges( directory, true );
- mod.SaveDefaultMod();
- }
-
- // Return the name of a new valid directory based on the base directory and the given name.
- private static DirectoryInfo NewOptionDirectory( DirectoryInfo baseDir, string optionName )
- => new(Path.Combine( baseDir.FullName, ReplaceBadXivSymbols( optionName ) ));
-
- // Normalize for nicer names, and remove invalid symbols or invalid paths.
- public static string ReplaceBadXivSymbols( string s, string replacement = "_" )
- {
- if( s == "." )
- {
- return replacement;
- }
-
- if( s == ".." )
- {
- return replacement + replacement;
- }
-
- StringBuilder sb = new(s.Length);
- foreach( var c in s.Normalize( NormalizationForm.FormKC ) )
- {
- if( c.IsInvalidInPath() )
- {
- sb.Append( replacement );
- }
- else
- {
- sb.Append( c );
- }
- }
-
- return sb.ToString();
- }
-}
\ No newline at end of file
diff --git a/Penumbra/Mods/Mod.Creator.cs b/Penumbra/Mods/Mod.Creator.cs
new file mode 100644
index 00000000..85fbfa50
--- /dev/null
+++ b/Penumbra/Mods/Mod.Creator.cs
@@ -0,0 +1,188 @@
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using Dalamud.Utility;
+using OtterGui.Classes;
+using OtterGui.Filesystem;
+using Penumbra.Api.Enums;
+using Penumbra.Import;
+using Penumbra.String.Classes;
+
+namespace Penumbra.Mods;
+
+public partial class Mod
+{
+ internal static class Creator
+ {
+ ///
+ /// Create and return a new directory based on the given directory and name, that is
+ /// - Not Empty.
+ /// - Unique, by appending (digit) for duplicates.
+ /// - Containing no symbols invalid for FFXIV or windows paths.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static DirectoryInfo CreateModFolder( DirectoryInfo outDirectory, string modListName, bool create = true )
+ {
+ var name = modListName;
+ if( name.Length == 0 )
+ {
+ name = "_";
+ }
+
+ var newModFolderBase = NewOptionDirectory( outDirectory, name );
+ var newModFolder = newModFolderBase.FullName.ObtainUniqueFile();
+ if( newModFolder.Length == 0 )
+ {
+ throw new IOException( "Could not create mod folder: too many folders of the same name exist." );
+ }
+
+ if( create )
+ {
+ Directory.CreateDirectory( newModFolder );
+ }
+
+ return new DirectoryInfo( newModFolder );
+ }
+
+ ///
+ /// Create the name for a group or option subfolder based on its parent folder and given name.
+ /// subFolderName should never be empty, and the result is unique and contains no invalid symbols.
+ ///
+ public static DirectoryInfo? NewSubFolderName( DirectoryInfo parentFolder, string subFolderName )
+ {
+ var newModFolderBase = NewOptionDirectory( parentFolder, subFolderName );
+ var newModFolder = newModFolderBase.FullName.ObtainUniqueFile();
+ return newModFolder.Length == 0 ? null : new DirectoryInfo( newModFolder );
+ }
+
+ /// Create the file containing the meta information about a mod from scratch.
+ public static void CreateMeta( DirectoryInfo directory, string? name, string? author, string? description, string? version,
+ string? website )
+ {
+ var mod = new Mod( directory );
+ mod.Name = name.IsNullOrEmpty() ? mod.Name : new LowerString( name! );
+ mod.Author = author != null ? new LowerString( author ) : mod.Author;
+ mod.Description = description ?? mod.Description;
+ mod.Version = version ?? mod.Version;
+ mod.Website = website ?? mod.Website;
+ mod.SaveMetaFile(); // Not delayed.
+ }
+
+ /// Create a file for an option group from given data.
+ public static void CreateOptionGroup( DirectoryInfo baseFolder, GroupType type, string name,
+ int priority, int index, uint defaultSettings, string desc, IEnumerable< ISubMod > subMods )
+ {
+ switch( type )
+ {
+ case GroupType.Multi:
+ {
+ var group = new MultiModGroup()
+ {
+ Name = name,
+ Description = desc,
+ Priority = priority,
+ DefaultSettings = defaultSettings,
+ };
+ group.PrioritizedOptions.AddRange( subMods.OfType< SubMod >().Select( ( s, idx ) => ( s, idx ) ) );
+ IModGroup.Save( group, baseFolder, index );
+ break;
+ }
+ case GroupType.Single:
+ {
+ var group = new SingleModGroup()
+ {
+ Name = name,
+ Description = desc,
+ Priority = priority,
+ DefaultSettings = defaultSettings,
+ };
+ group.OptionData.AddRange( subMods.OfType< SubMod >() );
+ IModGroup.Save( group, baseFolder, index );
+ break;
+ }
+ }
+ }
+
+ /// Create the data for a given sub mod from its data and the folder it is based on.
+ public static ISubMod CreateSubMod( DirectoryInfo baseFolder, DirectoryInfo optionFolder, OptionList option )
+ {
+ var list = optionFolder.EnumerateFiles( "*.*", SearchOption.AllDirectories )
+ .Select( f => ( Utf8GamePath.FromFile( f, optionFolder, out var gamePath, true ), gamePath, new FullPath( f ) ) )
+ .Where( t => t.Item1 );
+
+ var mod = new SubMod( null! ) // Mod is irrelevant here, only used for saving.
+ {
+ Name = option.Name,
+ Description = option.Description,
+ };
+ foreach( var (_, gamePath, file) in list )
+ {
+ mod.FileData.TryAdd( gamePath, file );
+ }
+
+ mod.IncorporateMetaChanges( baseFolder, true );
+ return mod;
+ }
+
+ /// Create an empty sub mod for single groups with None options.
+ internal static ISubMod CreateEmptySubMod( string name )
+ => new SubMod( null! ) // Mod is irrelevant here, only used for saving.
+ {
+ Name = name,
+ };
+
+ ///
+ /// Create the default data file from all unused files that were not handled before
+ /// and are used in sub mods.
+ ///
+ internal static void CreateDefaultFiles( DirectoryInfo directory )
+ {
+ var mod = new Mod( directory );
+ mod.Reload( false, out _ );
+ foreach( var file in mod.FindUnusedFiles() )
+ {
+ if( Utf8GamePath.FromFile( new FileInfo( file.FullName ), directory, out var gamePath, true ) )
+ {
+ mod._default.FileData.TryAdd( gamePath, file );
+ }
+ }
+
+ mod._default.IncorporateMetaChanges( directory, true );
+ mod.SaveDefaultMod();
+ }
+
+ /// Return the name of a new valid directory based on the base directory and the given name.
+ public static DirectoryInfo NewOptionDirectory( DirectoryInfo baseDir, string optionName )
+ => new(Path.Combine( baseDir.FullName, ReplaceBadXivSymbols( optionName ) ));
+
+ /// Normalize for nicer names, and remove invalid symbols or invalid paths.
+ public static string ReplaceBadXivSymbols( string s, string replacement = "_" )
+ {
+ switch( s )
+ {
+ case ".": return replacement;
+ case "..": return replacement + replacement;
+ }
+
+ StringBuilder sb = new(s.Length);
+ foreach( var c in s.Normalize( NormalizationForm.FormKC ) )
+ {
+ if( c.IsInvalidInPath() )
+ {
+ sb.Append( replacement );
+ }
+ else
+ {
+ sb.Append( c );
+ }
+ }
+
+ return sb.ToString();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Penumbra/Mods/Mod.TemporaryMod.cs b/Penumbra/Mods/Mod.TemporaryMod.cs
index 802852e9..6de0a682 100644
--- a/Penumbra/Mods/Mod.TemporaryMod.cs
+++ b/Penumbra/Mods/Mod.TemporaryMod.cs
@@ -51,9 +51,9 @@ public sealed partial class Mod
DirectoryInfo? dir = null;
try
{
- dir = CreateModFolder( Penumbra.ModManager.BasePath, collection.Name );
+ dir = Creator.CreateModFolder( Penumbra.ModManager.BasePath, collection.Name );
var fileDir = Directory.CreateDirectory( Path.Combine( dir.FullName, "files" ) );
- CreateMeta( dir, collection.Name, character ?? Penumbra.Config.DefaultModAuthor,
+ Creator.CreateMeta( dir, collection.Name, character ?? Penumbra.Config.DefaultModAuthor,
$"Mod generated from temporary collection {collection.Name} for {character ?? "Unknown Character"}.", null, null );
var mod = new Mod( dir );
var defaultMod = mod._default;
diff --git a/Penumbra/Mods/Subclasses/Mod.Files.MultiModGroup.cs b/Penumbra/Mods/Subclasses/Mod.Files.MultiModGroup.cs
index fe7b1173..6b6259f6 100644
--- a/Penumbra/Mods/Subclasses/Mod.Files.MultiModGroup.cs
+++ b/Penumbra/Mods/Subclasses/Mod.Files.MultiModGroup.cs
@@ -3,11 +3,13 @@ using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
+using Dalamud.Interface.Internal.Notifications;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using OtterGui;
using OtterGui.Filesystem;
using Penumbra.Api.Enums;
+using Penumbra.Util;
namespace Penumbra.Mods;
@@ -63,8 +65,7 @@ public partial class Mod
{
if( ret.PrioritizedOptions.Count == IModGroup.MaxMultiOptions )
{
- Penumbra.Log.Warning(
- $"Multi Group {ret.Name} has more than {IModGroup.MaxMultiOptions} options, ignoring excessive options." );
+ ChatUtil.NotificationMessage( $"Multi Group {ret.Name} has more than {IModGroup.MaxMultiOptions} options, ignoring excessive options.", "Warning", NotificationType.Warning );
break;
}
diff --git a/Penumbra/Mods/Subclasses/Mod.Files.SubMod.cs b/Penumbra/Mods/Subclasses/Mod.Files.SubMod.cs
index ed0fd1fb..981b336b 100644
--- a/Penumbra/Mods/Subclasses/Mod.Files.SubMod.cs
+++ b/Penumbra/Mods/Subclasses/Mod.Files.SubMod.cs
@@ -67,7 +67,7 @@ public partial class Mod
_default.WriteTexToolsMeta( ModPath );
foreach( var group in Groups )
{
- var dir = NewOptionDirectory( ModPath, group.Name );
+ var dir = Creator.NewOptionDirectory( ModPath, group.Name );
if( !dir.Exists )
{
dir.Create();
@@ -75,7 +75,7 @@ public partial class Mod
foreach( var option in group.OfType< SubMod >() )
{
- var optionDir = NewOptionDirectory( dir, option.Name );
+ var optionDir = Creator.NewOptionDirectory( dir, option.Name );
if( !optionDir.Exists )
{
optionDir.Create();
diff --git a/Penumbra/UI/Classes/ItemSwapWindow.cs b/Penumbra/UI/Classes/ItemSwapWindow.cs
index 8215bcc7..cd551088 100644
--- a/Penumbra/UI/Classes/ItemSwapWindow.cs
+++ b/Penumbra/UI/Classes/ItemSwapWindow.cs
@@ -216,9 +216,9 @@ public class ItemSwapWindow : IDisposable
private void CreateMod()
{
- var newDir = Mod.CreateModFolder( Penumbra.ModManager.BasePath, _newModName );
- Mod.CreateMeta( newDir, _newModName, Penumbra.Config.DefaultModAuthor, CreateDescription(), "1.0", string.Empty );
- Mod.CreateDefaultFiles( newDir );
+ var newDir = Mod.Creator.CreateModFolder( Penumbra.ModManager.BasePath, _newModName );
+ Mod.Creator.CreateMeta( newDir, _newModName, Penumbra.Config.DefaultModAuthor, CreateDescription(), "1.0", string.Empty );
+ Mod.Creator.CreateDefaultFiles( newDir );
Penumbra.ModManager.AddMod( newDir );
if( !_swapData.WriteMod( Penumbra.ModManager.Last(), _useFileSwaps ? ItemSwapContainer.WriteType.UseSwaps : ItemSwapContainer.WriteType.NoSwaps ) )
{
@@ -239,7 +239,7 @@ public class ItemSwapWindow : IDisposable
DirectoryInfo? optionFolderName = null;
try
{
- optionFolderName = Mod.NewSubFolderName( new DirectoryInfo( Path.Combine( _mod.ModPath.FullName, _selectedGroup?.Name ?? _newGroupName ) ), _newOptionName );
+ optionFolderName = Mod.Creator.NewSubFolderName( new DirectoryInfo( Path.Combine( _mod.ModPath.FullName, _selectedGroup?.Name ?? _newGroupName ) ), _newOptionName );
if( optionFolderName?.Exists == true )
{
throw new Exception( $"The folder {optionFolderName.FullName} for the option already exists." );
diff --git a/Penumbra/UI/Classes/ModFileSystemSelector.cs b/Penumbra/UI/Classes/ModFileSystemSelector.cs
index 61b46a36..497a2f0e 100644
--- a/Penumbra/UI/Classes/ModFileSystemSelector.cs
+++ b/Penumbra/UI/Classes/ModFileSystemSelector.cs
@@ -92,9 +92,9 @@ public sealed partial class ModFileSystemSelector : FileSystemSelector< Mod, Mod
{
try
{
- var newDir = Mod.CreateModFolder( Penumbra.ModManager.BasePath, _newModName );
- Mod.CreateMeta( newDir, _newModName, Penumbra.Config.DefaultModAuthor, string.Empty, "1.0", string.Empty );
- Mod.CreateDefaultFiles( newDir );
+ var newDir = Mod.Creator.CreateModFolder( Penumbra.ModManager.BasePath, _newModName );
+ Mod.Creator.CreateMeta( newDir, _newModName, Penumbra.Config.DefaultModAuthor, string.Empty, "1.0", string.Empty );
+ Mod.Creator.CreateDefaultFiles( newDir );
Penumbra.ModManager.AddMod( newDir );
_newModName = string.Empty;
}