Skip to content

Commit 34ee6ac

Browse files
authored
Merge pull request #44 from KSP2Community/turbo-patching
Speed up patch manager
2 parents 784bb42 + 4977a84 commit 34ee6ac

File tree

64 files changed

+842
-386
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+842
-386
lines changed

Runtime/Core/Assets/PatchingManager.cs

Lines changed: 67 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
using PatchManager.Core.Cache.Json;
99
using PatchManager.Core.Utility;
1010
using PatchManager.SassyPatching.Execution;
11+
using PatchManager.SassyPatching.Interfaces;
1112
using PatchManager.Shared;
12-
using PatchManager.Shared.Interfaces;
1313
using SpaceWarp.API.Mods;
1414
using UniLinq;
1515
using UnityEngine;
@@ -20,14 +20,12 @@ namespace PatchManager.Core.Assets
2020
{
2121
internal static class PatchingManager
2222
{
23-
internal static readonly List<ITextPatcher> Patchers = new();
24-
internal static readonly List<ITextAssetGenerator> Generators = new();
2523
internal static Universe Universe;
2624

2725
private static readonly PatchHashes CurrentPatchHashes = PatchHashes.CreateDefault();
2826

2927
private static int _initialLibraryCount;
30-
private static Dictionary<string, List<(string name, string text)>> _createdAssets = new();
28+
private static Dictionary<string, List<(string name, ISelectable data)>> _createdAssets = new();
3129

3230
internal static int TotalPatchCount;
3331
internal static int TotalErrorCount;
@@ -36,81 +34,74 @@ public static void GenerateUniverse(HashSet<string> singleFileModIds)
3634
{
3735
var loadedPlugins = PluginList.AllEnabledAndActivePlugins.Select(x => x.Guid).ToList();
3836
loadedPlugins.AddRange(singleFileModIds);
39-
Universe = new(RegisterPatcher, Logging.LogError, Logging.LogMessage, RegisterGenerator,
37+
Universe = new(Logging.LogError, Logging.LogMessage,
4038
loadedPlugins);
4139
_initialLibraryCount = Universe.AllLibraries.Count;
4240
}
4341

44-
private static void RegisterPatcher(ITextPatcher patcher)
45-
{
46-
for (var index = 0; index < Patchers.Count; index++)
47-
{
48-
if (Patchers[index].Priority <= patcher.Priority)
49-
{
50-
continue;
51-
}
42+
// private static void RegisterPatcher(ITextPatcher patcher)
43+
// {
44+
// for (var index = 0; index < Patchers.Count; index++)
45+
// {
46+
// if (Patchers[index].Priority <= patcher.Priority)
47+
// {
48+
// continue;
49+
// }
50+
//
51+
// Patchers.Insert(index, patcher);
52+
// return;
53+
// }
54+
//
55+
// Patchers.Add(patcher);
56+
// }
57+
//
58+
// private static void RegisterGenerator(ITextAssetGenerator generator)
59+
// {
60+
// for (var index = 0; index < Generators.Count; index++)
61+
// {
62+
// if (Generators[index].Priority <= generator.Priority)
63+
// {
64+
// continue;
65+
// }
66+
//
67+
// Generators.Insert(index, generator);
68+
// return;
69+
// }
70+
//
71+
// Generators.Add(generator);
72+
// }
5273

53-
Patchers.Insert(index, patcher);
54-
return;
55-
}
56-
57-
Patchers.Add(patcher);
58-
}
59-
60-
private static void RegisterGenerator(ITextAssetGenerator generator)
74+
private static string PatchJson(string label, string assetName, string text)
6175
{
62-
for (var index = 0; index < Generators.Count; index++)
63-
{
64-
if (Generators[index].Priority <= generator.Priority)
65-
{
66-
continue;
67-
}
76+
Logging.LogInfo($"Patching {label}:{assetName}");
6877

69-
Generators.Insert(index, generator);
70-
return;
78+
text = Universe.RunAllPatchesFor(label, assetName, text, out var patchCount, out var errorCount);
79+
TotalErrorCount += errorCount;
80+
TotalPatchCount += patchCount;
81+
if (patchCount > 0)
82+
{
83+
Logging.LogInfo($"Patched {label}:{assetName} with {patchCount} patches. Total: {TotalPatchCount}");
7184
}
7285

73-
Generators.Add(generator);
86+
return text;
7487
}
75-
76-
private static string PatchJson(string label, string assetName, string text)
88+
89+
private static string PatchJson(string label, string assetName, ISelectable data)
7790
{
78-
Console.WriteLine($"Patching {label}:{assetName}");
79-
var patchCount = 0;
80-
81-
foreach (var patcher in Patchers)
82-
{
83-
var backup = text;
84-
try
85-
{
86-
var wasPatched = patcher.TryPatch(label, assetName, ref text);
87-
if (wasPatched)
88-
{
89-
patchCount++;
90-
}
91-
}
92-
catch (Exception e)
93-
{
94-
TotalErrorCount += 1;
95-
Console.WriteLine($"Patch of {label}:{assetName} errored due to: {e}");
96-
text = backup;
97-
}
98-
99-
if (text == "")
100-
{
101-
break;
102-
}
103-
}
91+
Logging.LogInfo($"Patching {label}:{assetName}");
10492

93+
var text = Universe.RunAllPatchesFor(label, assetName, data, out var patchCount, out var errorCount);
94+
TotalErrorCount += errorCount;
10595
TotalPatchCount += patchCount;
10696
if (patchCount > 0)
10797
{
108-
Console.WriteLine($"Patched {label}:{assetName} with {patchCount} patches. Total: {TotalPatchCount}");
98+
Logging.LogInfo($"Patched {label}:{assetName} with {patchCount} patches. Total: {TotalPatchCount}");
10999
}
110100

111101
return text;
112102
}
113103

104+
114105
private static int _previousLibraryCount = -1;
115106

116107
public static void ImportModPatches(string modName, string modFolder)
@@ -150,8 +141,8 @@ public static void RegisterPatches()
150141
{
151142
Logging.LogInfo($"Registering all patches!");
152143
Universe.RegisterAllPatches();
153-
Logging.LogInfo($"{Patchers.Count} patchers registered!");
154-
Logging.LogInfo($"{Generators.Count} generators registered!");
144+
Logging.LogInfo($"{Universe.TotalPatchCount} patchers registered!");
145+
Logging.LogInfo($"{Universe.Generators.Count} generators registered!");
155146
}
156147

157148
/// <summary>
@@ -241,7 +232,7 @@ private static AsyncOperationHandle<IList<TextAsset>> RebuildCache(string label)
241232
}
242233
catch (Exception e)
243234
{
244-
Console.WriteLine($"Unable to patch {asset.name} due to: {e.Message}");
235+
Logging.LogError($"Unable to patch {asset.name} due to: {e.Message}, {e.StackTrace}");
245236
}
246237
});
247238

@@ -261,7 +252,7 @@ void SaveArchive()
261252
CacheManager.Inventory.CacheEntries.AddRangeUnique(assetsCacheEntries);
262253
CacheManager.SaveInventory();
263254

264-
Console.WriteLine($"Cache for label '{label}' rebuilt.");
255+
Logging.LogInfo($"Cache for label '{label}' rebuilt.");
265256
}
266257

267258
if (handle.Status == AsyncOperationStatus.Failed && !unchanged)
@@ -285,21 +276,21 @@ void SaveArchive()
285276

286277
public static void CreateNewAssets(Action resolve, Action<string> reject)
287278
{
288-
foreach (var generator in Generators)
279+
foreach (var generator in Universe.Generators)
289280
{
290281
try
291282
{
292-
var text = generator.Create(out var label, out var name);
293-
Logging.LogDebug($"Generated an asset with the label {label}, and name {name}:\n{text}");
283+
var data = generator.Create(out var label, out var name);
284+
Logging.LogDebug($"Generated an asset with the label {label}, and name {name}:\n{data}");
294285

295286
if (!_createdAssets.ContainsKey(label))
296287
{
297-
_createdAssets[label] = new List<(string name, string text)>();
288+
_createdAssets[label] = new List<(string name, ISelectable data)>();
298289
}
299290

300291
if (!_createdAssets[label].Any(x => x.name == name))
301292
{
302-
_createdAssets[label].Add((name, text));
293+
_createdAssets[label].Add((name, data));
303294
}
304295

305296
}
@@ -327,29 +318,19 @@ GenericFlowAction CreateIndexedFlowAction(int idx)
327318
(resolve2, _) =>
328319
{
329320
var handle = RebuildCache(distinctKeys[idx]);
330-
var killTips = false;
331-
if (idx + 1 < distinctKeys.Count)
332-
{
333-
GameManager.Instance.LoadingFlow.FlowActions.Insert(
334-
GameManager.Instance.LoadingFlow.flowIndex + 1,
335-
CreateIndexedFlowAction(idx + 1)
336-
);
337-
}
338-
else
339-
{
340-
killTips = true;
341-
}
342-
343-
CoroutineUtil.Instance.DoCoroutine(WaitForCacheRebuildSingleHandle(handle, resolve2, killTips));
321+
CoroutineUtil.Instance.DoCoroutine(WaitForCacheRebuildSingleHandle(handle, resolve2, idx + 1 == distinctKeys.Count));
344322
});
345323
}
346324

347325
if (distinctKeys.Count > 0)
348326
{
349-
GameManager.Instance.LoadingFlow.FlowActions.Insert(
350-
GameManager.Instance.LoadingFlow.flowIndex + 1,
351-
CreateIndexedFlowAction(0)
352-
);
327+
for (var i = distinctKeys.Count - 1; i >= 0; i--)
328+
{
329+
GameManager.Instance.LoadingFlow.FlowActions.Insert(
330+
GameManager.Instance.LoadingFlow.flowIndex + 1,
331+
CreateIndexedFlowAction(i)
332+
);
333+
}
353334
}
354335

355336
resolve();

Runtime/Core/CoreModule.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,8 @@ public override VisualElement GetDetails()
171171
visible = true
172172
};
173173
var text = new TextElement();
174-
text.text += $"Amount of loaded patchers: {PatchingManager.Patchers.Count}\n";
175-
text.text += $"Amount of loaded generators: {PatchingManager.Generators.Count}\n";
174+
text.text += $"Amount of loaded patchers: {PatchingManager.Universe.TotalPatchCount}\n";
175+
text.text += $"Amount of loaded generators: {PatchingManager.Universe.Generators.Count}\n";
176176
text.text += $"Amount of loaded libraries: {PatchingManager.Universe.AllLibraries.Count}\n";
177177
if (_wasCacheInvalidated)
178178
{

Runtime/Generic/SassyPatching/Rulesets/JsonRuleset.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,23 @@ public bool Matches(string label)
2020
return true;
2121
}
2222

23+
public string[] Labels => null;
24+
2325
/// <inheritdoc />
2426
public ISelectable ConvertToSelectable(string type, string name, string jsonData)
2527
{
2628
return new JTokenSelectable(() => { }, JToken.Parse(jsonData), name, type);
2729
}
2830

31+
public bool CanIngestSelectable(ISelectable selectable) => selectable is JTokenSelectable;
32+
33+
public bool CanGetAssetNameFromSelectableName => false;
34+
35+
public string SelectableNameToAssetName(string selectableName)
36+
{
37+
throw new System.NotImplementedException();
38+
}
39+
2940
/// <inheritdoc />
3041
public INewAsset CreateNew(List<DataValue> dataValues)
3142
{

Runtime/Missions/Rulesets/MissionRuleset.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,22 @@ namespace PatchManager.Missions.Rulesets
1616
public class MissionRuleset : IPatcherRuleSet
1717
{
1818
/// <inheritdoc/>
19-
public bool Matches(string label) => label == "missions";
19+
public string[] Labels => new[] { "missions" };
2020

2121
/// <inheritdoc/>
2222
public ISelectable ConvertToSelectable(string type, string name, string jsonData) =>
2323
new MissionSelectable(JObject.Parse(jsonData));
2424

25+
public bool CanIngestSelectable(ISelectable selectable) => selectable is MissionSelectable
26+
{
27+
Deleted: false
28+
};
29+
30+
// TODO: Validate
31+
public bool CanGetAssetNameFromSelectableName => true;
32+
33+
public string SelectableNameToAssetName(string selectableName) => selectableName;
34+
2535
/// <inheritdoc/>
2636
public INewAsset CreateNew(List<DataValue> dataValues)
2737
{

Runtime/Missions/Selectables/ActionsSelectable.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,16 @@ public sealed class ActionsSelectable : BaseSelectable
2323
/// </summary>
2424
public JArray Actions;
2525

26+
public void SetModified()
27+
{
28+
Selectable.SetModified();
29+
}
30+
31+
public override bool WasModified => Selectable.WasModified;
32+
public override void ClearModified()
33+
{
34+
}
35+
2636
private static string TrimTypeName(string typeName)
2737
{
2838
var comma = typeName.IndexOf(',');
@@ -97,11 +107,12 @@ public override bool IsSameAs(ISelectable other) =>
97107
other is ActionsSelectable actionsSelectable && actionsSelectable.Actions == Actions;
98108

99109
/// <inheritdoc />
100-
public override IModifiable OpenModification() => new JTokenModifiable(Actions, Selectable.SetModified);
110+
public override IModifiable OpenModification() => new JTokenModifiable(Actions, SetModified);
101111

102112
/// <inheritdoc />
103113
public override ISelectable AddElement(string elementType)
104114
{
115+
SetModified();
105116
var actualType = MissionsTypes.Actions[elementType];
106117
var elementObject = new JObject()
107118
{
@@ -112,7 +123,7 @@ public override ISelectable AddElement(string elementType)
112123
elementObject[key] = value;
113124
}
114125

115-
var selectable = new JTokenSelectable(Selectable.SetModified, elementObject,
126+
var selectable = new JTokenSelectable(SetModified, elementObject,
116127
token => TrimTypeName(((JObject)token)!.Value<string>()!), elementType);
117128
Children.Add(selectable);
118129
Classes.Add(elementType);

Runtime/Missions/Selectables/ConditionSetSelectable.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ public sealed class ConditionSetSelectable : BaseSelectable
2929
/// </summary>
3030
private JArray _children;
3131

32+
public void SetModified()
33+
{
34+
MissionSelectable.SetModified();
35+
}
36+
37+
public override bool WasModified => MissionSelectable.WasModified;
38+
public override void ClearModified()
39+
{
40+
}
41+
3242
/// <summary>
3343
/// Create a new condition set selectable
3444
/// </summary>
@@ -97,11 +107,12 @@ public override bool IsSameAs(ISelectable other) => other is ConditionSetSelecta
97107
conditionSetSelectable.ConditionSet == ConditionSet;
98108

99109
/// <inheritdoc />
100-
public override IModifiable OpenModification() => new JTokenModifiable(ConditionSet, MissionSelectable.SetModified);
110+
public override IModifiable OpenModification() => new JTokenModifiable(ConditionSet, SetModified);
101111

102112
/// <inheritdoc />
103113
public override ISelectable AddElement(string elementType)
104114
{
115+
SetModified();
105116
var conditionType = MissionsTypes.Conditions[elementType];
106117
var conditionObject = new JObject()
107118
{
@@ -121,7 +132,7 @@ public override ISelectable AddElement(string elementType)
121132
}
122133
else
123134
{
124-
var selectable = new JTokenSelectable(MissionSelectable.SetModified, conditionObject,
135+
var selectable = new JTokenSelectable(SetModified, conditionObject,
125136
"scriptableCondition", "scriptableCondition");
126137
Children.Add(selectable);
127138
return selectable;

0 commit comments

Comments
 (0)