mirror of
https://github.com/xivdev/Penumbra.git
synced 2026-02-21 23:37:47 +01:00
A lot of interface stuff, some more cleanup and fixes. Main functionality should be mostly fine, importing works. Missing a lot of mod edit options.
This commit is contained in:
parent
8dd681bdda
commit
dbb9931189
77 changed files with 3332 additions and 2066 deletions
154
Penumbra/Mods/Mod.Creation.cs
Normal file
154
Penumbra/Mods/Mod.Creation.cs
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Dalamud.Utility;
|
||||
using OtterGui.Classes;
|
||||
using OtterGui.Filesystem;
|
||||
using Penumbra.GameData.ByteString;
|
||||
using Penumbra.Import;
|
||||
|
||||
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 )
|
||||
{
|
||||
var name = Path.GetFileNameWithoutExtension( 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." );
|
||||
}
|
||||
|
||||
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.SaveMeta();
|
||||
}
|
||||
|
||||
// Create a file for an option group from given data.
|
||||
internal static void CreateOptionGroup( DirectoryInfo baseFolder, ModGroup groupData,
|
||||
int priority, string desc, IEnumerable< ISubMod > subMods )
|
||||
{
|
||||
switch( groupData.SelectionType )
|
||||
{
|
||||
case SelectType.Multi:
|
||||
{
|
||||
var group = new MultiModGroup()
|
||||
{
|
||||
Name = groupData.GroupName!,
|
||||
Description = desc,
|
||||
Priority = priority,
|
||||
};
|
||||
group.PrioritizedOptions.AddRange( subMods.OfType< SubMod >().Select( ( s, idx ) => ( s, idx ) ) );
|
||||
IModGroup.SaveModGroup( group, baseFolder );
|
||||
break;
|
||||
}
|
||||
case SelectType.Single:
|
||||
{
|
||||
var group = new SingleModGroup()
|
||||
{
|
||||
Name = groupData.GroupName!,
|
||||
Description = desc,
|
||||
Priority = priority,
|
||||
};
|
||||
group.OptionData.AddRange( subMods.OfType< SubMod >() );
|
||||
IModGroup.SaveModGroup( group, baseFolder );
|
||||
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()
|
||||
{
|
||||
Name = option.Name!,
|
||||
};
|
||||
foreach( var (_, gamePath, file) in list )
|
||||
{
|
||||
mod.FileData.TryAdd( gamePath, file );
|
||||
}
|
||||
|
||||
mod.IncorporateMetaChanges( baseFolder, true );
|
||||
return mod;
|
||||
}
|
||||
|
||||
// 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 );
|
||||
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 ) ));
|
||||
|
||||
|
||||
// XIV can not deal with non-ascii symbols in a path,
|
||||
// and the path must obviously be valid itself.
|
||||
private static string ReplaceBadXivSymbols( string s, string replacement = "_" )
|
||||
{
|
||||
StringBuilder sb = new(s.Length);
|
||||
foreach( var c in s )
|
||||
{
|
||||
if( c.IsInvalidAscii() || c.IsInvalidInPath() )
|
||||
{
|
||||
sb.Append( replacement );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append( c );
|
||||
}
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue