Skip to content

Commit 4e82b5e

Browse files
committed
feat(diagnostics): include Workshop IDs in mod inventories
- Add Workshop item IDs to startup logs, self-check bundles, telemetry, and multiplayer diagnostic lists when available. - Prefer native mod metadata while retaining path-based discovery for older supported game versions.
1 parent 2f3fa1a commit 4e82b5e

8 files changed

Lines changed: 53 additions & 16 deletions

File tree

‎schemas/telemetry/v1/openapi.yaml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,9 @@ components:
305305
type: string
306306
source:
307307
type: string
308+
workshop_id:
309+
type: integer
310+
minimum: 1
308311
affects_gameplay:
309312
type: boolean
310313
assembly:

‎src/Compat/Sts2ModManagerCompat.cs‎

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ internal static class Sts2ModManagerCompat
2929
private static readonly Func<Mod, IReadOnlyList<LocString>> ReadErrors = CreateModErrorsAccessor();
3030
private static readonly Func<Mod, string> ReadSource = CreateModSourceAccessor();
3131
private static readonly Func<Mod, string?> ReadPath = CreateModPathAccessor();
32+
private static readonly Func<Mod, ulong?> ReadWorkshopItemId = CreateModWorkshopItemIdAccessor();
3233
private static readonly Func<Mod, int, string> ReadLoadState = CreateLoadStateAccessor();
3334

3435
private static readonly Func<ModManifest, string?> ReadManifestId =
@@ -304,11 +305,16 @@ .. EnumerateModsForManifestLookup()
304305
ArgumentNullException.ThrowIfNull(mod);
305306
try
306307
{
307-
if (SteamWorkshopInstallSource.TryGetWorkshopItemIdFromPath(ReadPath(mod), out var pathItemId))
308+
if (ReadWorkshopItemId(mod) is { } workshopItemId && workshopItemId > 0)
309+
return workshopItemId;
310+
311+
if (SteamWorkshopInstallSource.TryGetWorkshopItemIdFromPath(ReadPath(mod), out var pathItemId) &&
312+
pathItemId > 0)
308313
return pathItemId;
309314

310315
foreach (var assembly in ReadAssemblies(mod))
311-
if (SteamWorkshopInstallSource.TryGetWorkshopItemIdFromAssembly(assembly, out var assemblyItemId))
316+
if (SteamWorkshopInstallSource.TryGetWorkshopItemIdFromAssembly(assembly, out var assemblyItemId) &&
317+
assemblyItemId > 0)
312318
return assemblyItemId;
313319
}
314320
catch (Exception ex)
@@ -378,7 +384,8 @@ internal static bool TryGetBestModPresentationInfoForAssembly(Assembly assembly,
378384
assemblyName?.Name,
379385
assemblyName?.Version?.ToString(),
380386
errors,
381-
CommonIncompatibleModRegistry.IsMatch(assemblies));
387+
CommonIncompatibleModRegistry.IsMatch(assemblies),
388+
TryGetWorkshopItemId(mod));
382389
}
383390
catch (Exception ex)
384391
{
@@ -639,6 +646,12 @@ private static Func<Mod, string> CreateModSourceAccessor()
639646
return mod => getter?.Invoke(mod) as string;
640647
}
641648

649+
private static Func<Mod, ulong?> CreateModWorkshopItemIdAccessor()
650+
{
651+
var getter = CreateUntypedMemberGetter(typeof(Mod), "workshopId");
652+
return mod => getter?.Invoke(mod) as ulong?;
653+
}
654+
642655
private static Func<Mod, int, string> CreateLoadStateAccessor()
643656
{
644657
if (typeof(Mod).GetField("state", InstanceMemberFlags) != null)
@@ -754,7 +767,8 @@ internal sealed record Sts2ModInventoryEntry(
754767
string? AssemblyName,
755768
string? AssemblyVersion,
756769
IReadOnlyList<LocString> Errors,
757-
bool IsCommonIncompatibleMod);
770+
bool IsCommonIncompatibleMod,
771+
ulong? WorkshopItemId);
758772

759773
internal sealed record Sts2LoadedModAssemblyEntry(
760774
string Id,

‎src/Diagnostics/SelfCheckBundleWriter.Artifacts.cs‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ private static void WriteModInventory(
258258
var target = GetBundlePath(bundleDir, "diagnostics/mod_inventory.tsv");
259259
var sb = new StringBuilder();
260260
sb.AppendLine(
261-
"scope\tid\tname\tversion\tstate\tsource\taffectsGameplay\tassemblyName\tassemblyVersion\terrorCount\terrors");
261+
"scope\tid\tname\tversion\tstate\tsource\tworkshopId\taffectsGameplay\tassemblyName\tassemblyVersion\terrorCount\terrors");
262262

263263
foreach (var mod in Sts2ModManagerCompat.BuildLoadedModInventoryEntries()
264264
.OrderBy(x => x.Id, StringComparer.OrdinalIgnoreCase))
@@ -495,6 +495,7 @@ private static void AppendModInventoryLine(StringBuilder sb, string scope, Sts2M
495495
EscapeTsv(mod.Version),
496496
EscapeTsv(mod.State),
497497
EscapeTsv(mod.Source),
498+
EscapeTsv(mod.WorkshopItemId?.ToString()),
498499
EscapeTsv(mod.AffectsGameplay.ToString()),
499500
EscapeTsv(mod.AssemblyName),
500501
EscapeTsv(mod.AssemblyVersion),

‎src/Diagnostics/StartupModListLogger.cs‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,8 @@ private static void TryLogStartupModList()
117117
else
118118
{
119119
foreach (var mod in loadedMods)
120-
text.AppendLine($" * {FormatModName(mod)} ({FormatVersion(mod)})");
120+
text.AppendLine($" * {FormatModName(mod)} ({FormatVersion(mod)})" +
121+
FormatWorkshopItemId(mod));
121122

122123
var commonIncompatibleMods = registeredMods
123124
.Where(static mod => mod.IsCommonIncompatibleMod)
@@ -127,7 +128,8 @@ private static void TryLogStartupModList()
127128
text.AppendLine("Common Incompatible Mods:");
128129
foreach (var mod in commonIncompatibleMods)
129130
text.AppendLine($" * {FormatModName(mod)} ({FormatVersion(mod)}) " +
130-
$"state={mod.State} source={mod.Source}");
131+
$"state={mod.State} source={mod.Source}" +
132+
FormatWorkshopItemId(mod));
131133
}
132134
}
133135

@@ -163,5 +165,10 @@ private static string FormatVersion(Sts2ModInventoryEntry mod)
163165
{
164166
return string.IsNullOrWhiteSpace(mod.Version) ? "unknown version" : mod.Version.Trim();
165167
}
168+
169+
private static string FormatWorkshopItemId(Sts2ModInventoryEntry mod)
170+
{
171+
return mod.WorkshopItemId.HasValue ? $" workshopId={mod.WorkshopItemId.Value}" : "";
172+
}
166173
}
167174
}

‎src/Networking/JoinDiagnostics/JoinFailureDiagnosticsPanel.cs‎

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1212,7 +1212,8 @@ private static Color ValueColor(string value, bool differs)
12121212

12131213
private static string FormatModLine(JoinDiagnosticsModEntry mod)
12141214
{
1215-
return FormatModName(mod) + " version=" + FormatVersion(mod.Version);
1215+
var workshop = mod.WorkshopItemId.HasValue ? " workshop=" + mod.WorkshopItemId.Value : "";
1216+
return FormatModName(mod) + " version=" + FormatVersion(mod.Version) + workshop;
12161217
}
12171218

12181219
private static string FormatModName(JoinDiagnosticsModEntry mod)
@@ -1228,21 +1229,24 @@ private static string FormatGameplayModInventoryLine(JoinDiagnosticsModEntry mod
12281229
? mod.Id
12291230
: mod.Name + " (" + mod.Id + ")";
12301231
var source = string.IsNullOrWhiteSpace(mod.Source) ? "" : " source=" + mod.Source;
1231-
return $"#{mod.Index + 1:00} {name} version={FormatVersion(mod.Version)}{source}";
1232+
var workshop = mod.WorkshopItemId.HasValue ? " workshop=" + mod.WorkshopItemId.Value : "";
1233+
return $"#{mod.Index + 1:00} {name} version={FormatVersion(mod.Version)}{source}{workshop}";
12321234
}
12331235

12341236
private static string FormatContentModInventoryLine(ContentModInventoryEntry mod)
12351237
{
12361238
var role = mod.IsDependency ? " dep" : "";
12371239
var source = string.IsNullOrWhiteSpace(mod.Source) ? "" : " source=" + mod.Source;
1240+
var workshop = mod.WorkshopItemId.HasValue ? " workshop=" + mod.WorkshopItemId.Value : "";
12381241
return
1239-
$"#{mod.Index + 1:00}{role} {FormatContentModName(mod)} version={FormatVersion(mod.Version)}{source}";
1242+
$"#{mod.Index + 1:00}{role} {FormatContentModName(mod)} version={FormatVersion(mod.Version)}{source}{workshop}";
12401243
}
12411244

12421245
private static string FormatContentModLine(ContentModInventoryEntry mod)
12431246
{
12441247
var source = string.IsNullOrWhiteSpace(mod.Source) ? "" : " source=" + mod.Source;
1245-
return FormatContentModName(mod) + " version=" + FormatVersion(mod.Version) + source;
1248+
var workshop = mod.WorkshopItemId.HasValue ? " workshop=" + mod.WorkshopItemId.Value : "";
1249+
return FormatContentModName(mod) + " version=" + FormatVersion(mod.Version) + source + workshop;
12461250
}
12471251

12481252
private static string FormatContentModName(ContentModInventoryEntry mod)

‎src/Networking/JoinDiagnostics/JoinFailureDiagnosticsService.cs‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,8 @@ private static string FormatModValue(JoinDiagnosticsModEntry mod)
597597
? T("value.noVersion", "No version")
598598
: mod.Version;
599599
var id = string.IsNullOrWhiteSpace(mod.Id) ? mod.Key : mod.Id;
600-
return "#" + (mod.Index + 1) + " " + id + " version=" + version;
600+
var workshop = mod.WorkshopItemId.HasValue ? " workshop=" + mod.WorkshopItemId.Value : "";
601+
return "#" + (mod.Index + 1) + " " + id + " version=" + version + workshop;
601602
}
602603

603604
private static string FormatContentModLabel(ContentModInventoryEntry mod)
@@ -615,7 +616,8 @@ private static string FormatContentModValue(ContentModInventoryEntry mod)
615616
? T("value.noVersion", "No version")
616617
: mod.Version;
617618
var source = string.IsNullOrWhiteSpace(mod.Source) ? "" : " source=" + mod.Source;
618-
return "#" + (mod.Index + 1) + " " + mod.Id + " version=" + version + source;
619+
var workshop = mod.WorkshopItemId.HasValue ? " workshop=" + mod.WorkshopItemId.Value : "";
620+
return "#" + (mod.Index + 1) + " " + mod.Id + " version=" + version + source + workshop;
619621
}
620622

621623
private static IReadOnlyDictionary<string, ContentModInventoryEntry> BuildContentModIdentityMap(

‎src/Networking/StateDivergence/StateDivergenceDiagnosticsPanel.cs‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -884,8 +884,9 @@ private static string FormatContentModInventoryLine(ContentModInventoryEntry mod
884884
? T("value.dependency", "dependency")
885885
: T("value.content", "content");
886886
var enabled = mod.IsEnabled ? T("value.enabled", "enabled") : T("value.disabled", "disabled");
887+
var workshop = mod.WorkshopItemId.HasValue ? " workshop=" + mod.WorkshopItemId.Value : "";
887888
return
888-
$"#{mod.Index + 1:00} [{role}, {enabled}] {name} version={version} source={mod.Source}";
889+
$"#{mod.Index + 1:00} [{role}, {enabled}] {name} version={version} source={mod.Source}{workshop}";
889890
}
890891

891892
private static string FormatLoadedModInventoryLine(ContentModInventoryEntry mod)

‎src/Telemetry/RunHistory/RunHistoryTelemetryCollector.cs‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ internal static JsonArray BuildModInventoryList()
1414
{
1515
var mods = new JsonArray();
1616
foreach (var mod in Sts2ModManagerCompat.BuildModInventoryEntries())
17-
mods.Add(new JsonObject
17+
{
18+
var entry = new JsonObject
1819
{
1920
["id"] = mod.Id,
2021
["name"] = mod.Name,
@@ -26,7 +27,11 @@ internal static JsonArray BuildModInventoryList()
2627
["assembly_version"] = mod.AssemblyVersion,
2728
["error_count"] = mod.Errors.Count,
2829
["errors"] = BuildModErrors(mod.Errors),
29-
});
30+
};
31+
if (mod.WorkshopItemId.HasValue)
32+
entry["workshop_id"] = mod.WorkshopItemId.Value;
33+
mods.Add(entry);
34+
}
3035

3136
return mods;
3237
}

0 commit comments

Comments
 (0)