diff --git a/Penumbra.GameData b/Penumbra.GameData
index 78ce195c..c5250722 160000
--- a/Penumbra.GameData
+++ b/Penumbra.GameData
@@ -1 +1 @@
-Subproject commit 78ce195c171d7bce4ad9df105f1f95cce9bf1150
+Subproject commit c525072299d5febd2bb638ab229060b0073ba6a6
diff --git a/Penumbra/Mods/Manager/ModDataEditor.cs b/Penumbra/Mods/Manager/ModDataEditor.cs
index 162f823d..7c48205a 100644
--- a/Penumbra/Mods/Manager/ModDataEditor.cs
+++ b/Penumbra/Mods/Manager/ModDataEditor.cs
@@ -27,6 +27,9 @@ public enum ModDataChangeType : ushort
public class ModDataEditor(SaveService saveService, CommunicatorService communicatorService) : IService
{
+ public SaveService SaveService
+ => saveService;
+
/// Create the file containing the meta information about a mod from scratch.
public void CreateMeta(DirectoryInfo directory, string? name, string? author, string? description, string? version,
string? website)
@@ -40,148 +43,6 @@ public class ModDataEditor(SaveService saveService, CommunicatorService communic
saveService.ImmediateSaveSync(new ModMeta(mod));
}
- public ModDataChangeType LoadLocalData(Mod mod)
- {
- var dataFile = saveService.FileNames.LocalDataFile(mod);
-
- var importDate = 0L;
- var localTags = Enumerable.Empty();
- var favorite = false;
- var note = string.Empty;
-
- var save = true;
- if (File.Exists(dataFile))
- try
- {
- var text = File.ReadAllText(dataFile);
- var json = JObject.Parse(text);
-
- importDate = json[nameof(Mod.ImportDate)]?.Value() ?? importDate;
- favorite = json[nameof(Mod.Favorite)]?.Value() ?? favorite;
- note = json[nameof(Mod.Note)]?.Value() ?? note;
- localTags = (json[nameof(Mod.LocalTags)] as JArray)?.Values().OfType() ?? localTags;
- save = false;
- }
- catch (Exception e)
- {
- Penumbra.Log.Error($"Could not load local mod data:\n{e}");
- }
-
- if (importDate == 0)
- importDate = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
-
- ModDataChangeType changes = 0;
- if (mod.ImportDate != importDate)
- {
- mod.ImportDate = importDate;
- changes |= ModDataChangeType.ImportDate;
- }
-
- changes |= ModLocalData.UpdateTags(mod, null, localTags);
-
- if (mod.Favorite != favorite)
- {
- mod.Favorite = favorite;
- changes |= ModDataChangeType.Favorite;
- }
-
- if (mod.Note != note)
- {
- mod.Note = note;
- changes |= ModDataChangeType.Note;
- }
-
- if (save)
- saveService.QueueSave(new ModLocalData(mod));
-
- return changes;
- }
-
- public ModDataChangeType LoadMeta(ModCreator creator, Mod mod)
- {
- var metaFile = saveService.FileNames.ModMetaPath(mod);
- if (!File.Exists(metaFile))
- {
- Penumbra.Log.Debug($"No mod meta found for {mod.ModPath.Name}.");
- return ModDataChangeType.Deletion;
- }
-
- try
- {
- var text = File.ReadAllText(metaFile);
- var json = JObject.Parse(text);
-
- var newName = json[nameof(Mod.Name)]?.Value() ?? string.Empty;
- var newAuthor = json[nameof(Mod.Author)]?.Value() ?? string.Empty;
- var newDescription = json[nameof(Mod.Description)]?.Value() ?? string.Empty;
- var newImage = json[nameof(Mod.Image)]?.Value() ?? string.Empty;
- var newVersion = json[nameof(Mod.Version)]?.Value() ?? string.Empty;
- var newWebsite = json[nameof(Mod.Website)]?.Value() ?? string.Empty;
- var newFileVersion = json[nameof(ModMeta.FileVersion)]?.Value() ?? 0;
- var importDate = json[nameof(Mod.ImportDate)]?.Value();
- var modTags = (json[nameof(Mod.ModTags)] as JArray)?.Values().OfType();
-
- ModDataChangeType changes = 0;
- if (mod.Name != newName)
- {
- changes |= ModDataChangeType.Name;
- mod.Name = newName;
- }
-
- if (mod.Author != newAuthor)
- {
- changes |= ModDataChangeType.Author;
- mod.Author = newAuthor;
- }
-
- if (mod.Description != newDescription)
- {
- changes |= ModDataChangeType.Description;
- mod.Description = newDescription;
- }
-
- if (mod.Image != newImage)
- {
- changes |= ModDataChangeType.Image;
- mod.Image = newImage;
- }
-
- if (mod.Version != newVersion)
- {
- changes |= ModDataChangeType.Version;
- mod.Version = newVersion;
- }
-
- if (mod.Website != newWebsite)
- {
- changes |= ModDataChangeType.Website;
- mod.Website = newWebsite;
- }
-
- if (newFileVersion != ModMeta.FileVersion)
- if (ModMigration.Migrate(creator, saveService, mod, json, ref newFileVersion))
- {
- changes |= ModDataChangeType.Migration;
- saveService.ImmediateSave(new ModMeta(mod));
- }
-
- if (importDate != null && mod.ImportDate != importDate.Value)
- {
- mod.ImportDate = importDate.Value;
- changes |= ModDataChangeType.ImportDate;
- }
-
- changes |= ModLocalData.UpdateTags(mod, modTags, null);
-
- return changes;
- }
- catch (Exception e)
- {
- Penumbra.Log.Error($"Could not load mod meta for {metaFile}:\n{e}");
- return ModDataChangeType.Deletion;
- }
- }
-
public void ChangeModName(Mod mod, string newName)
{
if (mod.Name.Text == newName)
diff --git a/Penumbra/Mods/ModCreator.cs b/Penumbra/Mods/ModCreator.cs
index 18d2bc09..0db83ef9 100644
--- a/Penumbra/Mods/ModCreator.cs
+++ b/Penumbra/Mods/ModCreator.cs
@@ -72,11 +72,11 @@ public partial class ModCreator(
if (!Directory.Exists(mod.ModPath.FullName))
return false;
- modDataChange = dataEditor.LoadMeta(this, mod);
+ modDataChange = ModMeta.Load(dataEditor, this, mod);
if (modDataChange.HasFlag(ModDataChangeType.Deletion) || mod.Name.Length == 0)
return false;
- modDataChange |= dataEditor.LoadLocalData(mod);
+ modDataChange |= ModLocalData.Load(dataEditor, mod);
LoadDefaultOption(mod);
LoadAllGroups(mod);
if (incorporateMetaChanges)
diff --git a/Penumbra/Mods/ModLocalData.cs b/Penumbra/Mods/ModLocalData.cs
index beda0dc7..d3534391 100644
--- a/Penumbra/Mods/ModLocalData.cs
+++ b/Penumbra/Mods/ModLocalData.cs
@@ -27,6 +27,63 @@ public readonly struct ModLocalData(Mod mod) : ISavable
jObject.WriteTo(jWriter);
}
+ public static ModDataChangeType Load(ModDataEditor editor, Mod mod)
+ {
+ var dataFile = editor.SaveService.FileNames.LocalDataFile(mod);
+
+ var importDate = 0L;
+ var localTags = Enumerable.Empty();
+ var favorite = false;
+ var note = string.Empty;
+
+ var save = true;
+ if (File.Exists(dataFile))
+ try
+ {
+ var text = File.ReadAllText(dataFile);
+ var json = JObject.Parse(text);
+
+ importDate = json[nameof(Mod.ImportDate)]?.Value() ?? importDate;
+ favorite = json[nameof(Mod.Favorite)]?.Value() ?? favorite;
+ note = json[nameof(Mod.Note)]?.Value() ?? note;
+ localTags = (json[nameof(Mod.LocalTags)] as JArray)?.Values().OfType() ?? localTags;
+ save = false;
+ }
+ catch (Exception e)
+ {
+ Penumbra.Log.Error($"Could not load local mod data:\n{e}");
+ }
+
+ if (importDate == 0)
+ importDate = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+
+ ModDataChangeType changes = 0;
+ if (mod.ImportDate != importDate)
+ {
+ mod.ImportDate = importDate;
+ changes |= ModDataChangeType.ImportDate;
+ }
+
+ changes |= ModLocalData.UpdateTags(mod, null, localTags);
+
+ if (mod.Favorite != favorite)
+ {
+ mod.Favorite = favorite;
+ changes |= ModDataChangeType.Favorite;
+ }
+
+ if (mod.Note != note)
+ {
+ mod.Note = note;
+ changes |= ModDataChangeType.Note;
+ }
+
+ if (save)
+ editor.SaveService.QueueSave(new ModLocalData(mod));
+
+ return changes;
+ }
+
internal static ModDataChangeType UpdateTags(Mod mod, IEnumerable? newModTags, IEnumerable? newLocalTags)
{
if (newModTags == null && newLocalTags == null)
diff --git a/Penumbra/Mods/ModMeta.cs b/Penumbra/Mods/ModMeta.cs
index 39dd20e4..0cebcf81 100644
--- a/Penumbra/Mods/ModMeta.cs
+++ b/Penumbra/Mods/ModMeta.cs
@@ -1,5 +1,7 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
+using Penumbra.Mods.Editor;
+using Penumbra.Mods.Manager;
using Penumbra.Services;
namespace Penumbra.Mods;
@@ -28,4 +30,85 @@ public readonly struct ModMeta(Mod mod) : ISavable
jWriter.Formatting = Formatting.Indented;
jObject.WriteTo(jWriter);
}
+
+ public static ModDataChangeType Load(ModDataEditor editor, ModCreator creator, Mod mod)
+ {
+ var metaFile = editor.SaveService.FileNames.ModMetaPath(mod);
+ if (!File.Exists(metaFile))
+ {
+ Penumbra.Log.Debug($"No mod meta found for {mod.ModPath.Name}.");
+ return ModDataChangeType.Deletion;
+ }
+
+ try
+ {
+ var text = File.ReadAllText(metaFile);
+ var json = JObject.Parse(text);
+
+ var newFileVersion = json[nameof(FileVersion)]?.Value() ?? 0;
+
+ // Empty name gets checked after loading and is not allowed.
+ var newName = json[nameof(Mod.Name)]?.Value() ?? string.Empty;
+
+ var newAuthor = json[nameof(Mod.Author)]?.Value() ?? string.Empty;
+ var newDescription = json[nameof(Mod.Description)]?.Value() ?? string.Empty;
+ var newImage = json[nameof(Mod.Image)]?.Value() ?? string.Empty;
+ var newVersion = json[nameof(Mod.Version)]?.Value() ?? string.Empty;
+ var newWebsite = json[nameof(Mod.Website)]?.Value() ?? string.Empty;
+ var modTags = (json[nameof(Mod.ModTags)] as JArray)?.Values().OfType();
+
+ ModDataChangeType changes = 0;
+ if (mod.Name != newName)
+ {
+ changes |= ModDataChangeType.Name;
+ mod.Name = newName;
+ }
+
+ if (mod.Author != newAuthor)
+ {
+ changes |= ModDataChangeType.Author;
+ mod.Author = newAuthor;
+ }
+
+ if (mod.Description != newDescription)
+ {
+ changes |= ModDataChangeType.Description;
+ mod.Description = newDescription;
+ }
+
+ if (mod.Image != newImage)
+ {
+ changes |= ModDataChangeType.Image;
+ mod.Image = newImage;
+ }
+
+ if (mod.Version != newVersion)
+ {
+ changes |= ModDataChangeType.Version;
+ mod.Version = newVersion;
+ }
+
+ if (mod.Website != newWebsite)
+ {
+ changes |= ModDataChangeType.Website;
+ mod.Website = newWebsite;
+ }
+
+ if (newFileVersion != FileVersion)
+ if (ModMigration.Migrate(creator, editor.SaveService, mod, json, ref newFileVersion))
+ {
+ changes |= ModDataChangeType.Migration;
+ editor.SaveService.ImmediateSave(new ModMeta(mod));
+ }
+
+ changes |= ModLocalData.UpdateTags(mod, modTags, null);
+
+ return changes;
+ }
+ catch (Exception e)
+ {
+ Penumbra.Log.Error($"Could not load mod meta for {metaFile}:\n{e}");
+ return ModDataChangeType.Deletion;
+ }
+ }
}