fix log parsing for invalid content packs (#860)
This commit is contained in:
parent
e376386d25
commit
d813c4e2c8
|
@ -29,6 +29,7 @@
|
||||||
* Added log parser warning about performance of PyTK 1.23.0 or earlier.
|
* Added log parser warning about performance of PyTK 1.23.0 or earlier.
|
||||||
* Converted images to SVG (thanks to ishan!).
|
* Converted images to SVG (thanks to ishan!).
|
||||||
* Updated log parser for new update alert format in SMAPI 3.15.1.
|
* Updated log parser for new update alert format in SMAPI 3.15.1.
|
||||||
|
* Fixed parsing for invalid content packs.
|
||||||
|
|
||||||
## 3.15.1
|
## 3.15.1
|
||||||
Released 06 July 2022 for Stardew Valley 1.5.6 or later.
|
Released 06 July 2022 for Stardew Valley 1.5.6 or later.
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace StardewModdingAPI.Web.Framework.LogParsing
|
||||||
private readonly Regex ContentPackListStartPattern = new(@"^Loaded \d+ content packs:$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
private readonly Regex ContentPackListStartPattern = new(@"^Loaded \d+ content packs:$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||||
|
|
||||||
/// <summary>A regex pattern matching an entry in SMAPI's content pack list.</summary>
|
/// <summary>A regex pattern matching an entry in SMAPI's content pack list.</summary>
|
||||||
private readonly Regex ContentPackListEntryPattern = new(@"^ (?<name>.+?) (?<version>[^\s]+)(?: by (?<author>[^\|]+))? \| for (?<for>[^\|]+)(?: \| (?<description>.+))?$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
private readonly Regex ContentPackListEntryPattern = new(@"^ (?<name>.+?) (?<version>[^\s]+)(?: by (?<author>[^\|]+))? \| for (?<for>[^\|]*)(?: \| (?<description>.+))?$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||||
|
|
||||||
/// <summary>A regex pattern matching the start of SMAPI's mod update list.</summary>
|
/// <summary>A regex pattern matching the start of SMAPI's mod update list.</summary>
|
||||||
private readonly Regex ModUpdateListStartPattern = new(@"^You can update \d+ mods?:$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
private readonly Regex ModUpdateListStartPattern = new(@"^You can update \d+ mods?:$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||||
|
@ -77,8 +77,8 @@ namespace StardewModdingAPI.Web.Framework.LogParsing
|
||||||
};
|
};
|
||||||
|
|
||||||
// parse log messages
|
// parse log messages
|
||||||
LogModInfo smapiMod = new(name: "SMAPI", author: "Pathoschild", version: "", description: "", loaded: true, isMod: false);
|
LogModInfo smapiMod = new(ModType.Special, name: "SMAPI", author: "Pathoschild", version: "", description: "", loaded: true);
|
||||||
LogModInfo gameMod = new(name: "game", author: "", version: "", description: "", loaded: true, isMod: false);
|
LogModInfo gameMod = new(ModType.Special, name: "game", author: "", version: "", description: "", loaded: true);
|
||||||
IDictionary<string, List<LogModInfo>> mods = new Dictionary<string, List<LogModInfo>>();
|
IDictionary<string, List<LogModInfo>> mods = new Dictionary<string, List<LogModInfo>>();
|
||||||
bool inModList = false;
|
bool inModList = false;
|
||||||
bool inContentPackList = false;
|
bool inContentPackList = false;
|
||||||
|
@ -133,7 +133,7 @@ namespace StardewModdingAPI.Web.Framework.LogParsing
|
||||||
|
|
||||||
if (!mods.TryGetValue(name, out List<LogModInfo>? entries))
|
if (!mods.TryGetValue(name, out List<LogModInfo>? entries))
|
||||||
mods[name] = entries = new List<LogModInfo>();
|
mods[name] = entries = new List<LogModInfo>();
|
||||||
entries.Add(new LogModInfo(name: name, author: author, version: version, description: description, loaded: true));
|
entries.Add(new LogModInfo(ModType.CodeMod, name: name, author: author, version: version, description: description, loaded: true));
|
||||||
|
|
||||||
message.Section = LogSection.ModsList;
|
message.Section = LogSection.ModsList;
|
||||||
}
|
}
|
||||||
|
@ -156,7 +156,7 @@ namespace StardewModdingAPI.Web.Framework.LogParsing
|
||||||
|
|
||||||
if (!mods.TryGetValue(name, out List<LogModInfo>? entries))
|
if (!mods.TryGetValue(name, out List<LogModInfo>? entries))
|
||||||
mods[name] = entries = new List<LogModInfo>();
|
mods[name] = entries = new List<LogModInfo>();
|
||||||
entries.Add(new LogModInfo(name: name, author: author, version: version, description: description, contentPackFor: forMod, loaded: true));
|
entries.Add(new LogModInfo(ModType.ContentPack, name: name, author: author, version: version, description: description, contentPackFor: forMod, loaded: true));
|
||||||
|
|
||||||
message.Section = LogSection.ContentPackList;
|
message.Section = LogSection.ContentPackList;
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,21 +48,24 @@ namespace StardewModdingAPI.Web.Framework.LogParsing.Models
|
||||||
[MemberNotNullWhen(true, nameof(LogModInfo.UpdateVersion), nameof(LogModInfo.UpdateLink))]
|
[MemberNotNullWhen(true, nameof(LogModInfo.UpdateVersion), nameof(LogModInfo.UpdateLink))]
|
||||||
public bool HasUpdate => this.UpdateVersion != null && this.Version != this.UpdateVersion;
|
public bool HasUpdate => this.UpdateVersion != null && this.Version != this.UpdateVersion;
|
||||||
|
|
||||||
|
/// <summary>The mod type.</summary>
|
||||||
|
public ModType ModType { get; }
|
||||||
|
|
||||||
/// <summary>Whether this is an actual mod (rather than a special entry for SMAPI or the game itself).</summary>
|
/// <summary>Whether this is an actual mod (rather than a special entry for SMAPI or the game itself).</summary>
|
||||||
public bool IsMod { get; }
|
public bool IsMod => this.ModType != ModType.Special;
|
||||||
|
|
||||||
/// <summary>Whether this is a C# code mod.</summary>
|
/// <summary>Whether this is a C# code mod.</summary>
|
||||||
public bool IsCodeMod { get; }
|
public bool IsCodeMod => this.ModType == ModType.CodeMod;
|
||||||
|
|
||||||
/// <summary>Whether this is a content pack for another mod.</summary>
|
/// <summary>Whether this is a content pack for another mod.</summary>
|
||||||
[MemberNotNullWhen(true, nameof(LogModInfo.ContentPackFor))]
|
public bool IsContentPack => this.ModType == ModType.ContentPack;
|
||||||
public bool IsContentPack { get; }
|
|
||||||
|
|
||||||
|
|
||||||
/*********
|
/*********
|
||||||
** Public methods
|
** Public methods
|
||||||
*********/
|
*********/
|
||||||
/// <summary>Construct an instance.</summary>
|
/// <summary>Construct an instance.</summary>
|
||||||
|
/// <param name="modType">The mod type.</param>
|
||||||
/// <param name="name">The mod name.</param>
|
/// <param name="name">The mod name.</param>
|
||||||
/// <param name="author">The mod author.</param>
|
/// <param name="author">The mod author.</param>
|
||||||
/// <param name="version">The mod version.</param>
|
/// <param name="version">The mod version.</param>
|
||||||
|
@ -72,9 +75,9 @@ namespace StardewModdingAPI.Web.Framework.LogParsing.Models
|
||||||
/// <param name="contentPackFor">The name of the mod for which this is a content pack (if applicable).</param>
|
/// <param name="contentPackFor">The name of the mod for which this is a content pack (if applicable).</param>
|
||||||
/// <param name="errors">The number of errors logged by this mod.</param>
|
/// <param name="errors">The number of errors logged by this mod.</param>
|
||||||
/// <param name="loaded">Whether the mod was loaded into the game.</param>
|
/// <param name="loaded">Whether the mod was loaded into the game.</param>
|
||||||
/// <param name="isMod">Whether this is an actual mod (instead of a special entry for SMAPI or the game).</param>
|
public LogModInfo(ModType modType, string name, string author, string version, string description, string? updateVersion = null, string? updateLink = null, string? contentPackFor = null, int errors = 0, bool loaded = true)
|
||||||
public LogModInfo(string name, string author, string version, string description, string? updateVersion = null, string? updateLink = null, string? contentPackFor = null, int errors = 0, bool loaded = true, bool isMod = true)
|
|
||||||
{
|
{
|
||||||
|
this.ModType = modType;
|
||||||
this.Name = name;
|
this.Name = name;
|
||||||
this.Author = author;
|
this.Author = author;
|
||||||
this.Description = description;
|
this.Description = description;
|
||||||
|
@ -84,13 +87,6 @@ namespace StardewModdingAPI.Web.Framework.LogParsing.Models
|
||||||
this.Errors = errors;
|
this.Errors = errors;
|
||||||
this.Loaded = loaded;
|
this.Loaded = loaded;
|
||||||
|
|
||||||
if (isMod)
|
|
||||||
{
|
|
||||||
this.IsMod = true;
|
|
||||||
this.IsContentPack = !string.IsNullOrWhiteSpace(this.ContentPackFor);
|
|
||||||
this.IsCodeMod = !this.IsContentPack;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.OverrideVersion(version);
|
this.OverrideVersion(version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
namespace StardewModdingAPI.Web.Framework.LogParsing.Models
|
||||||
|
{
|
||||||
|
/// <summary>The type for a <see cref="LogModInfo"/> instance.</summary>
|
||||||
|
public enum ModType
|
||||||
|
{
|
||||||
|
/// <summary>A special non-mod entry (e.g. for SMAPI or the game itself).</summary>
|
||||||
|
Special,
|
||||||
|
|
||||||
|
/// <summary>A C# mod.</summary>
|
||||||
|
CodeMod,
|
||||||
|
|
||||||
|
/// <summary>A content pack loaded by a C# mod.</summary>
|
||||||
|
ContentPack
|
||||||
|
}
|
||||||
|
}
|
|
@ -107,7 +107,7 @@ namespace StardewModdingAPI.Web.ViewModels
|
||||||
// group by mod
|
// group by mod
|
||||||
return mods
|
return mods
|
||||||
.Where(mod => mod.IsContentPack)
|
.Where(mod => mod.IsContentPack)
|
||||||
.GroupBy(mod => mod.ContentPackFor!)
|
.GroupBy(mod => mod.ContentPackFor ?? "")
|
||||||
.ToDictionary(group => group.Key, group => group.ToArray());
|
.ToDictionary(group => group.Key, group => group.ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -352,16 +352,31 @@ else if (log?.IsValid == true)
|
||||||
<span class="notice btn txt" v-on:click="toggleContentPacks">toggle content packs in list</span>
|
<span class="notice btn txt" v-on:click="toggleContentPacks">toggle content packs in list</span>
|
||||||
}
|
}
|
||||||
</caption>
|
</caption>
|
||||||
@foreach (var mod in log.Mods.Where(p => p.Loaded && !p.IsContentPack))
|
|
||||||
{
|
|
||||||
if (contentPacks == null || !contentPacks.TryGetValue(mod.Name, out LogModInfo[]? contentPackList))
|
|
||||||
contentPackList = null;
|
|
||||||
|
|
||||||
|
@{
|
||||||
|
var modsWithContentPacks = log.Mods
|
||||||
|
.Where(mod => mod.Loaded && !mod.IsContentPack)
|
||||||
|
.Select(mod => (
|
||||||
|
Mod: mod,
|
||||||
|
ContentPacks: contentPacks?.TryGetValue(mod.Name, out LogModInfo[]? contentPackList) == true ? contentPackList : Array.Empty<LogModInfo>()
|
||||||
|
))
|
||||||
|
.ToList();
|
||||||
|
if (contentPacks?.TryGetValue("", out LogModInfo[] invalidPacks) == true)
|
||||||
|
{
|
||||||
|
modsWithContentPacks.Add((
|
||||||
|
Mod: new LogModInfo(ModType.CodeMod, "<invalid content packs>", "", "", ""),
|
||||||
|
ContentPacks: invalidPacks
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@foreach ((LogModInfo mod, LogModInfo[] contentPackList) in modsWithContentPacks)
|
||||||
|
{
|
||||||
<tr v-on:click="toggleMod('@Model.GetSlug(mod.Name)')" class="mod-entry" v-bind:class="{ hidden: !showMods['@Model.GetSlug(mod.Name)'] }">
|
<tr v-on:click="toggleMod('@Model.GetSlug(mod.Name)')" class="mod-entry" v-bind:class="{ hidden: !showMods['@Model.GetSlug(mod.Name)'] }">
|
||||||
<td><input type="checkbox" v-bind:checked="showMods['@Model.GetSlug(mod.Name)']" v-bind:class="{ invisible: !anyModsHidden }" /></td>
|
<td><input type="checkbox" v-bind:checked="showMods['@Model.GetSlug(mod.Name)']" v-bind:class="{ invisible: !anyModsHidden }" /></td>
|
||||||
<td>
|
<td>
|
||||||
<strong v-pre>@mod.Name</strong> @mod.Version
|
<strong v-pre>@mod.Name</strong> @mod.Version
|
||||||
@if (contentPackList != null)
|
@if (contentPackList.Any())
|
||||||
{
|
{
|
||||||
<div v-if="!hideContentPacks" class="content-packs">
|
<div v-if="!hideContentPacks" class="content-packs">
|
||||||
@foreach (var contentPack in contentPackList)
|
@foreach (var contentPack in contentPackList)
|
||||||
|
@ -374,7 +389,7 @@ else if (log?.IsValid == true)
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@mod.Author
|
@mod.Author
|
||||||
@if (contentPackList != null)
|
@if (contentPackList.Any())
|
||||||
{
|
{
|
||||||
<div v-if="!hideContentPacks" class="content-packs">
|
<div v-if="!hideContentPacks" class="content-packs">
|
||||||
@foreach (var contentPack in contentPackList)
|
@foreach (var contentPack in contentPackList)
|
||||||
|
|
Loading…
Reference in New Issue