2021-02-01 11:43:38 -08:00
|
|
|
|
using System;
|
2025-02-12 15:36:25 -05:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.IO;
|
|
|
|
|
|
#if NET40_OR_GREATER || NETCOREAPP
|
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
#endif
|
2024-03-11 21:30:24 -04:00
|
|
|
|
using SabreTools.Core.Tools;
|
2020-12-10 23:24:09 -08:00
|
|
|
|
using SabreTools.DatFiles;
|
2025-02-12 15:36:25 -05:00
|
|
|
|
using SabreTools.DatItems;
|
|
|
|
|
|
using SabreTools.IO;
|
2024-10-24 00:36:44 -04:00
|
|
|
|
using SabreTools.IO.Logging;
|
2020-12-09 21:52:38 -08:00
|
|
|
|
|
2024-10-30 11:26:56 -04:00
|
|
|
|
namespace SabreTools.DatTools
|
2020-12-09 21:52:38 -08:00
|
|
|
|
{
|
2024-10-30 11:26:56 -04:00
|
|
|
|
public class MergeSplit
|
2020-12-09 21:52:38 -08:00
|
|
|
|
{
|
2021-02-01 11:43:38 -08:00
|
|
|
|
#region Fields
|
2020-12-10 14:11:35 -08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2021-02-01 11:43:38 -08:00
|
|
|
|
/// Splitting mode to apply
|
2020-12-10 14:11:35 -08:00
|
|
|
|
/// </summary>
|
2021-02-01 11:43:38 -08:00
|
|
|
|
public MergingFlag SplitType { get; set; }
|
2020-12-10 14:11:35 -08:00
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2021-02-01 11:43:38 -08:00
|
|
|
|
#region Logging
|
2020-12-09 21:52:38 -08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2021-02-01 11:43:38 -08:00
|
|
|
|
/// Logging object
|
2020-12-09 21:52:38 -08:00
|
|
|
|
/// </summary>
|
2025-01-08 16:59:44 -05:00
|
|
|
|
private static readonly Logger _staticLogger = new();
|
2020-12-09 21:52:38 -08:00
|
|
|
|
|
2021-02-01 11:43:38 -08:00
|
|
|
|
#endregion
|
2023-04-19 12:04:25 -04:00
|
|
|
|
|
2021-02-01 11:43:38 -08:00
|
|
|
|
#region Running
|
2020-12-09 21:52:38 -08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Apply splitting on the DatFile
|
|
|
|
|
|
/// </summary>
|
2020-12-10 13:13:54 -08:00
|
|
|
|
/// <param name="datFile">Current DatFile object to run operations on</param>
|
2020-12-09 21:52:38 -08:00
|
|
|
|
/// <param name="useTags">True if DatFile tags override splitting, false otherwise</param>
|
|
|
|
|
|
/// <param name="throwOnError">True if the error that is thrown should be thrown back to the caller, false otherwise</param>
|
|
|
|
|
|
/// <returns>True if the DatFile was split, false on error</returns>
|
2023-04-19 12:04:25 -04:00
|
|
|
|
public bool ApplySplitting(DatFile datFile, bool useTags, bool throwOnError = false)
|
2020-12-09 21:52:38 -08:00
|
|
|
|
{
|
2023-04-19 16:39:58 -04:00
|
|
|
|
InternalStopwatch watch = new("Applying splitting to DAT");
|
2021-02-02 14:09:49 -08:00
|
|
|
|
|
2020-12-09 21:52:38 -08:00
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
// If we are using tags from the DAT, set the proper input for split type unless overridden
|
2021-02-01 11:43:38 -08:00
|
|
|
|
if (useTags && SplitType == MergingFlag.None)
|
2025-05-11 22:55:38 -04:00
|
|
|
|
SplitType = datFile.Header.GetStringFieldValue(Models.Metadata.Header.ForceMergingKey).AsMergingFlag();
|
2020-12-09 21:52:38 -08:00
|
|
|
|
|
|
|
|
|
|
// Run internal splitting
|
2021-02-01 11:43:38 -08:00
|
|
|
|
switch (SplitType)
|
2020-12-09 21:52:38 -08:00
|
|
|
|
{
|
2023-04-19 12:04:25 -04:00
|
|
|
|
// Standard
|
2020-12-09 21:52:38 -08:00
|
|
|
|
case MergingFlag.None:
|
|
|
|
|
|
// No-op
|
|
|
|
|
|
break;
|
2023-04-19 12:04:25 -04:00
|
|
|
|
case MergingFlag.Split:
|
2025-01-13 15:41:57 -05:00
|
|
|
|
datFile.ApplySplit();
|
2020-12-09 21:52:38 -08:00
|
|
|
|
break;
|
2023-04-19 12:04:25 -04:00
|
|
|
|
case MergingFlag.Merged:
|
2025-01-13 15:41:57 -05:00
|
|
|
|
datFile.ApplyMerged();
|
2020-12-09 21:52:38 -08:00
|
|
|
|
break;
|
|
|
|
|
|
case MergingFlag.NonMerged:
|
2025-01-13 15:41:57 -05:00
|
|
|
|
datFile.ApplyNonMerged();
|
2020-12-09 21:52:38 -08:00
|
|
|
|
break;
|
2023-04-19 12:04:25 -04:00
|
|
|
|
|
|
|
|
|
|
// Nonstandard
|
|
|
|
|
|
case MergingFlag.FullMerged:
|
2025-01-13 15:41:57 -05:00
|
|
|
|
datFile.ApplyFullyMerged();
|
2020-12-09 21:52:38 -08:00
|
|
|
|
break;
|
2023-04-19 12:04:25 -04:00
|
|
|
|
case MergingFlag.DeviceNonMerged:
|
2025-01-13 15:41:57 -05:00
|
|
|
|
datFile.ApplyDeviceNonMerged();
|
2023-04-19 12:04:25 -04:00
|
|
|
|
break;
|
|
|
|
|
|
case MergingFlag.FullNonMerged:
|
2025-01-13 15:41:57 -05:00
|
|
|
|
datFile.ApplyFullyNonMerged();
|
2020-12-09 21:52:38 -08:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2021-01-12 15:54:14 -08:00
|
|
|
|
catch (Exception ex) when (!throwOnError)
|
2020-12-09 21:52:38 -08:00
|
|
|
|
{
|
2025-01-08 16:59:44 -05:00
|
|
|
|
_staticLogger.Error(ex);
|
2020-12-09 21:52:38 -08:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2021-02-02 14:09:49 -08:00
|
|
|
|
finally
|
|
|
|
|
|
{
|
|
|
|
|
|
watch.Stop();
|
|
|
|
|
|
}
|
2020-12-09 21:52:38 -08:00
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-02-12 15:36:25 -05:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Apply SuperDAT naming logic to a merged DatFile
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="datFile">Current DatFile object to run operations on</param>
|
|
|
|
|
|
/// <param name="inputs">List of inputs to use for renaming</param>
|
|
|
|
|
|
public static void ApplySuperDAT(DatFile datFile, List<ParentablePath> inputs)
|
|
|
|
|
|
{
|
|
|
|
|
|
#if NET452_OR_GREATER || NETCOREAPP
|
|
|
|
|
|
Parallel.ForEach(datFile.Items.SortedKeys, Core.Globals.ParallelOptions, key =>
|
|
|
|
|
|
#elif NET40_OR_GREATER
|
|
|
|
|
|
Parallel.ForEach(datFile.Items.SortedKeys, key =>
|
|
|
|
|
|
#else
|
|
|
|
|
|
foreach (var key in datFile.Items.SortedKeys)
|
|
|
|
|
|
#endif
|
|
|
|
|
|
{
|
|
|
|
|
|
List<DatItem>? items = datFile.GetItemsForBucket(key);
|
|
|
|
|
|
if (items == null)
|
|
|
|
|
|
#if NET40_OR_GREATER || NETCOREAPP
|
|
|
|
|
|
return;
|
|
|
|
|
|
#else
|
|
|
|
|
|
continue;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
List<DatItem> newItems = [];
|
|
|
|
|
|
foreach (DatItem item in items)
|
|
|
|
|
|
{
|
|
|
|
|
|
DatItem newItem = item;
|
|
|
|
|
|
var source = newItem.GetFieldValue<Source?>(DatItem.SourceKey);
|
|
|
|
|
|
if (source == null)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
string filename = inputs[source.Index].CurrentPath;
|
|
|
|
|
|
string rootpath = inputs[source.Index].ParentPath ?? string.Empty;
|
|
|
|
|
|
|
|
|
|
|
|
if (rootpath.Length > 0
|
|
|
|
|
|
#if NETFRAMEWORK
|
|
|
|
|
|
&& !rootpath.EndsWith(Path.DirectorySeparatorChar.ToString())
|
|
|
|
|
|
&& !rootpath.EndsWith(Path.AltDirectorySeparatorChar.ToString()))
|
|
|
|
|
|
#else
|
|
|
|
|
|
&& !rootpath.EndsWith(Path.DirectorySeparatorChar)
|
|
|
|
|
|
&& !rootpath.EndsWith(Path.AltDirectorySeparatorChar))
|
|
|
|
|
|
#endif
|
|
|
|
|
|
{
|
|
|
|
|
|
rootpath += Path.DirectorySeparatorChar.ToString();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
filename = filename.Remove(0, rootpath.Length);
|
|
|
|
|
|
|
2025-05-02 16:46:20 -04:00
|
|
|
|
var machine = newItem.GetMachine();
|
2025-02-12 15:36:25 -05:00
|
|
|
|
if (machine == null)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
2025-04-01 16:25:22 -04:00
|
|
|
|
string machineName = Path.GetDirectoryName(filename)
|
2025-02-12 15:36:25 -05:00
|
|
|
|
+ Path.DirectorySeparatorChar
|
|
|
|
|
|
+ Path.GetFileNameWithoutExtension(filename)
|
|
|
|
|
|
+ Path.DirectorySeparatorChar
|
2025-05-02 16:05:08 -04:00
|
|
|
|
+ machine.GetName();
|
2025-04-01 16:25:22 -04:00
|
|
|
|
if (machineName.Length == 0)
|
|
|
|
|
|
machineName = "Default";
|
|
|
|
|
|
|
2025-05-02 16:05:08 -04:00
|
|
|
|
machine.SetName(machineName);
|
2025-02-12 15:36:25 -05:00
|
|
|
|
|
|
|
|
|
|
newItems.Add(newItem);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
datFile.RemoveBucket(key);
|
|
|
|
|
|
newItems.ForEach(item => datFile.AddItem(item, statsOnly: false));
|
|
|
|
|
|
#if NET40_OR_GREATER || NETCOREAPP
|
|
|
|
|
|
});
|
|
|
|
|
|
#else
|
|
|
|
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Apply SuperDAT naming logic to a merged DatFile
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="datFile">Current DatFile object to run operations on</param>
|
|
|
|
|
|
/// <param name="inputs">List of inputs to use for renaming</param>
|
|
|
|
|
|
public static void ApplySuperDATDB(DatFile datFile, List<ParentablePath> inputs)
|
|
|
|
|
|
{
|
|
|
|
|
|
List<string> keys = [.. datFile.ItemsDB.SortedKeys];
|
|
|
|
|
|
#if NET452_OR_GREATER || NETCOREAPP
|
|
|
|
|
|
Parallel.ForEach(keys, Core.Globals.ParallelOptions, key =>
|
|
|
|
|
|
#elif NET40_OR_GREATER
|
|
|
|
|
|
Parallel.ForEach(keys, key =>
|
|
|
|
|
|
#else
|
|
|
|
|
|
foreach (var key in keys)
|
|
|
|
|
|
#endif
|
|
|
|
|
|
{
|
|
|
|
|
|
var items = datFile.GetItemsForBucketDB(key);
|
|
|
|
|
|
if (items == null)
|
|
|
|
|
|
#if NET40_OR_GREATER || NETCOREAPP
|
|
|
|
|
|
return;
|
|
|
|
|
|
#else
|
|
|
|
|
|
continue;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var item in items)
|
|
|
|
|
|
{
|
2025-02-24 09:20:46 -05:00
|
|
|
|
var source = datFile.GetSourceForItemDB(item.Key);
|
2025-02-12 15:36:25 -05:00
|
|
|
|
if (source.Value == null)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
2025-02-24 09:20:46 -05:00
|
|
|
|
var machine = datFile.GetMachineForItemDB(item.Key);
|
2025-02-12 15:36:25 -05:00
|
|
|
|
if (machine.Value == null)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
string filename = inputs[source.Value.Index].CurrentPath;
|
|
|
|
|
|
string rootpath = inputs[source.Value.Index].ParentPath ?? string.Empty;
|
|
|
|
|
|
|
|
|
|
|
|
if (rootpath.Length > 0
|
|
|
|
|
|
#if NETFRAMEWORK
|
|
|
|
|
|
&& !rootpath!.EndsWith(Path.DirectorySeparatorChar.ToString())
|
|
|
|
|
|
&& !rootpath!.EndsWith(Path.AltDirectorySeparatorChar.ToString()))
|
|
|
|
|
|
#else
|
|
|
|
|
|
&& !rootpath.EndsWith(Path.DirectorySeparatorChar)
|
|
|
|
|
|
&& !rootpath.EndsWith(Path.AltDirectorySeparatorChar))
|
|
|
|
|
|
#endif
|
|
|
|
|
|
{
|
|
|
|
|
|
rootpath += Path.DirectorySeparatorChar.ToString();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
filename = filename.Remove(0, rootpath.Length);
|
|
|
|
|
|
|
2025-04-01 16:25:22 -04:00
|
|
|
|
string machineName = Path.GetDirectoryName(filename)
|
|
|
|
|
|
+ Path.DirectorySeparatorChar
|
|
|
|
|
|
+ Path.GetFileNameWithoutExtension(filename)
|
|
|
|
|
|
+ Path.DirectorySeparatorChar
|
2025-05-02 16:05:08 -04:00
|
|
|
|
+ machine.Value.GetName();
|
2025-04-01 16:25:22 -04:00
|
|
|
|
if (machineName.Length == 0)
|
|
|
|
|
|
machineName = "Default";
|
|
|
|
|
|
|
2025-05-02 16:05:08 -04:00
|
|
|
|
machine.Value.SetName(machineName);
|
2025-02-12 15:36:25 -05:00
|
|
|
|
}
|
|
|
|
|
|
#if NET40_OR_GREATER || NETCOREAPP
|
|
|
|
|
|
});
|
|
|
|
|
|
#else
|
|
|
|
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-12-09 21:52:38 -08:00
|
|
|
|
#endregion
|
|
|
|
|
|
}
|
2021-02-01 11:43:38 -08:00
|
|
|
|
}
|