Skip to content

Commit

Permalink
Add diagnostic for mods that overwrite game files (#1481)
Browse files Browse the repository at this point in the history
  • Loading branch information
erri120 authored May 29, 2024
1 parent ecc5995 commit 27a1f35
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ public static class LoadoutExtensions
{
private static IEnumerable<Mod.Model> GetEnabledMods(this Loadout.Model loadout, bool onlyEnabledMods)
{
return onlyEnabledMods
var enumerable = onlyEnabledMods
? loadout.Mods.Where(mod => mod.Enabled)
: loadout.Mods;

return enumerable.Where(mod => mod.Category == ModCategory.Mod);
}

/// <summary>
Expand Down
23 changes: 23 additions & 0 deletions src/Games/NexusMods.Games.StardewValley/Diagnostics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -264,4 +264,27 @@ of the mod from {NexusModsLink}.
.AddValue<NamedLink>("NexusModsLink")
)
.Finish();

[DiagnosticTemplate]
[UsedImplicitly]
internal static IDiagnosticTemplate ModOverwritesGameFilesTemplate = DiagnosticTemplateBuilder
.Start()
.WithId(new DiagnosticId(Source, number: 13))
.WithTitle("Mod overwrites game files")
.WithSeverity(DiagnosticSeverity.Suggestion)
.WithSummary("Mod {ModName} overwrites game files")
.WithDetails("""
Mod {Mod} overwrites game files. This can cause compatibility issues and have other
unintended side-effects. See the {SMAPIWikiLink} for details.
You can resolve this diagnostic by replacing {Mod} with a SMAPI mod that doesn't
overwrite game files. See the {SMAPIWikiTableLink} for a list of alternatives.
""")
.WithMessageData(messageBuilder => messageBuilder
.AddDataReference<ModReference>("Mod")
.AddValue<string>("ModName")
.AddValue<NamedLink>("SMAPIWikiLink")
.AddValue<NamedLink>("SMAPIWikiTableLink")
)
.Finish();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System.Runtime.CompilerServices;
using NexusMods.Abstractions.Diagnostics;
using NexusMods.Abstractions.Diagnostics.Emitters;
using NexusMods.Abstractions.Diagnostics.References;
using NexusMods.Abstractions.Diagnostics.Values;
using NexusMods.Abstractions.GameLocators;
using NexusMods.Abstractions.Loadouts;
using NexusMods.Abstractions.Loadouts.Extensions;

namespace NexusMods.Games.StardewValley.Emitters;

public class ModOverwritesGameFilesEmitter : ILoadoutDiagnosticEmitter
{
private static readonly NamedLink SMAPIWikiLink = new("SMAPI Wiki", new Uri("https://stardewvalleywiki.com/Modding:Using_XNB_mods"));
private static readonly NamedLink SMAPIWikiTableLink = new("SMAPI Wiki", new Uri("https://stardewvalleywiki.com/Modding:Using_XNB_mods#Alternatives_using_Content_Patcher"));

private static readonly GamePath ContentDirectoryPath = new(LocationId.Game, "Content");

public async IAsyncEnumerable<Diagnostic> Diagnose(Loadout.Model loadout, [EnumeratorCancellation] CancellationToken cancellationToken)
{
await Task.Yield();

var mods = loadout
.GetEnabledMods()
.Where(mod => mod.Files.Any(file => file.To.StartsWith(ContentDirectoryPath)))
.ToArray();

foreach (var mod in mods)
{
yield return Diagnostics.CreateModOverwritesGameFiles(
Mod: mod.ToReference(loadout),
ModName: mod.Name,
SMAPIWikiLink: SMAPIWikiLink,
SMAPIWikiTableLink: SMAPIWikiTableLink
);
}
}
}
1 change: 1 addition & 0 deletions src/Games/NexusMods.Games.StardewValley/Services.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public static IServiceCollection AddStardewValley(this IServiceCollection servic
.AddSingleton<SMAPIModDatabaseCompatibilityDiagnosticEmitter>()
.AddSingleton<SMAPIGameVersionDiagnosticEmitter>()
.AddSingleton<VersionDiagnosticEmitter>()
.AddSingleton<ModOverwritesGameFilesEmitter>()

// Attributes
.AddAttributeCollection(typeof(SMAPIMarker))
Expand Down
1 change: 1 addition & 0 deletions src/Games/NexusMods.Games.StardewValley/StardewValley.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ protected override IReadOnlyDictionary<LocationId, AbsolutePath> GetLocations(IF
_serviceProvider.GetRequiredService<MissingSMAPIEmitter>(),
_serviceProvider.GetRequiredService<SMAPIModDatabaseCompatibilityDiagnosticEmitter>(),
_serviceProvider.GetRequiredService<VersionDiagnosticEmitter>(),
_serviceProvider.GetRequiredService<ModOverwritesGameFilesEmitter>(),
];

public override List<IModInstallDestination> GetInstallDestinations(IReadOnlyDictionary<LocationId, AbsolutePath> locations) => ModInstallDestinationHelpers.GetCommonLocations(locations);
Expand Down

0 comments on commit 27a1f35

Please sign in to comment.