mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
Update mod loading structure.
This commit is contained in:
parent
3b8aac8eca
commit
5f8377acaa
5 changed files with 146 additions and 145 deletions
|
|
@ -1 +1 @@
|
||||||
Subproject commit 78ce195c171d7bce4ad9df105f1f95cce9bf1150
|
Subproject commit c525072299d5febd2bb638ab229060b0073ba6a6
|
||||||
|
|
@ -27,6 +27,9 @@ public enum ModDataChangeType : ushort
|
||||||
|
|
||||||
public class ModDataEditor(SaveService saveService, CommunicatorService communicatorService) : IService
|
public class ModDataEditor(SaveService saveService, CommunicatorService communicatorService) : IService
|
||||||
{
|
{
|
||||||
|
public SaveService SaveService
|
||||||
|
=> saveService;
|
||||||
|
|
||||||
/// <summary> Create the file containing the meta information about a mod from scratch. </summary>
|
/// <summary> Create the file containing the meta information about a mod from scratch. </summary>
|
||||||
public void CreateMeta(DirectoryInfo directory, string? name, string? author, string? description, string? version,
|
public void CreateMeta(DirectoryInfo directory, string? name, string? author, string? description, string? version,
|
||||||
string? website)
|
string? website)
|
||||||
|
|
@ -40,148 +43,6 @@ public class ModDataEditor(SaveService saveService, CommunicatorService communic
|
||||||
saveService.ImmediateSaveSync(new ModMeta(mod));
|
saveService.ImmediateSaveSync(new ModMeta(mod));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModDataChangeType LoadLocalData(Mod mod)
|
|
||||||
{
|
|
||||||
var dataFile = saveService.FileNames.LocalDataFile(mod);
|
|
||||||
|
|
||||||
var importDate = 0L;
|
|
||||||
var localTags = Enumerable.Empty<string>();
|
|
||||||
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<long>() ?? importDate;
|
|
||||||
favorite = json[nameof(Mod.Favorite)]?.Value<bool>() ?? favorite;
|
|
||||||
note = json[nameof(Mod.Note)]?.Value<string>() ?? note;
|
|
||||||
localTags = (json[nameof(Mod.LocalTags)] as JArray)?.Values<string>().OfType<string>() ?? 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>() ?? string.Empty;
|
|
||||||
var newAuthor = json[nameof(Mod.Author)]?.Value<string>() ?? string.Empty;
|
|
||||||
var newDescription = json[nameof(Mod.Description)]?.Value<string>() ?? string.Empty;
|
|
||||||
var newImage = json[nameof(Mod.Image)]?.Value<string>() ?? string.Empty;
|
|
||||||
var newVersion = json[nameof(Mod.Version)]?.Value<string>() ?? string.Empty;
|
|
||||||
var newWebsite = json[nameof(Mod.Website)]?.Value<string>() ?? string.Empty;
|
|
||||||
var newFileVersion = json[nameof(ModMeta.FileVersion)]?.Value<uint>() ?? 0;
|
|
||||||
var importDate = json[nameof(Mod.ImportDate)]?.Value<long>();
|
|
||||||
var modTags = (json[nameof(Mod.ModTags)] as JArray)?.Values<string>().OfType<string>();
|
|
||||||
|
|
||||||
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)
|
public void ChangeModName(Mod mod, string newName)
|
||||||
{
|
{
|
||||||
if (mod.Name.Text == newName)
|
if (mod.Name.Text == newName)
|
||||||
|
|
|
||||||
|
|
@ -72,11 +72,11 @@ public partial class ModCreator(
|
||||||
if (!Directory.Exists(mod.ModPath.FullName))
|
if (!Directory.Exists(mod.ModPath.FullName))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
modDataChange = dataEditor.LoadMeta(this, mod);
|
modDataChange = ModMeta.Load(dataEditor, this, mod);
|
||||||
if (modDataChange.HasFlag(ModDataChangeType.Deletion) || mod.Name.Length == 0)
|
if (modDataChange.HasFlag(ModDataChangeType.Deletion) || mod.Name.Length == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
modDataChange |= dataEditor.LoadLocalData(mod);
|
modDataChange |= ModLocalData.Load(dataEditor, mod);
|
||||||
LoadDefaultOption(mod);
|
LoadDefaultOption(mod);
|
||||||
LoadAllGroups(mod);
|
LoadAllGroups(mod);
|
||||||
if (incorporateMetaChanges)
|
if (incorporateMetaChanges)
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,63 @@ public readonly struct ModLocalData(Mod mod) : ISavable
|
||||||
jObject.WriteTo(jWriter);
|
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<string>();
|
||||||
|
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<long>() ?? importDate;
|
||||||
|
favorite = json[nameof(Mod.Favorite)]?.Value<bool>() ?? favorite;
|
||||||
|
note = json[nameof(Mod.Note)]?.Value<string>() ?? note;
|
||||||
|
localTags = (json[nameof(Mod.LocalTags)] as JArray)?.Values<string>().OfType<string>() ?? 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<string>? newModTags, IEnumerable<string>? newLocalTags)
|
internal static ModDataChangeType UpdateTags(Mod mod, IEnumerable<string>? newModTags, IEnumerable<string>? newLocalTags)
|
||||||
{
|
{
|
||||||
if (newModTags == null && newLocalTags == null)
|
if (newModTags == null && newLocalTags == null)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Penumbra.Mods.Editor;
|
||||||
|
using Penumbra.Mods.Manager;
|
||||||
using Penumbra.Services;
|
using Penumbra.Services;
|
||||||
|
|
||||||
namespace Penumbra.Mods;
|
namespace Penumbra.Mods;
|
||||||
|
|
@ -28,4 +30,85 @@ public readonly struct ModMeta(Mod mod) : ISavable
|
||||||
jWriter.Formatting = Formatting.Indented;
|
jWriter.Formatting = Formatting.Indented;
|
||||||
jObject.WriteTo(jWriter);
|
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<uint>() ?? 0;
|
||||||
|
|
||||||
|
// Empty name gets checked after loading and is not allowed.
|
||||||
|
var newName = json[nameof(Mod.Name)]?.Value<string>() ?? string.Empty;
|
||||||
|
|
||||||
|
var newAuthor = json[nameof(Mod.Author)]?.Value<string>() ?? string.Empty;
|
||||||
|
var newDescription = json[nameof(Mod.Description)]?.Value<string>() ?? string.Empty;
|
||||||
|
var newImage = json[nameof(Mod.Image)]?.Value<string>() ?? string.Empty;
|
||||||
|
var newVersion = json[nameof(Mod.Version)]?.Value<string>() ?? string.Empty;
|
||||||
|
var newWebsite = json[nameof(Mod.Website)]?.Value<string>() ?? string.Empty;
|
||||||
|
var modTags = (json[nameof(Mod.ModTags)] as JArray)?.Values<string>().OfType<string>();
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue