mirror of
https://github.com/claunia/SabreTools.git
synced 2025-12-16 19:14:27 +00:00
Add Game diffing
This commit is contained in:
@@ -326,6 +326,14 @@ namespace SabreTools.Library.DatFiles
|
||||
DiffAgainst(inputFileNames, outDir, inplace);
|
||||
}
|
||||
|
||||
// If we are in game diffing mode
|
||||
else if (updateMode.HasFlag(UpdateMode.DiffGame))
|
||||
{
|
||||
// Populate the combined data
|
||||
PopulateUserData(baseFileNames, filter);
|
||||
DiffGame(inputFileNames, outDir, inplace, filter);
|
||||
}
|
||||
|
||||
// If we have one of the base replacement modes
|
||||
else if (updateMode.HasFlag(UpdateMode.BaseReplace)
|
||||
|| updateMode.HasFlag(UpdateMode.ReverseBaseReplace))
|
||||
@@ -406,6 +414,19 @@ namespace SabreTools.Library.DatFiles
|
||||
DiffNoCascade(paths, outDir, diff);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Output games that contain different items (by name)
|
||||
/// </summary>
|
||||
/// <param name="inputs">Names of the input files</param>
|
||||
/// <param name="outDir">Optional param for output directory</param>
|
||||
/// <param name="inplace">True if the output files should overwrite their inputs, false otherwise</param>
|
||||
/// <param name="filter">Filter object to be passed to the DatItem level</param>
|
||||
public void DiffGame(List<string> inputs, string outDir, bool inplace, Filter filter)
|
||||
{
|
||||
List<ParentablePath> paths = inputs.Select(i => new ParentablePath(i)).ToList();
|
||||
DiffGame(paths, outDir, inplace, filter);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Output user defined merge
|
||||
/// </summary>
|
||||
@@ -1226,6 +1247,70 @@ namespace SabreTools.Library.DatFiles
|
||||
watch.Stop();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replace item values from the base set represented by the current DAT
|
||||
/// </summary>
|
||||
/// <param name="inputs">Names of the input files</param>
|
||||
/// <param name="outDir">Optional param for output directory</param>
|
||||
/// <param name="inplace">True if the output files should overwrite their inputs, false otherwise</param>
|
||||
/// <param name="filter">Filter object to be passed to the DatItem level</param>
|
||||
/// <remarks>TODO: Can this be wrapped into DiffAgainst?</remarks>
|
||||
internal void DiffGame(List<ParentablePath> inputs, string outDir, bool inplace, Filter filter)
|
||||
{
|
||||
// Order the current DAT by game first
|
||||
Items.BucketBy(BucketedBy.Game, DedupeType.None);
|
||||
|
||||
// We want to try to replace each item in each input DAT from the base
|
||||
foreach (ParentablePath path in inputs)
|
||||
{
|
||||
Globals.Logger.User($"Comparing items in '{path.CurrentPath}' to the base DAT");
|
||||
|
||||
// First we parse in the DAT internally
|
||||
DatFile intDat = Create(Header.CloneFiltering());
|
||||
intDat.Parse(path, 1, keep: true);
|
||||
filter.FilterDatFile(intDat, false /* useTags */);
|
||||
intDat.Items.BucketBy(BucketedBy.Game, DedupeType.None);
|
||||
|
||||
// TODO: Do we need to include items in base NOT in compare?
|
||||
List<string> games = intDat.Items.Keys.ToList();
|
||||
foreach (string game in games)
|
||||
{
|
||||
// If the base DAT doesn't contain the key, keep it
|
||||
if (!Items.ContainsKey(game))
|
||||
continue;
|
||||
|
||||
// If the number of items is different, then keep it
|
||||
if (Items[game].Count != intDat.Items[game].Count)
|
||||
continue;
|
||||
|
||||
// Otherwise, compare by name and hash the remaining files
|
||||
bool exactMatch = true;
|
||||
foreach (DatItem item in intDat.Items[game])
|
||||
{
|
||||
// TODO: Make this granular to name as well
|
||||
if (!Items[game].Contains(item))
|
||||
{
|
||||
exactMatch = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If we have an exact match, remove the game
|
||||
if (exactMatch)
|
||||
intDat.Items.Remove(game);
|
||||
}
|
||||
|
||||
// Determine the output path for the DAT
|
||||
string interOutDir = path.GetOutputPath(outDir, inplace);
|
||||
|
||||
// Once we're done, try writing out
|
||||
intDat.Write(interOutDir, overwrite: inplace);
|
||||
|
||||
// Due to possible memory requirements, we force a garbage collection
|
||||
GC.Collect();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Output user defined merge
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user