This commit is contained in:
Ottermandias 2022-04-14 15:23:58 +02:00
parent 48e442a9fd
commit da73feacf4
59 changed files with 2115 additions and 3428 deletions

View file

@ -6,6 +6,7 @@ using Dalamud.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Penumbra.GameData.ByteString;
using Penumbra.Importer;
using Penumbra.Meta.Manipulations;
namespace Penumbra.Mods;
@ -113,5 +114,82 @@ public partial class Mod2
}
}
}
public void IncorporateMetaChanges( DirectoryInfo basePath, bool delete )
{
foreach( var (key, file) in Files.ToList() )
{
try
{
switch( file.Extension )
{
case ".meta":
FileData.Remove( key );
if( !file.Exists )
{
continue;
}
var meta = new TexToolsMeta( File.ReadAllBytes( file.FullName ) );
if( delete )
{
File.Delete( file.FullName );
}
foreach( var manip in meta.EqpManipulations )
{
ManipulationData.Add( manip );
}
foreach( var manip in meta.EqdpManipulations )
{
ManipulationData.Add( manip );
}
foreach( var manip in meta.EstManipulations )
{
ManipulationData.Add( manip );
}
foreach( var manip in meta.GmpManipulations )
{
ManipulationData.Add( manip );
}
foreach( var manip in meta.ImcManipulations )
{
ManipulationData.Add( manip );
}
break;
case ".rgsp":
FileData.Remove( key );
if( !file.Exists )
{
continue;
}
var rgsp = TexToolsMeta.FromRgspFile( file.FullName, File.ReadAllBytes( file.FullName ) );
if( delete )
{
File.Delete( file.FullName );
}
foreach( var manip in rgsp.RspManipulations )
{
ManipulationData.Add( manip );
}
break;
default: continue;
}
}
catch( Exception e )
{
PluginLog.Error( $"Could not incorporate meta changes in mod {basePath} from file {file.FullName}:\n{e}" );
continue;
}
}
}
}
}

View file

@ -4,72 +4,140 @@ using System.Linq;
namespace Penumbra.Mods;
// Contains the settings for a given mod.
public class ModSettings
public class ModSettings2
{
public static readonly ModSettings Empty = new();
public bool Enabled { get; set; }
public static readonly ModSettings2 Empty = new();
public List< uint > Settings { get; init; } = new();
public int Priority { get; set; }
public Dictionary< string, int > Settings { get; set; } = new();
public bool Enabled { get; set; }
// For backwards compatibility
private Dictionary< string, int > Conf
{
set => Settings = value;
}
public ModSettings DeepCopy()
{
var settings = new ModSettings
public ModSettings2 DeepCopy()
=> new()
{
Enabled = Enabled,
Priority = Priority,
Settings = Settings.ToDictionary( kvp => kvp.Key, kvp => kvp.Value ),
Settings = Settings.ToList(),
};
return settings;
}
public static ModSettings DefaultSettings( ModMeta meta )
{
return new ModSettings
public static ModSettings2 DefaultSettings( Mod2 mod )
=> new()
{
Enabled = false,
Priority = 0,
Settings = meta.Groups.ToDictionary( kvp => kvp.Key, _ => 0 ),
Settings = Enumerable.Repeat( 0u, mod.Groups.Count ).ToList(),
};
public void HandleChanges( ModOptionChangeType type, Mod2 mod, int groupIdx, int optionIdx )
{
switch( type )
{
case ModOptionChangeType.GroupAdded:
Settings.Insert( groupIdx, 0 );
break;
case ModOptionChangeType.GroupDeleted:
Settings.RemoveAt( groupIdx );
break;
case ModOptionChangeType.OptionDeleted:
var group = mod.Groups[ groupIdx ];
var config = Settings[ groupIdx ];
Settings[ groupIdx ] = group.Type switch
{
SelectType.Single => config >= optionIdx ? Math.Max( 0, config - 1 ) : config,
SelectType.Multi => RemoveBit( config, optionIdx ),
_ => config,
};
break;
}
}
public void SetValue( Mod2 mod, int groupIdx, uint newValue )
{
AddMissingSettings( groupIdx + 1 );
var group = mod.Groups[ groupIdx ];
Settings[ groupIdx ] = group.Type switch
{
SelectType.Single => ( uint )Math.Max( newValue, group.Count ),
SelectType.Multi => ( ( 1u << group.Count ) - 1 ) & newValue,
_ => newValue,
};
}
public bool FixSpecificSetting( string name, ModMeta meta )
private static uint RemoveBit( uint config, int bit )
{
if( !meta.Groups.TryGetValue( name, out var group ) )
{
return Settings.Remove( name );
}
if( Settings.TryGetValue( name, out var oldSetting ) )
{
Settings[ name ] = group.SelectionType switch
{
SelectType.Single => Math.Min( Math.Max( oldSetting, 0 ), group.Options.Count - 1 ),
SelectType.Multi => Math.Min( Math.Max( oldSetting, 0 ), ( 1 << group.Options.Count ) - 1 ),
_ => Settings[ group.GroupName ],
};
return oldSetting != Settings[ group.GroupName ];
}
Settings[ name ] = 0;
return true;
var lowMask = ( 1u << bit ) - 1u;
var highMask = ~( ( 1u << ( bit + 1 ) ) - 1u );
var low = config & lowMask;
var high = ( config & highMask ) >> 1;
return low | high;
}
public bool FixInvalidSettings( ModMeta meta )
internal bool AddMissingSettings( int totalCount )
{
if( meta.Groups.Count == 0 )
if( totalCount <= Settings.Count )
{
return false;
}
return Settings.Keys.ToArray().Union( meta.Groups.Keys )
.Aggregate( false, ( current, name ) => current | FixSpecificSetting( name, meta ) );
Settings.AddRange( Enumerable.Repeat( 0u, totalCount - Settings.Count ) );
return true;
}
public struct SavedSettings
{
public Dictionary< string, uint > Settings;
public int Priority;
public bool Enabled;
public SavedSettings DeepCopy()
=> new()
{
Enabled = Enabled,
Priority = Priority,
Settings = Settings.ToDictionary( kvp => kvp.Key, kvp => kvp.Value ),
};
public SavedSettings( ModSettings2 settings, Mod2 mod )
{
Priority = settings.Priority;
Enabled = settings.Enabled;
Settings = new Dictionary< string, uint >( mod.Groups.Count );
settings.AddMissingSettings( mod.Groups.Count );
foreach( var (group, setting) in mod.Groups.Zip( settings.Settings ) )
{
Settings.Add( group.Name, setting );
}
}
public bool ToSettings( Mod2 mod, out ModSettings2 settings )
{
var list = new List< uint >( mod.Groups.Count );
var changes = Settings.Count != mod.Groups.Count;
foreach( var group in mod.Groups )
{
if( Settings.TryGetValue( group.Name, out var config ) )
{
list.Add( config );
}
else
{
list.Add( 0 );
changes = true;
}
}
settings = new ModSettings2
{
Enabled = Enabled,
Priority = Priority,
Settings = list,
};
return changes;
}
}
}

View file

@ -0,0 +1,7 @@
namespace Penumbra.Mods;
public enum SelectType
{
Single,
Multi,
}