Skip to content

Commit d717f3b

Browse files
committed
harden IL patch
guard against unfounded load order assumtions
1 parent 6e3c9ef commit d717f3b

7 files changed

Lines changed: 59 additions & 8 deletions

File tree

Source/ModSwitch/ModSwitch.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Linq;
1+
using System.Collections.Generic;
2+
using System.Linq;
23
using System.Reflection;
34

45
using HarmonyLib;
@@ -28,6 +29,16 @@ public ModSwitch(ModContentPack content) : base(content) {
2829
Log.Message($"ModSwitch {assembly.GetName().Version} - initialized patches...");
2930

3031
CustomSettings = GetSettings<Settings>();
32+
33+
if (ModsConfigUI.Helpers.PreInitTSUpdateCache.Count != null) {
34+
var entries = ModsConfigUI.Helpers.PreInitTSUpdateCache.ToArray();
35+
ModsConfigUI.Helpers.PreInitTSUpdateCache.Clear();
36+
Log.Message($"ModSwitch - copying cached steam TS values.");
37+
38+
foreach (KeyValuePair<string, uint> cachedTSValue in entries) {
39+
CustomSettings.Attributes[cachedTSValue.Key].LastUpdateTS = cachedTSValue.Value;
40+
}
41+
}
3142
}
3243

3344
public Settings CustomSettings { get; }

Source/ModSwitch/ModSwitch.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@
9090
<Compile Include="[Util]\Position.cs" />
9191
<Compile Include="[Util]\Scribe.cs" />
9292
<Compile Include="[Util]\Util.cs" />
93-
<None Include="[Patches]\Patches.cs" />
93+
<Compile Include="[Patches]\Patches.cs" />
9494
<Compile Include="[Util]\Linq.cs" />
9595
<Compile Include="[Util]\Widgets.cs" />
9696
</ItemGroup>

Source/ModSwitch/Properties/AssemblyInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@
1212
[assembly: System.Reflection.AssemblyCopyright("Copyright © DoctorVanGogh 2017")]
1313
[assembly: System.Runtime.InteropServices.ComVisible(false)]
1414
[assembly: System.Runtime.InteropServices.Guid("ab2e8e89-3d1d-4e36-a0ae-489b6ebc84a6")]
15-
[assembly: System.Reflection.AssemblyVersion("2.0.3.294")]
15+
[assembly: System.Reflection.AssemblyVersion("2.0.3.299")]
1616

1717

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.0.3.294
1+
2.0.3.299

Source/ModSwitch/[Patches]/Patches.cs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Reflection.Emit;
66
using HarmonyLib;
77
using RimWorld;
8+
using Steamworks;
89
using UnityEngine;
910
using Verse;
1011
using Verse.Steam;
@@ -235,6 +236,7 @@ public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstructio
235236
List<CodeInstruction> instructions = new List<CodeInstruction>(instr);
236237

237238
ConstructorInfo ciTarget = AccessTools.Constructor(typeof(WorkshopItem_Mod));
239+
MethodInfo miAnchor = AccessTools.DeclaredMethod(typeof(SteamUGC), nameof(SteamUGC.GetItemInstallInfo));
238240

239241
int idxAnchor = instructions.FirstIndexOf(ci => ci.opcode == OpCodes.Newobj && ci.operand == ciTarget);
240242

@@ -243,18 +245,43 @@ public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstructio
243245
return instructions;
244246
}
245247

248+
249+
250+
int idxGetItemInstallInfo = instructions.FirstIndexOf(ci => ci.opcode == OpCodes.Call && ci.operand == miAnchor);
251+
if (idxGetItemInstallInfo == -1) {
252+
Util.Warning("Could not find SteamUGC.GetItemInstallInfo transpiler anchor - not injecting code");
253+
return instructions;
254+
}
255+
256+
Log.Message($"operand: {instructions[idxGetItemInstallInfo - 1].operand.GetType()}");
257+
258+
LocalBuilder lbTS = null;
259+
var opcode = instructions[idxGetItemInstallInfo - 1].opcode;
260+
if (opcode == OpCodes.Ldloca || opcode == OpCodes.Ldloca_S) {
261+
lbTS = (LocalBuilder) instructions[idxGetItemInstallInfo - 1].operand;
262+
} else {
263+
Util.Warning("Could not find SteamUGC.GetItemInstallInfo TS local - not injecting code");
264+
return instructions;
265+
}
266+
246267
/* Transform
268+
* ...
269+
* SteamUGC.GetItemInstallInfo(..., out [foo]);
270+
*
271+
* ...
247272
*
248273
* if (workshopItem == null)
249274
* {
250275
* workshopItem = new WorkshopItem_Mod();
251276
* }
252277
*
253278
* into
254-
*
279+
* ...
280+
* SteamUGC.GetItemInstallInfo(..., out [foo]);
281+
* ....
255282
* if (workshopItem == null)
256283
* {
257-
* ModsConfigUI.UpdateSteamTS(pfid, num2);
284+
* ModsConfigUI.UpdateSteamTS(pfid, [foo]);
258285
* workshopItem = new WorkshopItem_Mod();
259286
* }
260287
*
@@ -264,7 +291,7 @@ public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstructio
264291
idxAnchor,
265292
new[] {
266293
new CodeInstruction(OpCodes.Ldarg_0),
267-
new CodeInstruction(OpCodes.Ldloc_2),
294+
new CodeInstruction(OpCodes.Ldloc, lbTS),
268295
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(ModsConfigUI.Helpers), nameof(ModsConfigUI.Helpers.UpdateSteamTS)))
269296
}
270297
);

Source/ModSwitch/[UI]/ModsConfigUI.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Concurrent;
23
using System.Collections.Generic;
34
using System.Diagnostics;
45
using System.IO;
@@ -379,6 +380,9 @@ private static void UpdateSteamAttributes(string name, ModMetaData original, Str
379380

380381

381382
public static class Helpers {
383+
384+
public static IDictionary<string, uint> PreInitTSUpdateCache = new ConcurrentDictionary<string, uint>();
385+
382386
public static string ExplainError(string label, string error) {
383387
return $"{label} *{error}*";
384388
}
@@ -404,7 +408,16 @@ public static Color SetGUIColorMod(ModMetaData mod) {
404408
}
405409

406410
public static void UpdateSteamTS(PublishedFileId_t pfid, uint ts) {
407-
LoadedModManager.GetMod<ModSwitch>().CustomSettings.Attributes[pfid.ToString()].LastUpdateTS = ts;
411+
var modModSwitch = LoadedModManager.GetMod<ModSwitch>();
412+
413+
if (modModSwitch != null) {
414+
modModSwitch.CustomSettings.Attributes[pfid.ToString()].LastUpdateTS = ts;
415+
} else {
416+
if (PreInitTSUpdateCache.Count == 0) {
417+
Log.Message("ModSwitch: Mod yet loaded, but already getting steam update values - caching until mod initialization.");
418+
}
419+
PreInitTSUpdateCache[pfid.ToString()] = ts;
420+
}
408421
}
409422

410423
public static string WrapTimestamp(long? timestamp) {

v1.1/Assemblies/ModSwitch.dll

11 KB
Binary file not shown.

0 commit comments

Comments
 (0)