forked from AnotherSymbiote/WitcherScriptMerger
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathModFileIndex.cs
More file actions
158 lines (142 loc) · 5.52 KB
/
Copy pathModFileIndex.cs
File metadata and controls
158 lines (142 loc) · 5.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using WitcherScriptMerger.Inventory;
using WitcherScriptMerger.Tools;
namespace WitcherScriptMerger.FileIndex
{
public class ModFileIndex
{
public List<ModFile> Files;
public IEnumerable<ModFile> Conflicts => Files.Where(f => f.HasConflict);
public bool HasConflict => Files.Any(f => f.HasConflict);
public int ModCount { get; private set; }
public int ScriptCount { get; private set; }
public int XmlCount { get; private set; }
public int BundleCount { get; private set; }
public ModFileIndex()
{
Files = new List<ModFile>();
}
public void BuildAsync(
bool checkScripts, bool checkXml, bool checkBundles,
ProgressChangedEventHandler progressHandler,
RunWorkerCompletedEventHandler completedHandler)
{
var ignoredModNames = GetIgnoredModNames();
var modDirPaths = Directory.GetDirectories(Paths.ModsDirectory, "mod*", SearchOption.TopDirectoryOnly)
.Where(path => !ignoredModNames.Any(name => name.EqualsIgnoreCase(new DirectoryInfo(path).Name)))
.ToList();
ModCount = modDirPaths.Count;
if (ModCount == 0)
{
AppState.Notifier.ShowMessage("Can't find any mods in the Mods directory.");
}
// Checked once up front, not per bundle: QuickBms.GetBundleContentPaths already
// reports (and now tolerates - see its own comment) a missing QuickBMS/wcc_lite
// per bundle it's asked about, but that's needlessly noisy across a whole scan,
// and WitcherScriptMerger.Headless (the Linux-capable CLI/MCP-only host, no
// QuickBMS/wcc_lite bundled at all - see its CLAUDE.md section) deliberately
// doesn't gate scanning on Paths.ValidateDependencyPaths() first, so this is the
// first point in a scan where that host's missing bundle tooling surfaces. One
// clear message beats one per bundle. BundleCount (below) still counts every
// *.bundle file found regardless of whether checking could proceed - unchanged
// from before this gate, and consistent with ScriptCount/XmlCount, which also
// count regardless of checkScripts/checkXml - only the actual per-file
// conflict-scanning loop is skipped here.
var canCheckBundles = checkBundles && QuickBms.IsAvailable;
if (checkBundles && !canCheckBundles)
{
AppState.Notifier.ShowMessage(
"Bundle-content conflicts aren't supported without QuickBMS and wcc_lite configured - skipping bundle-content checking for this scan.",
"Bundle Checking Unavailable",
NotifyButtons.OK,
DialogIcon.Warning);
}
var bgWorker = new BackgroundWorker
{
WorkerReportsProgress = true
};
bgWorker.DoWork += (sender, e) =>
{
var i = 0;
ScriptCount = XmlCount = BundleCount = 0;
foreach (var modDirPath in modDirPaths)
{
var modName = Path.GetFileName(modDirPath);
var filePaths = Directory.GetFiles(modDirPath, "*", SearchOption.AllDirectories);
var scriptPaths = filePaths.Where(path => ModFile.IsScript(path));
var xmlPaths = filePaths.Where(path => ModFile.IsXml(path));
var bundlePaths = filePaths.Where(path => ModFile.IsBundle(path));
ScriptCount += scriptPaths.Count();
XmlCount += xmlPaths.Count();
BundleCount += bundlePaths.Count();
if (checkScripts)
{
Files.AddRange(GetModFilesFromPaths(scriptPaths, Categories.Script, modName));
}
if (checkXml)
{
Files.AddRange(GetModFilesFromPaths(xmlPaths, Categories.Xml, modName));
}
if (canCheckBundles)
{
foreach (var bundlePath in bundlePaths)
{
var contentPaths = QuickBms.GetBundleContentPaths(bundlePath);
Files.AddRange(GetModFilesFromPaths(contentPaths, Categories.BundleText, modName, bundlePath));
}
}
var progressPct = (int)((float)++i / modDirPaths.Count * 100f);
bgWorker.ReportProgress(progressPct, modName as object);
}
if (canCheckBundles)
System.Threading.Thread.Sleep(500); // Wait for progress bar to fill completely
};
bgWorker.RunWorkerCompleted += completedHandler;
bgWorker.ProgressChanged += progressHandler;
bgWorker.RunWorkerAsync();
}
private List<ModFile> GetModFilesFromPaths(
IEnumerable<string> filePaths,
ModFileCategory category,
string modName, string bundlePath = null)
{
var fileList = new List<ModFile>();
foreach (var filePath in filePaths)
{
string relPath = null;
if (category == Categories.Script)
relPath = Paths.GetRelativePath(filePath, Paths.ModScriptBase);
else if (category == Categories.Xml)
relPath = Paths.GetRelativePath(filePath, modName);
else if (category == Categories.BundleText)
relPath = filePath;
else
throw new NotImplementedException();
var existingFile = Files.FirstOrDefault(file =>
file.RelativePath.EqualsIgnoreCase(relPath));
if (existingFile == null)
{
var newFile = (bundlePath != null
? new ModFile(relPath, bundlePath)
: new ModFile(relPath));
newFile.Mods.Add(new FileHash { Name = modName });
fileList.Add(newFile);
}
else
existingFile.Mods.Add(new FileHash { Name = modName });
}
return fileList;
}
private IEnumerable<string> GetIgnoredModNames()
{
var ignoredNames = AppState.Settings.Get("IgnoreModNames");
return ignoredNames.Split(',')
.Where(name => !string.IsNullOrWhiteSpace(name))
.Select(name => name.Trim());
}
}
}