Services here, too!

This commit is contained in:
Ottermandias 2023-04-23 19:50:51 +02:00
parent 1eb16b98a8
commit 85adc3626e
47 changed files with 1015 additions and 562 deletions

View file

@ -5,6 +5,7 @@ using System.Linq;
using Dalamud.Plugin;
using Dalamud.Utility;
using Glamourer.Customization;
using Glamourer.Services;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using OtterGui;
@ -21,8 +22,9 @@ public partial class Design
public const string DesignFolderName = "designs";
public readonly string DesignFolder;
private readonly FrameworkManager _framework;
private readonly List<Design> _designs = new();
private readonly ItemManager _items;
private readonly SaveService _saveService;
private readonly List<Design> _designs = new();
public enum DesignChangeType
{
@ -50,9 +52,10 @@ public partial class Design
public IReadOnlyList<Design> Designs
=> _designs;
public Manager(DalamudPluginInterface pi, FrameworkManager framework)
public Manager(DalamudPluginInterface pi, SaveService saveService, ItemManager items)
{
_framework = framework;
_saveService = saveService;
_items = items;
DesignFolder = SetDesignFolder(pi);
DesignChange += OnChange;
LoadDesigns();
@ -105,7 +108,7 @@ public partial class Design
=> Path.Combine(DesignFolder, $"{design.Identifier}.json");
public void SaveDesign(Design design)
=> _framework.RegisterDelayed($"{nameof(SaveDesign)}_{design.Identifier}", () => SaveDesignInternal(design));
=> _saveService.QueueSave(design);
private void SaveDesignInternal(Design design)
{
@ -133,7 +136,7 @@ public partial class Design
{
var text = File.ReadAllText(file.FullName);
var data = JObject.Parse(text);
var design = LoadDesign(data, out var changes);
var design = LoadDesign(_items, data, out var changes);
if (design.Identifier.ToString() != Path.GetFileNameWithoutExtension(file.Name))
invalidNames.Add((design, file.FullName));
if (_designs.Any(f => f.Identifier == design.Identifier))
@ -177,7 +180,7 @@ public partial class Design
public Design Create(string name)
{
var design = new Design()
var design = new Design(_items)
{
CreationDate = DateTimeOffset.UtcNow,
Identifier = CreateNewGuid(),
@ -297,7 +300,7 @@ public partial class Design
public void ChangeEquip(Design design, EquipSlot slot, uint itemId, Lumina.Excel.GeneratedSheets.Item? item = null)
{
var old = design.Armor(slot);
if (design.SetArmor(slot, itemId, item))
if (design.SetArmor(_items, slot, itemId, item))
{
var n = design.Armor(slot);
Glamourer.Log.Debug(
@ -309,8 +312,8 @@ public partial class Design
public void ChangeWeapon(Design design, uint itemId, EquipSlot offhand, Lumina.Excel.GeneratedSheets.Item? item = null)
{
var (old, change, n) = offhand == EquipSlot.OffHand
? (design.WeaponOff, design.SetOffhand(itemId, item), design.WeaponOff)
: (design.WeaponMain, design.SetMainhand(itemId, item), design.WeaponMain);
? (design.WeaponOff, design.SetOffhand(_items, itemId, item), design.WeaponOff)
: (design.WeaponMain, design.SetMainhand(_items, itemId, item), design.WeaponMain);
if (change)
{
Glamourer.Log.Debug(
@ -386,13 +389,13 @@ public partial class Design
try
{
var actualName = Path.GetFileName(name);
var design = new Design()
var design = new Design(_items)
{
CreationDate = DateTimeOffset.UtcNow,
Identifier = CreateNewGuid(),
Name = actualName,
};
design.MigrateBase64(base64);
design.MigrateBase64(_items, base64);
Add(design, $"Migrated old design to {design.Identifier}.");
migratedFileSystemPaths.Add(design.Identifier.ToString(), name);
++successes;

View file

@ -1,16 +1,17 @@
using System;
using System.IO;
using System.Linq;
using Glamourer.Customization;
using Glamourer.Util;
using Glamourer.Services;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using OtterGui;
using OtterGui.Classes;
using Penumbra.GameData.Enums;
using Penumbra.GameData.Structs;
namespace Glamourer.Designs;
public partial class Design : DesignBase
public partial class Design : DesignBase, ISavable
{
public const int FileVersion = 1;
@ -69,7 +70,8 @@ public partial class Design : DesignBase
}
private Design()
private Design(ItemManager items)
: base(items)
{ }
public JObject JsonSerialize()
@ -142,17 +144,17 @@ public partial class Design : DesignBase
return ret;
}
public static Design LoadDesign(JObject json, out bool changes)
public static Design LoadDesign(ItemManager items, JObject json, out bool changes)
{
var version = json[nameof(FileVersion)]?.ToObject<int>() ?? 0;
return version switch
{
1 => LoadDesignV1(json, out changes),
1 => LoadDesignV1(items, json, out changes),
_ => throw new Exception("The design to be loaded has no valid Version."),
};
}
private static Design LoadDesignV1(JObject json, out bool changes)
private static Design LoadDesignV1(ItemManager items, JObject json, out bool changes)
{
static string[] ParseTags(JObject json)
{
@ -160,7 +162,7 @@ public partial class Design : DesignBase
return tags.OrderBy(t => t).Distinct().ToArray();
}
var design = new Design()
var design = new Design(items)
{
CreationDate = json["CreationDate"]?.ToObject<DateTimeOffset>() ?? throw new ArgumentNullException("CreationDate"),
Identifier = json["Identifier"]?.ToObject<Guid>() ?? throw new ArgumentNullException("Identifier"),
@ -169,12 +171,12 @@ public partial class Design : DesignBase
Tags = ParseTags(json),
};
changes = LoadEquip(json["Equipment"], design);
changes = LoadEquip(items, json["Equipment"], design);
changes |= LoadCustomize(json["Customize"], design);
return design;
}
private static bool LoadEquip(JToken? equip, Design design)
private static bool LoadEquip(ItemManager items, JToken? equip, Design design)
{
if (equip == null)
return true;
@ -192,7 +194,7 @@ public partial class Design : DesignBase
foreach (var slot in EquipSlotExtensions.EqdpSlots)
{
var (id, stain, apply, applyStain) = ParseItem(slot, equip[slot.ToString()]);
changes |= !design.SetArmor(slot, id);
changes |= !design.SetArmor(items, slot, id);
changes |= !design.SetStain(slot, stain);
design.SetApplyEquip(slot, apply);
design.SetApplyStain(slot, applyStain);
@ -205,11 +207,11 @@ public partial class Design : DesignBase
}
else
{
var id = main["ItemId"]?.ToObject<uint>() ?? Glamourer.Items.DefaultSword.RowId;
var id = main["ItemId"]?.ToObject<uint>() ?? items.DefaultSword.RowId;
var stain = (StainId)(main["Stain"]?.ToObject<byte>() ?? 0);
var apply = main["Apply"]?.ToObject<bool>() ?? false;
var applyStain = main["ApplyStain"]?.ToObject<bool>() ?? false;
changes |= !design.SetMainhand(id);
changes |= !design.SetMainhand(items, id);
changes |= !design.SetStain(EquipSlot.MainHand, stain);
design.SetApplyEquip(EquipSlot.MainHand, apply);
design.SetApplyStain(EquipSlot.MainHand, applyStain);
@ -226,7 +228,7 @@ public partial class Design : DesignBase
var stain = (StainId)(off["Stain"]?.ToObject<byte>() ?? 0);
var apply = off["Apply"]?.ToObject<bool>() ?? false;
var applyStain = off["ApplyStain"]?.ToObject<bool>() ?? false;
changes |= !design.SetOffhand(id);
changes |= !design.SetOffhand(items, id);
changes |= !design.SetStain(EquipSlot.OffHand, stain);
design.SetApplyEquip(EquipSlot.OffHand, apply);
design.SetApplyStain(EquipSlot.OffHand, applyStain);
@ -259,14 +261,14 @@ public partial class Design : DesignBase
return false;
}
public void MigrateBase64(string base64)
public void MigrateBase64(ItemManager items, string base64)
{
var data = MigrateBase64(base64, out var applyEquip, out var applyCustomize, out var writeProtected, out var wet, out var hat,
out var visor, out var weapon);
UpdateMainhand(data.MainHand);
UpdateMainhand(data.OffHand);
UpdateMainhand(items, data.MainHand);
UpdateOffhand(items, data.OffHand);
foreach (var slot in EquipSlotExtensions.EqdpSlots)
UpdateArmor(slot, data.Equipment[slot], true);
UpdateArmor(items, slot, data.Equipment[slot], true);
CharacterData.CustomizeData = data.CustomizeData;
ApplyEquip = applyEquip;
ApplyCustomize = applyCustomize;
@ -277,10 +279,10 @@ public partial class Design : DesignBase
Weapon = weapon;
}
public static Design CreateTemporaryFromBase64(string base64, bool customize, bool equip)
public static Design CreateTemporaryFromBase64(ItemManager items, string base64, bool customize, bool equip)
{
var ret = new Design();
ret.MigrateBase64(base64);
var ret = new Design(items);
ret.MigrateBase64(items, base64);
if (!customize)
ret.ApplyCustomize = 0;
if (!equip)
@ -296,4 +298,20 @@ public partial class Design : DesignBase
public string CreateOldBase64()
=> CreateOldBase64(in CharacterData, ApplyEquip, ApplyCustomize, Wetness == QuadBool.True, Hat.ForcedValue, Hat.Enabled,
Visor.ForcedValue, Visor.Enabled, Weapon.ForcedValue, Weapon.Enabled, WriteProtected, 1f);
public string ToFilename(FilenameService fileNames)
=> fileNames.DesignFile(this);
public void Save(StreamWriter writer)
{
using var j = new JsonTextWriter(writer)
{
Formatting = Formatting.Indented,
};
var obj = JsonSerialize();
obj.WriteTo(j);
}
public string LogName(string fileName)
=> Path.GetFileNameWithoutExtension(fileName);
}

View file

@ -1,5 +1,6 @@
using System;
using Glamourer.Customization;
using Glamourer.Services;
using Glamourer.Util;
using OtterGui.Classes;
using OtterGui;
@ -45,14 +46,14 @@ public class DesignBase
public CharacterEquip Equipment()
=> CharacterData.Equipment;
public DesignBase()
public DesignBase(ItemManager items)
{
MainHand = Glamourer.Items.DefaultSword.RowId;
MainHand = items.DefaultSword.RowId;
(_, CharacterData.MainHand.Set, CharacterData.MainHand.Type, CharacterData.MainHand.Variant, MainhandName, MainhandType) =
Glamourer.Items.Resolve(MainHand, Glamourer.Items.DefaultSword);
items.Resolve(MainHand, items.DefaultSword);
OffHand = ItemManager.NothingId(MainhandType.Offhand());
(_, CharacterData.OffHand.Set, CharacterData.OffHand.Type, CharacterData.OffHand.Variant, OffhandName, _) =
Glamourer.Items.Resolve(OffHand, MainhandType);
items.Resolve(OffHand, MainhandType);
}
public uint ModelId
@ -96,9 +97,9 @@ public class DesignBase
return true;
}
protected bool SetArmor(EquipSlot slot, uint itemId, Lumina.Excel.GeneratedSheets.Item? item = null)
protected bool SetArmor(ItemManager items, EquipSlot slot, uint itemId, Lumina.Excel.GeneratedSheets.Item? item = null)
{
var (valid, set, variant, name) = Glamourer.Items.Resolve(slot, itemId, item);
var (valid, set, variant, name) = items.Resolve(slot, itemId, item);
if (!valid)
return false;
@ -108,7 +109,7 @@ public class DesignBase
protected bool SetArmor(EquipSlot slot, Item item)
=> SetArmor(slot, item.ModelBase, item.Variant, item.Name, item.ItemId);
protected bool UpdateArmor(EquipSlot slot, CharacterArmor armor, bool force)
protected bool UpdateArmor(ItemManager items, EquipSlot slot, CharacterArmor armor, bool force)
{
if (!force)
switch (slot)
@ -125,19 +126,19 @@ public class DesignBase
case EquipSlot.LFinger when CharacterData.LFinger.Value == armor.Value: return false;
}
var (valid, id, name) = Glamourer.Items.Identify(slot, armor.Set, armor.Variant);
var (valid, id, name) = items.Identify(slot, armor.Set, armor.Variant);
if (!valid)
return false;
return SetArmor(slot, armor.Set, armor.Variant, name, id);
}
protected bool SetMainhand(uint mainId, Lumina.Excel.GeneratedSheets.Item? main = null)
protected bool SetMainhand(ItemManager items, uint mainId, Lumina.Excel.GeneratedSheets.Item? main = null)
{
if (mainId == MainHand)
return false;
var (valid, set, weapon, variant, name, type) = Glamourer.Items.Resolve(mainId, main);
var (valid, set, weapon, variant, name, type) = items.Resolve(mainId, main);
if (!valid)
return false;
@ -150,16 +151,16 @@ public class DesignBase
CharacterData.MainHand.Type = weapon;
CharacterData.MainHand.Variant = variant;
if (fixOffhand)
SetOffhand(ItemManager.NothingId(type.Offhand()));
SetOffhand(items, ItemManager.NothingId(type.Offhand()));
return true;
}
protected bool SetOffhand(uint offId, Lumina.Excel.GeneratedSheets.Item? off = null)
protected bool SetOffhand(ItemManager items, uint offId, Lumina.Excel.GeneratedSheets.Item? off = null)
{
if (offId == OffHand)
return false;
var (valid, set, weapon, variant, name, type) = Glamourer.Items.Resolve(offId, MainhandType, off);
var (valid, set, weapon, variant, name, type) = items.Resolve(offId, MainhandType, off);
if (!valid)
return false;
@ -171,12 +172,12 @@ public class DesignBase
return true;
}
protected bool UpdateMainhand(CharacterWeapon weapon)
protected bool UpdateMainhand(ItemManager items, CharacterWeapon weapon)
{
if (weapon.Value == CharacterData.MainHand.Value)
return false;
var (valid, id, name, type) = Glamourer.Items.Identify(EquipSlot.MainHand, weapon.Set, weapon.Type, (byte)weapon.Variant);
var (valid, id, name, type) = items.Identify(EquipSlot.MainHand, weapon.Set, weapon.Type, (byte)weapon.Variant);
if (!valid || id == MainHand)
return false;
@ -190,16 +191,16 @@ public class DesignBase
CharacterData.MainHand.Variant = weapon.Variant;
CharacterData.MainHand.Stain = weapon.Stain;
if (fixOffhand)
SetOffhand(ItemManager.NothingId(type.Offhand()));
SetOffhand(items, ItemManager.NothingId(type.Offhand()));
return true;
}
protected bool UpdateOffhand(CharacterWeapon weapon)
protected bool UpdateOffhand(ItemManager items, CharacterWeapon weapon)
{
if (weapon.Value == CharacterData.OffHand.Value)
return false;
var (valid, id, name, _) = Glamourer.Items.Identify(EquipSlot.OffHand, weapon.Set, weapon.Type, (byte)weapon.Variant, MainhandType);
var (valid, id, name, _) = items.Identify(EquipSlot.OffHand, weapon.Set, weapon.Type, (byte)weapon.Variant, MainhandType);
if (!valid || id == OffHand)
return false;

View file

@ -5,6 +5,7 @@ using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Dalamud.Plugin;
using Glamourer.Services;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using OtterGui.Classes;
@ -12,20 +13,20 @@ using OtterGui.Filesystem;
namespace Glamourer.Designs;
public sealed class DesignFileSystem : FileSystem<Design>, IDisposable
public sealed class DesignFileSystem : FileSystem<Design>, IDisposable, ISavable
{
public static string GetDesignFileSystemFile(DalamudPluginInterface pi)
=> Path.Combine(pi.GetPluginConfigDirectory(), "sort_order.json");
public readonly string DesignFileSystemFile;
private readonly FrameworkManager _framework;
private readonly Design.Manager _designManager;
public readonly string DesignFileSystemFile;
private readonly SaveService _saveService;
private readonly Design.Manager _designManager;
public DesignFileSystem(Design.Manager designManager, DalamudPluginInterface pi, FrameworkManager framework)
public DesignFileSystem(Design.Manager designManager, DalamudPluginInterface pi, SaveService saveService)
{
DesignFileSystemFile = GetDesignFileSystemFile(pi);
_designManager = designManager;
_framework = framework;
_saveService = saveService;
_designManager.DesignChange += OnDataChange;
Changed += OnChange;
Reload();
@ -34,7 +35,7 @@ public sealed class DesignFileSystem : FileSystem<Design>, IDisposable
private void Reload()
{
if (Load(new FileInfo(DesignFileSystemFile), _designManager.Designs, DesignToIdentifier, DesignToName))
SaveFilesystem();
_saveService.ImmediateSave(this);
Glamourer.Log.Debug("Reloaded design filesystem.");
}
@ -71,18 +72,9 @@ public sealed class DesignFileSystem : FileSystem<Design>, IDisposable
private void OnChange(FileSystemChangeType type, IPath _1, IPath? _2, IPath? _3)
{
if (type != FileSystemChangeType.Reload)
SaveFilesystem();
_saveService.QueueSave(this);
}
private void SaveFilesystem()
{
SaveToFile(new FileInfo(DesignFileSystemFile), SaveDesign, true);
Glamourer.Log.Verbose("Saved design filesystem.");
}
public void Save()
=> _framework.RegisterDelayed(nameof(SaveFilesystem), SaveFilesystem);
private void OnDataChange(Design.Manager.DesignChangeType type, Design design, object? data)
{
switch (type)
@ -176,4 +168,12 @@ public sealed class DesignFileSystem : FileSystem<Design>, IDisposable
Glamourer.Log.Error($"Could not migrate old folder paths to new version:\n{ex}");
}
}
public string ToFilename(FilenameService fileNames)
=> fileNames.DesignFileSystem;
public void Save(StreamWriter writer)
{
SaveToFile(writer, SaveDesign, true);
}
}