From f10280d15d08971421d09ae28d226832f9176b7e Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Fri, 27 Aug 2021 15:06:58 +0200 Subject: [PATCH] API 4 updates --- .../Customization/ActorCustomization.cs | 6 +- Glamourer.GameData/Customization/CmpFile.cs | 7 +- .../Customization/CustomizationManager.cs | 6 +- .../Customization/CustomizationOptions.cs | 31 +-- .../Customization/CustomizationSet.cs | 4 +- Glamourer.GameData/{Main.cs => GameData.cs} | 10 +- Glamourer.GameData/Glamourer.GameData.csproj | 5 +- Glamourer.GameData/Util/IconStorage.cs | 27 ++- ...orExtensions.cs => CharacterExtensions.cs} | 26 +-- Glamourer/CharacterSave.cs | 12 +- Glamourer/CmpFile.cs | 23 -- Glamourer/Dalamud.cs | 56 +++++ Glamourer/Designs/DesignManager.cs | 25 +-- Glamourer/FileSystem/FileSystemImGui.cs | 5 +- Glamourer/FileSystem/IFolderStructure.cs | 7 +- Glamourer/Glamourer.csproj | 25 +-- Glamourer/Glamourer.json | 2 +- Glamourer/GlamourerConfig.cs | 14 +- Glamourer/Gui/ComboWithFilter.cs | 16 +- Glamourer/Gui/ImGuiRaii.cs | 19 +- Glamourer/Gui/Interface.cs | 27 +-- Glamourer/Gui/InterfaceActorPanel.cs | 82 +++---- Glamourer/Gui/InterfaceActorSelector.cs | 28 +-- Glamourer/Gui/InterfaceConfig.cs | 4 +- Glamourer/Gui/InterfaceCustomization.cs | 18 +- Glamourer/Gui/InterfaceDesigns.cs | 12 +- Glamourer/Gui/InterfaceHelpers.cs | 9 +- Glamourer/Gui/InterfaceInitialization.cs | 4 +- Glamourer/Gui/InterfaceMiscellaneous.cs | 4 +- Glamourer/Main.cs | 206 ++++++++---------- repo.json | 6 +- 31 files changed, 359 insertions(+), 367 deletions(-) rename Glamourer.GameData/{Main.cs => GameData.cs} (88%) rename Glamourer/{ActorExtensions.cs => CharacterExtensions.cs} (71%) delete mode 100644 Glamourer/CmpFile.cs create mode 100644 Glamourer/Dalamud.cs diff --git a/Glamourer.GameData/Customization/ActorCustomization.cs b/Glamourer.GameData/Customization/ActorCustomization.cs index cbfd3ac..49c0f06 100644 --- a/Glamourer.GameData/Customization/ActorCustomization.cs +++ b/Glamourer.GameData/Customization/ActorCustomization.cs @@ -1,6 +1,6 @@ using System; using System.Runtime.InteropServices; -using Dalamud.Game.ClientState.Actors.Types; +using Dalamud.Game.ClientState.Objects.Types; using Penumbra.GameData.Enums; namespace Glamourer.Customization @@ -150,10 +150,10 @@ namespace Glamourer.Customization } } - public void Read(Actor actor) + public void Read(Character actor) => Read(actor.Address + CustomizationOffset); - public ActorCustomization(Actor actor) + public ActorCustomization(Character actor) : this() { Read(actor.Address + CustomizationOffset); diff --git a/Glamourer.GameData/Customization/CmpFile.cs b/Glamourer.GameData/Customization/CmpFile.cs index e320ab2..c709a0e 100644 --- a/Glamourer.GameData/Customization/CmpFile.cs +++ b/Glamourer.GameData/Customization/CmpFile.cs @@ -1,4 +1,5 @@ -using Dalamud.Plugin; +using Dalamud.Data; +using Dalamud.Plugin; namespace Glamourer { @@ -7,9 +8,9 @@ namespace Glamourer public readonly Lumina.Data.FileResource File; public readonly uint[] RgbaColors; - public CmpFile(DalamudPluginInterface pi) + public CmpFile(DataManager gameData) { - File = pi.Data.GetFile("chara/xls/charamake/human.cmp"); + File = gameData.GetFile("chara/xls/charamake/human.cmp")!; RgbaColors = new uint[File.Data.Length >> 2]; for (var i = 0; i < File.Data.Length; i += 4) { diff --git a/Glamourer.GameData/Customization/CustomizationManager.cs b/Glamourer.GameData/Customization/CustomizationManager.cs index 086903c..3d1a4f0 100644 --- a/Glamourer.GameData/Customization/CustomizationManager.cs +++ b/Glamourer.GameData/Customization/CustomizationManager.cs @@ -1,4 +1,6 @@ using System.Collections.Generic; +using Dalamud; +using Dalamud.Data; using Dalamud.Plugin; using Penumbra.GameData.Enums; @@ -11,9 +13,9 @@ namespace Glamourer.Customization private CustomizationManager() { } - public static ICustomizationManager Create(DalamudPluginInterface pi) + public static ICustomizationManager Create(DalamudPluginInterface pi, DataManager gameData, ClientLanguage language) { - _options ??= new CustomizationOptions(pi); + _options ??= new CustomizationOptions(pi, gameData, language); return new CustomizationManager(); } diff --git a/Glamourer.GameData/Customization/CustomizationOptions.cs b/Glamourer.GameData/Customization/CustomizationOptions.cs index a95b459..ef2176f 100644 --- a/Glamourer.GameData/Customization/CustomizationOptions.cs +++ b/Glamourer.GameData/Customization/CustomizationOptions.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using Dalamud; +using Dalamud.Data; using Dalamud.Plugin; using Glamourer.Util; using Lumina.Data; @@ -50,7 +51,7 @@ namespace Glamourer.Customization private Customization[] GetHairStyles(SubRace race, Gender gender) { - var row = _hairSheet.GetRow(((uint) race - 1) * 2 - 1 + (uint) gender); + var row = _hairSheet.GetRow(((uint) race - 1) * 2 - 1 + (uint) gender)!; var hairList = new List(row.Unknown30); for (var i = 0; i < row.Unknown30; ++i) { @@ -129,7 +130,7 @@ namespace Glamourer.Customization private CustomizationSet GetSet(SubRace race, Gender gender) { var (skin, hair) = GetColors(race, gender); - var row = _listSheet.GetRow(((uint) race - 1) * 2 - 1 + (uint) gender); + var row = _listSheet.GetRow(((uint) race - 1) * 2 - 1 + (uint) gender)!; var set = new CustomizationSet(race, gender) { HairStyles = race.ToRace() == Race.Hrothgar ? HrothgarFaces(row) : GetHairStyles(race, gender), @@ -211,7 +212,7 @@ namespace Glamourer.Customization return textRow?.Text.ToString() ?? c.ToDefaultName(); }).ToArray(); - set._types = ((CustomizationId[]) Enum.GetValues(typeof(CustomizationId))).Select(c => + set.Types = ((CustomizationId[]) Enum.GetValues(typeof(CustomizationId))).Select(c => { if (c == CustomizationId.HighlightColor) return CharaMakeParams.MenuType.ColorPicker; @@ -255,21 +256,21 @@ namespace Glamourer.Customization _ => Language.English, }; - internal CustomizationOptions(DalamudPluginInterface pi) + internal CustomizationOptions(DalamudPluginInterface pi, DataManager gameData, ClientLanguage language) { - _cmpFile = new CmpFile(pi); - _customizeSheet = pi.Data.GetExcelSheet(); - _lobby = pi.Data.GetExcelSheet(); - var tmp = pi.Data.Excel.GetType()!.GetMethod("GetSheet", BindingFlags.Instance | BindingFlags.NonPublic)! - .MakeGenericMethod(typeof(CharaMakeParams))!.Invoke(pi.Data.Excel, new object?[] + _cmpFile = new CmpFile(gameData); + _customizeSheet = gameData.GetExcelSheet()!; + _lobby = gameData.GetExcelSheet()!; + var tmp = gameData.Excel.GetType()!.GetMethod("GetSheet", BindingFlags.Instance | BindingFlags.NonPublic)! + .MakeGenericMethod(typeof(CharaMakeParams))!.Invoke(gameData.Excel, new object?[] { "charamaketype", - FromClientLanguage(pi.ClientState.ClientLanguage), + FromClientLanguage(language), null, }) as ExcelSheet; _listSheet = tmp!; - _hairSheet = pi.Data.GetExcelSheet(); - SetNames(pi); + _hairSheet = gameData.GetExcelSheet()!; + SetNames(gameData); _highlightPicker = CreateColorPicker(CustomizationId.HighlightColor, 256, 192); _lipColorPickerDark = CreateColorPicker(CustomizationId.LipColor, 512, 96); @@ -279,7 +280,7 @@ namespace Glamourer.Customization _facePaintColorPickerLight = CreateColorPicker(CustomizationId.FacePaintColor, 1152, 96, true); _tattooColorPicker = CreateColorPicker(CustomizationId.TattooColor, 0, 192); - _icons = new IconStorage(pi, _list.Length * 50); + _icons = new IconStorage(pi, gameData, _list.Length * 50); foreach (var race in Clans) { foreach (var gender in Genders) @@ -287,9 +288,9 @@ namespace Glamourer.Customization } } - public void SetNames(DalamudPluginInterface pi) + private void SetNames(DataManager gameData) { - var subRace = pi.Data.GetExcelSheet(); + var subRace = gameData.GetExcelSheet()!; _names[(int) CustomName.Clan] = _lobby.GetRow(102)?.Text ?? "Clan"; _names[(int) CustomName.Gender] = _lobby.GetRow(103)?.Text ?? "Gender"; _names[(int) CustomName.Reverse] = _lobby.GetRow(2135)?.Text ?? "Reverse"; diff --git a/Glamourer.GameData/Customization/CustomizationSet.cs b/Glamourer.GameData/Customization/CustomizationSet.cs index 035c956..8e6017d 100644 --- a/Glamourer.GameData/Customization/CustomizationSet.cs +++ b/Glamourer.GameData/Customization/CustomizationSet.cs @@ -69,7 +69,7 @@ namespace Glamourer.Customization public IReadOnlyList LipColorsLight { get; internal set; } = null!; public IReadOnlyList LipColorsDark { get; internal set; } = null!; - public IReadOnlyList _types { get; internal set; } = null!; + public IReadOnlyList Types { get; internal set; } = null!; public string Option(CustomizationId id) => OptionName[(int) id]; @@ -154,7 +154,7 @@ namespace Glamourer.Customization } public CharaMakeParams.MenuType Type(CustomizationId id) - => _types[(int) id]; + => Types[(int) id]; public int Count(CustomizationId id) diff --git a/Glamourer.GameData/Main.cs b/Glamourer.GameData/GameData.cs similarity index 88% rename from Glamourer.GameData/Main.cs rename to Glamourer.GameData/GameData.cs index 40c64ae..0af2def 100644 --- a/Glamourer.GameData/Main.cs +++ b/Glamourer.GameData/GameData.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; -using Dalamud.Plugin; +using Dalamud.Data; using Penumbra.GameData.Enums; namespace Glamourer @@ -11,22 +11,22 @@ namespace Glamourer private static Dictionary? _stains; private static Dictionary>? _itemsBySlot; - public static IReadOnlyDictionary Stains(DalamudPluginInterface pi) + public static IReadOnlyDictionary Stains(DataManager dataManager) { if (_stains != null) return _stains; - var sheet = pi.Data.GetExcelSheet(); + var sheet = dataManager.GetExcelSheet()!; _stains = sheet.Where(s => s.Color != 0).ToDictionary(s => (byte) s.RowId, s => new Stain((byte) s.RowId, s)); return _stains; } - public static IReadOnlyDictionary> ItemsBySlot(DalamudPluginInterface pi) + public static IReadOnlyDictionary> ItemsBySlot(DataManager dataManager) { if (_itemsBySlot != null) return _itemsBySlot; - var sheet = pi.Data.GetExcelSheet(); + var sheet = dataManager.GetExcelSheet()!; Item EmptySlot(EquipSlot slot) => new(sheet.First(), "Nothing", slot); diff --git a/Glamourer.GameData/Glamourer.GameData.csproj b/Glamourer.GameData/Glamourer.GameData.csproj index 7c1be7c..8dca87b 100644 --- a/Glamourer.GameData/Glamourer.GameData.csproj +++ b/Glamourer.GameData/Glamourer.GameData.csproj @@ -1,7 +1,8 @@ - net472 - preview + net5.0-windows + preview + x64 Glamourer Glamourer.GameData 1.0.0.0 diff --git a/Glamourer.GameData/Util/IconStorage.cs b/Glamourer.GameData/Util/IconStorage.cs index 24aa63a..0d6d37e 100644 --- a/Glamourer.GameData/Util/IconStorage.cs +++ b/Glamourer.GameData/Util/IconStorage.cs @@ -1,7 +1,8 @@ using System; using System.Collections.Generic; -using Dalamud.Data.LuminaExtensions; +using Dalamud.Data; using Dalamud.Plugin; +using Dalamud.Utility; using ImGuiScene; using Lumina.Data.Files; @@ -9,33 +10,35 @@ namespace Glamourer.Util { public class IconStorage : IDisposable { - private readonly DalamudPluginInterface _pi; - private readonly Dictionary _icons; + private readonly DalamudPluginInterface _pi; + private readonly DataManager _gameData; + private readonly Dictionary _icons; - public IconStorage(DalamudPluginInterface pi, int size = 0) + public IconStorage(DalamudPluginInterface pi, DataManager gameData, int size = 0) { - _pi = pi; - _icons = new Dictionary(size); + _pi = pi; + _gameData = gameData; + _icons = new Dictionary(size); } public TextureWrap this[int id] => LoadIcon(id); - private TexFile? LoadIconHq(int id) + private TexFile? LoadIconHq(uint id) { var path = $"ui/icon/{id / 1000 * 1000:000000}/{id:000000}_hr1.tex"; - return _pi.Data.GetFile(path); + return _gameData.GetFile(path); } - public TextureWrap LoadIcon(uint id) - => LoadIcon((int) id); - public TextureWrap LoadIcon(int id) + => LoadIcon((uint) id); + + public TextureWrap LoadIcon(uint id) { if (_icons.TryGetValue(id, out var ret)) return ret; - var icon = LoadIconHq(id) ?? _pi.Data.GetIcon(id); + var icon = LoadIconHq(id) ?? _gameData.GetIcon(id)!; var iconData = icon.GetRgbaImageData(); ret = _pi.UiBuilder.LoadImageRaw(iconData, icon.Header.Width, icon.Header.Height, 4); diff --git a/Glamourer/ActorExtensions.cs b/Glamourer/CharacterExtensions.cs similarity index 71% rename from Glamourer/ActorExtensions.cs rename to Glamourer/CharacterExtensions.cs index 158c0c2..a0f21e5 100644 --- a/Glamourer/ActorExtensions.cs +++ b/Glamourer/CharacterExtensions.cs @@ -1,8 +1,8 @@ -using Dalamud.Game.ClientState.Actors.Types; +using Dalamud.Game.ClientState.Objects.Types; namespace Glamourer { - public static class ActorExtensions + public static class CharacterExtensions { public const int WetnessOffset = 0x19A5; public const byte WetnessFlag = 0x10; @@ -13,10 +13,10 @@ namespace Glamourer public const int WeaponHiddenOffset = 0xF64; public const byte WeaponHiddenFlag = 0x02; - public static unsafe bool IsWet(this Actor a) + public static unsafe bool IsWet(this Character a) => (*((byte*) a.Address + WetnessOffset) & WetnessFlag) != 0; - public static unsafe bool SetWetness(this Actor a, bool value) + public static unsafe bool SetWetness(this Character a, bool value) { var current = a.IsWet(); if (current == value) @@ -29,10 +29,10 @@ namespace Glamourer return true; } - public static unsafe ref byte StateFlags(this Actor a) + public static unsafe ref byte StateFlags(this Character a) => ref *((byte*) a.Address + StateFlagsOffset); - public static bool SetStateFlag(this Actor a, bool value, byte flag) + public static bool SetStateFlag(this Character a, bool value, byte flag) { var current = a.StateFlags(); var previousValue = (current & flag) != 0; @@ -46,20 +46,20 @@ namespace Glamourer return true; } - public static bool IsHatHidden(this Actor a) + public static bool IsHatHidden(this Character a) => (a.StateFlags() & HatHiddenFlag) != 0; - public static unsafe bool IsWeaponHidden(this Actor a) + public static unsafe bool IsWeaponHidden(this Character a) => (a.StateFlags() & WeaponHiddenFlag) != 0 && (*((byte*) a.Address + WeaponHiddenOffset) & WeaponHiddenFlag) != 0; - public static bool IsVisorToggled(this Actor a) + public static bool IsVisorToggled(this Character a) => (a.StateFlags() & VisorToggledFlag) != 0; - public static bool SetHatHidden(this Actor a, bool value) + public static bool SetHatHidden(this Character a, bool value) => SetStateFlag(a, value, HatHiddenFlag); - public static unsafe bool SetWeaponHidden(this Actor a, bool value) + public static unsafe bool SetWeaponHidden(this Character a, bool value) { var ret = SetStateFlag(a, value, WeaponHiddenFlag); var val = *((byte*) a.Address + WeaponHiddenOffset); @@ -70,10 +70,10 @@ namespace Glamourer return ret || (val & WeaponHiddenFlag) != 0 != value; } - public static bool SetVisorToggled(this Actor a, bool value) + public static bool SetVisorToggled(this Character a, bool value) => SetStateFlag(a, value, VisorToggledFlag); - public static unsafe ref float Alpha(this Actor a) + public static unsafe ref float Alpha(this Character a) => ref *(float*) ((byte*) a.Address + AlphaOffset); } } diff --git a/Glamourer/CharacterSave.cs b/Glamourer/CharacterSave.cs index 2107caf..f31dc09 100644 --- a/Glamourer/CharacterSave.cs +++ b/Glamourer/CharacterSave.cs @@ -1,5 +1,5 @@ using System; -using Dalamud.Game.ClientState.Actors.Types; +using Dalamud.Game.ClientState.Objects.Types; using Glamourer.Customization; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -121,7 +121,7 @@ namespace Glamourer public ActorEquipMask WriteEquipment { - get => (ActorEquipMask) ((ushort) _bytes[2] | ((ushort) _bytes[3] << 8)); + get => (ActorEquipMask) (_bytes[2] | (_bytes[3] << 8)); set { _bytes[2] = (byte) ((ushort) value & 0xFF); @@ -181,17 +181,17 @@ namespace Glamourer private static void CheckActorMask(byte val1, byte val2) { - var mask = (ActorEquipMask) ((ushort) val1 | ((ushort) val2 << 8)); + var mask = (ActorEquipMask) (val1 | (val2 << 8)); if (mask > ActorEquipMask.All) throw new Exception($"Can not parse Base64 string into CharacterSave:\n\tInvalid value {mask} in byte 3 and 4."); } - public void LoadActor(Actor a) + public void LoadActor(Character a) { WriteCustomizations = true; Load(new ActorCustomization(a)); - Load(new ActorEquipment(a), ActorEquipMask.All); + Load(new ActorEquipment(a)); SetHatState = true; SetVisorState = true; @@ -202,7 +202,7 @@ namespace Glamourer Alpha = a.Alpha(); } - public void Apply(Actor a) + public void Apply(Character a) { if (WriteCustomizations) Customizations.Write(a.Address); diff --git a/Glamourer/CmpFile.cs b/Glamourer/CmpFile.cs deleted file mode 100644 index e320ab2..0000000 --- a/Glamourer/CmpFile.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Dalamud.Plugin; - -namespace Glamourer -{ - public class CmpFile - { - public readonly Lumina.Data.FileResource File; - public readonly uint[] RgbaColors; - - public CmpFile(DalamudPluginInterface pi) - { - File = pi.Data.GetFile("chara/xls/charamake/human.cmp"); - RgbaColors = new uint[File.Data.Length >> 2]; - for (var i = 0; i < File.Data.Length; i += 4) - { - RgbaColors[i >> 2] = File.Data[i] - | (uint) (File.Data[i + 1] << 8) - | (uint) (File.Data[i + 2] << 16) - | (uint) (File.Data[i + 3] << 24); - } - } - } -} diff --git a/Glamourer/Dalamud.cs b/Glamourer/Dalamud.cs new file mode 100644 index 0000000..80ac1a4 --- /dev/null +++ b/Glamourer/Dalamud.cs @@ -0,0 +1,56 @@ +using Dalamud.Data; +using Dalamud.Game; +using Dalamud.Game.ClientState; +using Dalamud.Game.ClientState.Buddy; +using Dalamud.Game.ClientState.Conditions; +using Dalamud.Game.ClientState.Fates; +using Dalamud.Game.ClientState.JobGauge; +using Dalamud.Game.ClientState.Keys; +using Dalamud.Game.ClientState.Objects; +using Dalamud.Game.ClientState.Party; +using Dalamud.Game.Command; +using Dalamud.Game.Gui; +using Dalamud.Game.Gui.FlyText; +using Dalamud.Game.Gui.PartyFinder; +using Dalamud.Game.Gui.Toast; +using Dalamud.Game.Libc; +using Dalamud.Game.Network; +using Dalamud.Game.Text.SeStringHandling; +using Dalamud.IoC; +using Dalamud.Plugin; +// ReSharper disable AutoPropertyCanBeMadeGetOnly.Local + +namespace Glamourer +{ + public class Dalamud + { + public static void Initialize(DalamudPluginInterface pluginInterface) + => pluginInterface.Create(); + + // @formatter:off + [PluginService][RequiredVersion("1.0")] public static DalamudPluginInterface PluginInterface { get; private set; } = null!; + [PluginService][RequiredVersion("1.0")] public static CommandManager Commands { get; private set; } = null!; + [PluginService][RequiredVersion("1.0")] public static SigScanner SigScanner { get; private set; } = null!; + [PluginService][RequiredVersion("1.0")] public static DataManager GameData { get; private set; } = null!; + [PluginService][RequiredVersion("1.0")] public static ClientState ClientState { get; private set; } = null!; + [PluginService][RequiredVersion("1.0")] public static ChatGui Chat { get; private set; } = null!; + //[PluginService][RequiredVersion("1.0")] public static SeStringManager SeStrings { get; private set; } = null!; + //[PluginService][RequiredVersion("1.0")] public static ChatHandlers ChatHandlers { get; private set; } = null!; + [PluginService][RequiredVersion("1.0")] public static Framework Framework { get; private set; } = null!; + //[PluginService][RequiredVersion("1.0")] public static GameNetwork Network { get; private set; } = null!; + [PluginService][RequiredVersion("1.0")] public static Condition Conditions { get; private set; } = null!; + //[PluginService][RequiredVersion("1.0")] public static KeyState Keys { get; private set; } = null!; + //[PluginService][RequiredVersion("1.0")] public static GameGui GameGui { get; private set; } = null!; + //[PluginService][RequiredVersion("1.0")] public static FlyTextGui FlyTexts { get; private set; } = null!; + //[PluginService][RequiredVersion("1.0")] public static ToastGui Toasts { get; private set; } = null!; + //[PluginService][RequiredVersion("1.0")] public static JobGauges Gauges { get; private set; } = null!; + //[PluginService][RequiredVersion("1.0")] public static PartyFinderGui PartyFinder { get; private set; } = null!; + //[PluginService][RequiredVersion("1.0")] public static BuddyList Buddies { get; private set; } = null!; + //[PluginService][RequiredVersion("1.0")] public static PartyList Party { get; private set; } = null!; + [PluginService][RequiredVersion("1.0")] public static TargetManager Targets { get; private set; } = null!; + [PluginService][RequiredVersion("1.0")] public static ObjectTable Objects { get; private set; } = null!; + //[PluginService][RequiredVersion("1.0")] public static FateTable Fates { get; private set; } = null!; + //[PluginService][RequiredVersion("1.0")] public static LibcFunction LibC { get; private set; } = null!; + // @formatter:on + } +} diff --git a/Glamourer/Designs/DesignManager.cs b/Glamourer/Designs/DesignManager.cs index 73d9a96..31fefcf 100644 --- a/Glamourer/Designs/DesignManager.cs +++ b/Glamourer/Designs/DesignManager.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using Dalamud.Plugin; +using Dalamud.Logging; using Glamourer.FileSystem; using Newtonsoft.Json; @@ -16,9 +16,9 @@ namespace Glamourer.Designs public SortedList Designs = null!; public FileSystem.FileSystem FileSystem { get; } = new(); - public DesignManager(DalamudPluginInterface pi) + public DesignManager() { - var saveFolder = new DirectoryInfo(pi.GetPluginConfigDirectory()); + var saveFolder = new DirectoryInfo(Dalamud.PluginInterface.GetPluginConfigDirectory()); if (!saveFolder.Exists) Directory.CreateDirectory(saveFolder.FullName); @@ -31,24 +31,21 @@ namespace Glamourer.Designs { FileSystem.Clear(); var anyChanges = false; - foreach (var kvp in Designs.ToArray()) + foreach (var (path, save) in Designs.ToArray()) { - var path = kvp.Key; - var save = kvp.Value; - try { var (folder, name) = FileSystem.CreateAllFolders(path); var design = new Design(folder, name) { Data = save }; folder.FindOrAddChild(design); var fixedPath = design.FullName(); - if (!string.Equals(fixedPath, path, StringComparison.InvariantCultureIgnoreCase)) - { - Designs.Remove(path); - Designs[fixedPath] = save; - anyChanges = true; - PluginLog.Debug($"Problem loading saved designs, {path} was renamed to {fixedPath}."); - } + if (string.Equals(fixedPath, path, StringComparison.InvariantCultureIgnoreCase)) + continue; + + Designs.Remove(path); + Designs[fixedPath] = save; + anyChanges = true; + PluginLog.Debug($"Problem loading saved designs, {path} was renamed to {fixedPath}."); } catch (Exception e) { diff --git a/Glamourer/FileSystem/FileSystemImGui.cs b/Glamourer/FileSystem/FileSystemImGui.cs index a358be2..8c70368 100644 --- a/Glamourer/FileSystem/FileSystemImGui.cs +++ b/Glamourer/FileSystem/FileSystemImGui.cs @@ -1,6 +1,5 @@ using System; -using System.Linq; -using Dalamud.Plugin; +using Dalamud.Logging; using ImGuiNET; namespace Glamourer.FileSystem @@ -12,7 +11,7 @@ namespace Glamourer.FileSystem private static unsafe bool IsDropping(string name) => ImGui.AcceptDragDropPayload(name).NativePtr != null; - private static IFileSystemBase? _draggedObject = null; + private static IFileSystemBase? _draggedObject; public static bool DragDropTarget(FileSystem fs, IFileSystemBase child, out string oldPath, out IFileSystemBase? draggedChild) { diff --git a/Glamourer/FileSystem/IFolderStructure.cs b/Glamourer/FileSystem/IFolderStructure.cs index f4bf01b..fc0cabd 100644 --- a/Glamourer/FileSystem/IFolderStructure.cs +++ b/Glamourer/FileSystem/IFolderStructure.cs @@ -1,17 +1,16 @@ using System; using System.Collections.Generic; using System.Linq; -using Glamourer.Designs; namespace Glamourer.FileSystem { internal class FolderStructureComparer : IComparer { // Compare only the direct folder names since this is only used inside an enumeration of children of one folder. - public static int Cmp(IFileSystemBase x, IFileSystemBase y) - => ReferenceEquals(x, y) ? 0 : string.Compare(x.Name, y.Name, StringComparison.InvariantCultureIgnoreCase); + public static int Cmp(IFileSystemBase? x, IFileSystemBase? y) + => ReferenceEquals(x, y) ? 0 : string.Compare(x?.Name, y?.Name, StringComparison.InvariantCultureIgnoreCase); - public int Compare(IFileSystemBase x, IFileSystemBase y) + public int Compare(IFileSystemBase? x, IFileSystemBase? y) => Cmp(x, y); internal static readonly FolderStructureComparer Default = new(); diff --git a/Glamourer/Glamourer.csproj b/Glamourer/Glamourer.csproj index 9249764..a2295f7 100644 --- a/Glamourer/Glamourer.csproj +++ b/Glamourer/Glamourer.csproj @@ -1,11 +1,12 @@  - net472 + net5.0-windows preview + x64 Glamourer Glamourer - 0.0.3.0 - 0.0.3.0 + 0.0.4.0 + 0.0.4.0 SoftOtter Glamourer Copyright © 2020 @@ -63,25 +64,15 @@ $(appdata)\XIVLauncher\addon\Hooks\dev\Lumina.Excel.dll - ..\..\Penumbra\Penumbra\bin\$(Configuration)\net472\Penumbra.GameData.dll + ..\..\Penumbra\Penumbra\bin\$(Configuration)\$(TargetFramework)\Penumbra.GameData.dll - ..\..\Penumbra\Penumbra\bin\$(Configuration)\net472\Penumbra.Api.dll + ..\..\Penumbra\Penumbra\bin\$(Configuration)\$(TargetFramework)\Penumbra.Api.dll - ..\..\Penumbra\Penumbra\bin\$(Configuration)\net472\Penumbra.PlayerWatch.dll + ..\..\Penumbra\Penumbra\bin\$(Configuration)\$(TargetFramework)\Penumbra.PlayerWatch.dll - - - - - - - - - - - + diff --git a/Glamourer/Glamourer.json b/Glamourer/Glamourer.json index 6556e2d..2ec9671 100644 --- a/Glamourer/Glamourer.json +++ b/Glamourer/Glamourer.json @@ -6,6 +6,6 @@ "AssemblyVersion": "0.0.3.0", "RepoUrl": "https://github.com/Ottermandias/Glamourer", "ApplicableVersion": "any", - "DalamudApiLevel": 3, + "DalamudApiLevel": 4, "LoadPriority": -100 } \ No newline at end of file diff --git a/Glamourer/GlamourerConfig.cs b/Glamourer/GlamourerConfig.cs index 2fa5da4..c948e8f 100644 --- a/Glamourer/GlamourerConfig.cs +++ b/Glamourer/GlamourerConfig.cs @@ -20,17 +20,15 @@ namespace Glamourer public uint EquipmentColor { get; set; } = DefaultEquipmentColor; public void Save() - => Glamourer.PluginInterface.SavePluginConfig(this); + => Dalamud.PluginInterface.SavePluginConfig(this); - public static GlamourerConfig Create() + public static GlamourerConfig Load() { - var config = Glamourer.PluginInterface.GetPluginConfig() as GlamourerConfig; - if (config == null) - { - config = new GlamourerConfig(); - Glamourer.PluginInterface.SavePluginConfig(config); - } + if (Dalamud.PluginInterface.GetPluginConfig() is GlamourerConfig config) + return config; + config = new GlamourerConfig(); + config.Save(); return config; } } diff --git a/Glamourer/Gui/ComboWithFilter.cs b/Glamourer/Gui/ComboWithFilter.cs index 69f4fdd..5a40a6d 100644 --- a/Glamourer/Gui/ComboWithFilter.cs +++ b/Glamourer/Gui/ComboWithFilter.cs @@ -20,12 +20,12 @@ namespace Glamourer.Gui private readonly IReadOnlyList _itemNamesLower; private readonly Func _itemToName; - public Action? PrePreview = null; - public Action? PostPreview = null; - public Func? CreateSelectable = null; - public Action? PreList = null; - public Action? PostList = null; - public float? HeightPerItem = null; + public Action? PrePreview; + public Action? PostPreview; + public Func? CreateSelectable; + public Action? PreList; + public Action? PostList; + public float? HeightPerItem; private float _heightPerItem; @@ -99,7 +99,7 @@ namespace Glamourer.Gui { nodeIdx = i; var item = _items[i]!; - var success = false; + bool success; if (CreateSelectable != null) { success = CreateSelectable(item); @@ -151,7 +151,7 @@ namespace Glamourer.Gui _heightPerItem = HeightPerItem ?? ImGui.GetTextLineHeightWithSpacing(); - var ret = false; + bool ret; try { ImGui.SetNextItemWidth(-1); diff --git a/Glamourer/Gui/ImGuiRaii.cs b/Glamourer/Gui/ImGuiRaii.cs index 8aba17b..5704be9 100644 --- a/Glamourer/Gui/ImGuiRaii.cs +++ b/Glamourer/Gui/ImGuiRaii.cs @@ -7,15 +7,12 @@ namespace Glamourer.Gui { public sealed class ImGuiRaii : IDisposable { - private int _colorStack = 0; - private int _fontStack = 0; - private int _styleStack = 0; - private float _indentation = 0f; + private int _colorStack; + private int _fontStack; + private int _styleStack; + private float _indentation; - private Stack? _onDispose = null; - - public ImGuiRaii() - { } + private Stack? _onDispose; public static ImGuiRaii NewGroup() => new ImGuiRaii().Group(); @@ -51,6 +48,7 @@ namespace Glamourer.Gui ImGui.PopStyleColor(actualN); _colorStack -= actualN; } + return this; } @@ -76,6 +74,7 @@ namespace Glamourer.Gui ImGui.PopStyleVar(actualN); _styleStack -= actualN; } + return this; } @@ -95,6 +94,7 @@ namespace Glamourer.Gui ImGui.PopFont(); --_fontStack; } + return this; } @@ -105,6 +105,7 @@ namespace Glamourer.Gui ImGui.Indent(width); _indentation += width; } + return this; } @@ -134,7 +135,7 @@ namespace Glamourer.Gui public void End(int n = 1) { var actualN = Math.Min(n, _onDispose?.Count ?? 0); - while(actualN-- > 0) + while (actualN-- > 0) _onDispose!.Pop()(); } diff --git a/Glamourer/Gui/Interface.cs b/Glamourer/Gui/Interface.cs index 02c9c96..366d986 100644 --- a/Glamourer/Gui/Interface.cs +++ b/Glamourer/Gui/Interface.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Numerics; -using Dalamud.Game.ClientState.Actors; using Glamourer.Designs; using ImGuiNET; using Penumbra.GameData; @@ -19,7 +18,6 @@ namespace Glamourer.Gui private readonly string _glamourerHeader; private readonly IReadOnlyDictionary _stains; - private readonly ActorTable _actors; private readonly IObjectIdentifier _identifier; private readonly Dictionary, ComboWithFilter)> _combos; private readonly ImGuiScene.TextureWrap? _legacyTattooIcon; @@ -27,8 +25,8 @@ namespace Glamourer.Gui private readonly DesignManager _designs; private readonly Glamourer _plugin; - private bool _visible = false; - private bool _inGPose = false; + private bool _visible; + private bool _inGPose; public Interface(Glamourer plugin) { @@ -37,31 +35,30 @@ namespace Glamourer.Gui _glamourerHeader = Glamourer.Version.Length > 0 ? $"{PluginName} v{Glamourer.Version}###{PluginName}Main" : $"{PluginName}###{PluginName}Main"; - Glamourer.PluginInterface.UiBuilder.DisableGposeUiHide = true; - Glamourer.PluginInterface.UiBuilder.OnBuildUi += Draw; - Glamourer.PluginInterface.UiBuilder.OnOpenConfigUi += ToggleVisibility; + Dalamud.PluginInterface.UiBuilder.DisableGposeUiHide = true; + Dalamud.PluginInterface.UiBuilder.Draw += Draw; + Dalamud.PluginInterface.UiBuilder.OpenConfigUi += ToggleVisibility; _equipSlotNames = GetEquipSlotNames(); - _stains = GameData.Stains(Glamourer.PluginInterface); - _identifier = Penumbra.GameData.GameData.GetIdentifier(Glamourer.PluginInterface); - _actors = Glamourer.PluginInterface.ClientState.Actors; + _stains = GameData.Stains(Dalamud.GameData); + _identifier = Penumbra.GameData.GameData.GetIdentifier(Dalamud.GameData, Dalamud.ClientState.ClientLanguage); var stainCombo = CreateDefaultStainCombo(_stains.Values.ToArray()); - var equip = GameData.ItemsBySlot(Glamourer.PluginInterface); + var equip = GameData.ItemsBySlot(Dalamud.GameData); _combos = equip.ToDictionary(kvp => kvp.Key, kvp => CreateCombos(kvp.Key, kvp.Value, stainCombo)); _legacyTattooIcon = GetLegacyTattooIcon(); } - public void ToggleVisibility(object _, object _2) + public void ToggleVisibility() => _visible = !_visible; public void Dispose() { _legacyTattooIcon?.Dispose(); - Glamourer.PluginInterface.UiBuilder.OnBuildUi -= Draw; - Glamourer.PluginInterface.UiBuilder.OnOpenConfigUi -= ToggleVisibility; + Dalamud.PluginInterface.UiBuilder.Draw -= Draw; + Dalamud.PluginInterface.UiBuilder.OpenConfigUi -= ToggleVisibility; } private void Draw() @@ -80,7 +77,7 @@ namespace Glamourer.Gui if (!raii.Begin(() => ImGui.BeginTabBar("##tabBar"), ImGui.EndTabBar)) return; - _inGPose = _actors[GPoseActorId] != null; + _inGPose = Dalamud.Objects[GPoseActorId] != null; _iconSize = Vector2.One * ImGui.GetTextLineHeightWithSpacing() * 2; _actualIconSize = _iconSize + 2 * ImGui.GetStyle().FramePadding; _comboSelectorSize = 4 * _actualIconSize.X + 3 * ImGui.GetStyle().ItemSpacing.X; diff --git a/Glamourer/Gui/InterfaceActorPanel.cs b/Glamourer/Gui/InterfaceActorPanel.cs index fac7506..79e55b1 100644 --- a/Glamourer/Gui/InterfaceActorPanel.cs +++ b/Glamourer/Gui/InterfaceActorPanel.cs @@ -1,9 +1,9 @@ using System; using System.Linq; using System.Numerics; -using System.Windows.Forms; +using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Interface; -using Dalamud.Plugin; +using Dalamud.Logging; using Glamourer.Designs; using Glamourer.FileSystem; using ImGuiNET; @@ -12,9 +12,9 @@ namespace Glamourer.Gui { internal partial class Interface { - private readonly CharacterSave _currentSave = new(); - private string _newDesignName = string.Empty; - private bool _keyboardFocus = false; + private readonly CharacterSave _currentSave = new(); + private string _newDesignName = string.Empty; + private bool _keyboardFocus; private const string DesignNamePopupLabel = "Save Design As..."; private const uint RedHeaderColor = 0xFF1818C0; private const uint GreenHeaderColor = 0xFF18C018; @@ -37,7 +37,7 @@ namespace Glamourer.Gui { ImGui.PushFont(UiBuilder.IconFont); if (ImGui.Button(FontAwesomeIcon.Clipboard.ToIconString())) - Clipboard.SetText(save.ToBase64()); + ImGui.SetClipboardText(save.ToBase64()); ImGui.PopFont(); if (ImGui.IsItemHovered()) ImGui.SetTooltip("Copy customization code to clipboard."); @@ -54,7 +54,7 @@ namespace Glamourer.Gui if (!applyButton) return false; - var text = Clipboard.GetText(); + var text = ImGui.GetClipboardText(); if (!text.Any()) return false; @@ -88,41 +88,41 @@ namespace Glamourer.Gui private void DrawTargetPlayerButton() { if (ImGui.Button("Target Player")) - Glamourer.PluginInterface.ClientState.Targets.SetCurrentTarget(_player); + Dalamud.Targets.SetTarget(_player); } private void DrawApplyToPlayerButton(CharacterSave save) { - if (ImGui.Button("Apply to Self")) - { - var player = _inGPose - ? Glamourer.PluginInterface.ClientState.Actors[GPoseActorId] - : Glamourer.PluginInterface.ClientState.LocalPlayer; - var fallback = _inGPose ? Glamourer.PluginInterface.ClientState.LocalPlayer : null; - if (player != null) - { - save.Apply(player); - if (_inGPose) - save.Apply(fallback!); - _plugin.UpdateActors(player, fallback); - } - } + if (!ImGui.Button("Apply to Self")) + return; + + var player = _inGPose + ? (Character?) Dalamud.Objects[GPoseActorId] + : Dalamud.ClientState.LocalPlayer; + var fallback = _inGPose ? Dalamud.ClientState.LocalPlayer : null; + if (player == null) + return; + + save.Apply(player); + if (_inGPose) + save.Apply(fallback!); + _plugin.UpdateActors(player, fallback); } private void DrawApplyToTargetButton(CharacterSave save) { - if (ImGui.Button("Apply to Target")) - { - var player = Glamourer.PluginInterface.ClientState.Targets.CurrentTarget; - if (player != null) - { - var fallBackActor = _playerNames[player.Name]; - save.Apply(player); - if (fallBackActor != null) - save.Apply(fallBackActor); - _plugin.UpdateActors(player, fallBackActor); - } - } + if (!ImGui.Button("Apply to Target")) + return; + + var player = Dalamud.Targets.Target as Character; + if (player == null) + return; + + var fallBackActor = _playerNames[player.Name.ToString()]; + save.Apply(player); + if (fallBackActor != null) + save.Apply(fallBackActor); + _plugin.UpdateActors(player, fallBackActor); } private void SaveNewDesign(CharacterSave save) @@ -130,13 +130,13 @@ namespace Glamourer.Gui try { var (folder, name) = _designs.FileSystem.CreateAllFolders(_newDesignName); - if (name.Any()) - { - var newDesign = new Design(folder, name) { Data = save }; - folder.AddChild(newDesign); - _designs.Designs[newDesign.FullName()] = save; - _designs.SaveToFile(); - } + if (!name.Any()) + return; + + var newDesign = new Design(folder, name) { Data = save }; + folder.AddChild(newDesign); + _designs.Designs[newDesign.FullName()] = save; + _designs.SaveToFile(); } catch (Exception e) { diff --git a/Glamourer/Gui/InterfaceActorSelector.cs b/Glamourer/Gui/InterfaceActorSelector.cs index 889b01a..c10fe46 100644 --- a/Glamourer/Gui/InterfaceActorSelector.cs +++ b/Glamourer/Gui/InterfaceActorSelector.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; using System.Linq; using System.Numerics; -using Dalamud.Game.ClientState.Actors; -using Dalamud.Game.ClientState.Actors.Types; +using Dalamud.Game.ClientState.Objects.Enums; +using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Interface; using ImGuiNET; @@ -10,11 +10,11 @@ namespace Glamourer.Gui { internal partial class Interface { - private Actor? _player; + private Character? _player; private string _currentActorName = string.Empty; private string _actorFilter = string.Empty; private string _actorFilterLower = string.Empty; - private readonly Dictionary _playerNames = new(400); + private readonly Dictionary _playerNames = new(400); private void DrawActorFilter() { @@ -26,9 +26,9 @@ namespace Glamourer.Gui _actorFilterLower = _actorFilter.ToLowerInvariant(); } - private void DrawActorSelectable(Actor actor, bool gPose) + private void DrawActorSelectable(Character actor, bool gPose) { - var actorName = actor.Name; + var actorName = actor.Name.ToString(); if (!actorName.Any()) return; @@ -50,7 +50,7 @@ namespace Glamourer.Gui return; } - if (_currentActorName == actor.Name) + if (_currentActorName == actorName) { _currentSave.LoadActor(actor); _player = actor; @@ -63,10 +63,10 @@ namespace Glamourer.Gui .PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero) .PushStyle(ImGuiStyleVar.FrameRounding, 0) .PushFont(UiBuilder.IconFont); - Actor? select = null; + Character? select = null; var buttonWidth = Vector2.UnitX * SelectorWidth / 2; if (ImGui.Button(FontAwesomeIcon.UserCircle.ToIconString(), buttonWidth)) - select = Glamourer.PluginInterface.ClientState.LocalPlayer; + select = Dalamud.ClientState.LocalPlayer; raii.PopFonts(); if (ImGui.IsItemHovered()) ImGui.SetTooltip("Select the local player character."); @@ -81,7 +81,7 @@ namespace Glamourer.Gui else { if (ImGui.Button(FontAwesomeIcon.HandPointer.ToIconString(), buttonWidth)) - select = Glamourer.PluginInterface.ClientState.Targets.CurrentTarget; + select = Dalamud.Targets.Target as Character; } raii.PopFonts(); @@ -92,7 +92,7 @@ namespace Glamourer.Gui return; _player = select; - _currentActorName = _player.Name; + _currentActorName = _player.Name.ToString(); _currentSave.LoadActor(_player); } @@ -107,7 +107,7 @@ namespace Glamourer.Gui _playerNames.Clear(); for (var i = GPoseActorId; i < GPoseActorId + 48; ++i) { - var actor = _actors[i]; + var actor = Dalamud.Objects[i] as Character; if (actor == null) break; @@ -117,13 +117,13 @@ namespace Glamourer.Gui for (var i = 0; i < GPoseActorId; i += 2) { - var actor = _actors[i]; + var actor = Dalamud.Objects[i] as Character; if (actor != null && actor.ObjectKind == ObjectKind.Player) DrawActorSelectable(actor, false); } - using (var raii = new ImGuiRaii().PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero)) + using (var _ = new ImGuiRaii().PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero)) { ImGui.EndChild(); } diff --git a/Glamourer/Gui/InterfaceConfig.cs b/Glamourer/Gui/InterfaceConfig.cs index 9e294a7..48d2702 100644 --- a/Glamourer/Gui/InterfaceConfig.cs +++ b/Glamourer/Gui/InterfaceConfig.cs @@ -53,7 +53,7 @@ namespace Glamourer.Gui return; } - if (ImGui.Button(buttonLabel) && _plugin.GetPenumbra()) + if (ImGui.Button(buttonLabel) && Glamourer.GetPenumbra()) { _plugin.UnregisterFunctions(); _plugin.RegisterFunctions(); @@ -88,7 +88,7 @@ namespace Glamourer.Gui cfg.AttachToPenumbra = v; if (v) { - if (_plugin.GetPenumbra()) + if (Glamourer.GetPenumbra()) _plugin.RegisterFunctions(); } else diff --git a/Glamourer/Gui/InterfaceCustomization.cs b/Glamourer/Gui/InterfaceCustomization.cs index 0e56c22..c856529 100644 --- a/Glamourer/Gui/InterfaceCustomization.cs +++ b/Glamourer/Gui/InterfaceCustomization.cs @@ -2,7 +2,7 @@ using System.Linq; using System.Numerics; using Dalamud.Interface; -using Dalamud.Plugin; +using Dalamud.Logging; using Glamourer.Customization; using ImGuiNET; using Penumbra.GameData.Enums; @@ -39,13 +39,13 @@ namespace Glamourer.Gui return ret; } - private Vector2 _iconSize = Vector2.Zero; - private Vector2 _actualIconSize = Vector2.Zero; - private float _raceSelectorWidth = 0; - private float _inputIntSize = 0; - private float _comboSelectorSize = 0; - private float _percentageSize = 0; - private float _itemComboWidth = 0; + private Vector2 _iconSize = Vector2.Zero; + private Vector2 _actualIconSize = Vector2.Zero; + private float _raceSelectorWidth; + private float _inputIntSize; + private float _comboSelectorSize; + private float _percentageSize; + private float _itemComboWidth; private bool InputInt(string label, ref int value, int minValue, int maxValue) { @@ -93,7 +93,7 @@ namespace Glamourer.Gui ImGui.SameLine(); - using (var group = ImGuiRaii.NewGroup()) + using (var _ = ImGuiRaii.NewGroup()) { if (InputInt($"##text_{id}", ref current, 1, count)) { diff --git a/Glamourer/Gui/InterfaceDesigns.cs b/Glamourer/Gui/InterfaceDesigns.cs index 6116e87..a65e937 100644 --- a/Glamourer/Gui/InterfaceDesigns.cs +++ b/Glamourer/Gui/InterfaceDesigns.cs @@ -1,9 +1,8 @@ using System; using System.Linq; using System.Numerics; -using System.Windows.Forms; using Dalamud.Interface; -using Dalamud.Plugin; +using Dalamud.Logging; using Glamourer.Designs; using Glamourer.FileSystem; using ImGuiNET; @@ -12,9 +11,9 @@ namespace Glamourer.Gui { internal partial class Interface { - private int _totalObject = 0; + private int _totalObject; - private Design? _selection = null; + private Design? _selection; private string _newChildName = string.Empty; private void DrawDesignSelector() @@ -50,7 +49,7 @@ namespace Glamourer.Gui if (_selection!.Data.WriteProtected || !applyButton) return; - var text = Clipboard.GetText(); + var text = ImGui.GetClipboardText(); if (!text.Any()) return; @@ -280,7 +279,6 @@ namespace Glamourer.Gui private void ContextMenu(IFileSystemBase child) { var label = $"##fsPopup{child.FullName()}"; - var renameLabel = $"{label}_rename"; if (ImGui.BeginPopup(label)) { if (ImGui.MenuItem("Delete")) @@ -289,7 +287,7 @@ namespace Glamourer.Gui RenameChildInput(child); if (child is Design d && ImGui.MenuItem("Copy to Clipboard")) - Clipboard.SetText(d.Data.ToBase64()); + ImGui.SetClipboardText(d.Data.ToBase64()); ImGui.EndPopup(); } diff --git a/Glamourer/Gui/InterfaceHelpers.cs b/Glamourer/Gui/InterfaceHelpers.cs index 84c0c5f..d7c3dbe 100644 --- a/Glamourer/Gui/InterfaceHelpers.cs +++ b/Glamourer/Gui/InterfaceHelpers.cs @@ -1,11 +1,8 @@ using System; using System.Linq; -using System.Windows.Forms; -using Dalamud.Game.ClientState.Actors.Types; -using Dalamud.Plugin; +using Dalamud.Logging; using Glamourer.Customization; using ImGuiNET; -using Penumbra.Api; using Penumbra.GameData.Enums; namespace Glamourer.Gui @@ -46,7 +43,7 @@ namespace Glamourer.Gui break; default: var count = set.Count(id); - if (set.DataByValue(id, customization[id], out var value) < 0) + if (set.DataByValue(id, customization[id], out _) < 0) if (count == 0) customization[id] = 0; else @@ -173,7 +170,7 @@ namespace Glamourer.Gui case DesignNameUse.FromClipboard: try { - var text = Clipboard.GetText(); + var text = ImGui.GetClipboardText(); var save = CharacterSave.FromString(text); SaveNewDesign(save); } diff --git a/Glamourer/Gui/InterfaceInitialization.cs b/Glamourer/Gui/InterfaceInitialization.cs index 4c279a6..1e4e1d5 100644 --- a/Glamourer/Gui/InterfaceInitialization.cs +++ b/Glamourer/Gui/InterfaceInitialization.cs @@ -53,7 +53,7 @@ namespace Glamourer.Gui { var rawImage = new byte[resource.Length]; resource.Read(rawImage, 0, (int) resource.Length); - return Glamourer.PluginInterface.UiBuilder.LoadImageRaw(rawImage, 192, 192, 4); + return Dalamud.PluginInterface.UiBuilder.LoadImageRaw(rawImage, 192, 192, 4); } return null; @@ -61,7 +61,7 @@ namespace Glamourer.Gui private static Dictionary GetEquipSlotNames() { - var sheet = Glamourer.PluginInterface.Data.GetExcelSheet(); + var sheet = Dalamud.GameData.GetExcelSheet()!; var ret = new Dictionary(12) { [EquipSlot.MainHand] = sheet.GetRow(738)?.Text.ToString() ?? "Main Hand", diff --git a/Glamourer/Gui/InterfaceMiscellaneous.cs b/Glamourer/Gui/InterfaceMiscellaneous.cs index f2ba9f6..87a4495 100644 --- a/Glamourer/Gui/InterfaceMiscellaneous.cs +++ b/Glamourer/Gui/InterfaceMiscellaneous.cs @@ -1,5 +1,5 @@ using System; -using Dalamud.Game.ClientState.Actors.Types; +using Dalamud.Game.ClientState.Objects.Types; using ImGuiNET; namespace Glamourer.Gui @@ -18,7 +18,7 @@ namespace Glamourer.Gui return false; } - private static bool DrawMiscellaneous(CharacterSave save, Actor? player) + private static bool DrawMiscellaneous(CharacterSave save, Character? player) { var ret = false; if (!ImGui.CollapsingHeader("Miscellaneous")) diff --git a/Glamourer/Main.cs b/Glamourer/Main.cs index 3823fc8..b17013d 100644 --- a/Glamourer/Main.cs +++ b/Glamourer/Main.cs @@ -1,10 +1,9 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Reflection; -using System.Windows.Forms; -using Dalamud.Game.ClientState.Actors.Types; +using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Game.Command; +using Dalamud.Logging; using Dalamud.Plugin; using Glamourer.Customization; using Glamourer.Designs; @@ -18,36 +17,23 @@ namespace Glamourer { public class Glamourer : IDalamudPlugin { - public const int RequiredPenumbraShareVersion = 1; + public const int RequiredPenumbraShareVersion = 3; private const string HelpString = "[Copy|Apply|Save],[Name or PlaceHolder],"; public string Name => "Glamourer"; - public static DalamudPluginInterface PluginInterface = null!; - public static GlamourerConfig Config = null!; - private Interface _interface = null!; - public static ICustomizationManager Customization = null!; - public DesignManager Designs = null!; - public IPlayerWatcher PlayerWatcher = null!; + public static GlamourerConfig Config = null!; + private Interface _interface = null!; + public static ICustomizationManager Customization = null!; + public DesignManager Designs = null!; + public IPlayerWatcher PlayerWatcher = null!; public static string Version = string.Empty; public static IPenumbraApi? Penumbra; - private Dalamud.Dalamud _dalamud = null!; - private List<(IDalamudPlugin Plugin, PluginDefinition Definition, DalamudPluginInterface PluginInterface, bool IsRaw)> _plugins = null!; - - private void SetDalamud(DalamudPluginInterface pi) - { - var dalamud = (Dalamud.Dalamud?) pi.GetType() - ?.GetField("dalamud", BindingFlags.NonPublic | BindingFlags.Instance) - ?.GetValue(pi); - - _dalamud = dalamud ?? throw new Exception("Could not obtain Dalamud."); - } - private static void PenumbraTooltip(object? it) { if (it is Lumina.Excel.GeneratedSheets.Item) @@ -56,22 +42,21 @@ namespace Glamourer private void PenumbraRightClick(MouseButton button, object? it) { - if (button == MouseButton.Right && it is Lumina.Excel.GeneratedSheets.Item item) + if (button != MouseButton.Right || it is not Lumina.Excel.GeneratedSheets.Item item) + return; + + var gPose = Dalamud.Objects[Interface.GPoseActorId] as Character; + var player = Dalamud.Objects[0] as Character; + var writeItem = new Item(item, string.Empty); + if (gPose != null) { - var actors = PluginInterface.ClientState.Actors; - var gPose = actors[Interface.GPoseActorId]; - var player = actors[0]; - var writeItem = new Item(item, string.Empty); - if (gPose != null) - { - writeItem.Write(gPose.Address); - UpdateActors(gPose, player); - } - else if (player != null) - { - writeItem.Write(player.Address); - UpdateActors(player); - } + writeItem.Write(gPose.Address); + UpdateActors(gPose, player); + } + else if (player != null) + { + writeItem.Write(player.Address); + UpdateActors(player); } } @@ -93,61 +78,51 @@ namespace Glamourer Penumbra!.ChangedItemClicked -= PenumbraRightClick; } - private void SetPlugins(DalamudPluginInterface pi) + internal static bool GetPenumbra() { - var pluginManager = _dalamud?.GetType() - ?.GetProperty("PluginManager", BindingFlags.Instance | BindingFlags.NonPublic) - ?.GetValue(_dalamud); + try + { + var subscriber = Dalamud.PluginInterface.GetIpcSubscriber("Penumbra.Api"); + var penumbraApiBase = subscriber.InvokeFunc(); + if (penumbraApiBase.ApiVersion != RequiredPenumbraShareVersion) + { + PluginLog.Debug("Could not get Penumbra because API version {penumbraApiBase.ApiVersion} does not equal the required version {RequiredPenumbraShareVersion}."); + Penumbra = null; + return false; + } - if (pluginManager == null) - throw new Exception("Could not obtain plugin manager."); - - var pluginsList = - (List<(IDalamudPlugin Plugin, PluginDefinition Definition, DalamudPluginInterface PluginInterface, bool IsRaw)>?) pluginManager - ?.GetType() - ?.GetProperty("Plugins", BindingFlags.Instance | BindingFlags.Public) - ?.GetValue(pluginManager); - - _plugins = pluginsList ?? throw new Exception("Could not obtain Dalamud."); - } - - public bool GetPenumbra() - { - if (Penumbra?.Valid ?? false) - return true; - - var plugin = _plugins.Find(p - => p.Definition.InternalName == "Penumbra" - && string.Compare(p.Definition.AssemblyVersion, "0.4.0.3", StringComparison.Ordinal) >= 0).Plugin; - - var penumbra = (IPenumbraApiBase?) plugin?.GetType().GetProperty("Api", BindingFlags.Instance | BindingFlags.Public) - ?.GetValue(plugin); - if (penumbra != null && penumbra.Valid && penumbra.ApiVersion >= RequiredPenumbraShareVersion) - Penumbra = (IPenumbraApi) penumbra!; - else + Penumbra = penumbraApiBase as IPenumbraApi; + } + catch (IpcNotReadyError ipc) + { Penumbra = null; + PluginLog.Debug($"Could not get Penumbra because IPC not registered:\n{ipc}"); + } + catch (Exception e) + { + Penumbra = null; + PluginLog.Debug($"Could not get Penumbra for unknown reason:\n{e}"); + } return Penumbra != null; } - public void Initialize(DalamudPluginInterface pluginInterface) + public Glamourer(DalamudPluginInterface pluginInterface) { - Version = Assembly.GetExecutingAssembly()?.GetName().Version.ToString() ?? ""; - PluginInterface = pluginInterface; - Config = GlamourerConfig.Create(); - Customization = CustomizationManager.Create(PluginInterface); - SetDalamud(PluginInterface); - SetPlugins(PluginInterface); - Designs = new DesignManager(PluginInterface); + Dalamud.Initialize(pluginInterface); + Version = Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? ""; + Config = GlamourerConfig.Load(); + Customization = CustomizationManager.Create(Dalamud.PluginInterface, Dalamud.GameData, Dalamud.ClientState.ClientLanguage); + Designs = new DesignManager(); if (GetPenumbra() && Config.AttachToPenumbra) RegisterFunctions(); - PlayerWatcher = PlayerWatchFactory.Create(PluginInterface); + PlayerWatcher = PlayerWatchFactory.Create(Dalamud.Framework, Dalamud.ClientState, Dalamud.Objects); - PluginInterface.CommandManager.AddHandler("/glamourer", new CommandInfo(OnGlamourer) + Dalamud.Commands.AddHandler("/glamourer", new CommandInfo(OnGlamourer) { HelpMessage = "Open or close the Glamourer window.", }); - PluginInterface.CommandManager.AddHandler("/glamour", new CommandInfo(OnGlamour) + Dalamud.Commands.AddHandler("/glamour", new CommandInfo(OnGlamour) { HelpMessage = $"Use Glamourer Functions: {HelpString}", }); @@ -156,48 +131,48 @@ namespace Glamourer } public void OnGlamourer(string command, string arguments) - => _interface?.ToggleVisibility(null!, null!); + => _interface.ToggleVisibility(); - private Actor? GetActor(string name) + private static GameObject? GetActor(string name) { var lowerName = name.ToLowerInvariant(); return lowerName switch { "" => null, - "" => PluginInterface.ClientState.Actors[Interface.GPoseActorId] ?? PluginInterface.ClientState.LocalPlayer, - "self" => PluginInterface.ClientState.Actors[Interface.GPoseActorId] ?? PluginInterface.ClientState.LocalPlayer, - "" => PluginInterface.ClientState.Targets.CurrentTarget, - "target" => PluginInterface.ClientState.Targets.CurrentTarget, - "" => PluginInterface.ClientState.Targets.FocusTarget, - "focus" => PluginInterface.ClientState.Targets.FocusTarget, - "" => PluginInterface.ClientState.Targets.MouseOverTarget, - "mouseover" => PluginInterface.ClientState.Targets.MouseOverTarget, - _ => PluginInterface.ClientState.Actors.LastOrDefault( - a => string.Equals(a.Name, lowerName, StringComparison.InvariantCultureIgnoreCase)), + "" => Dalamud.Objects[Interface.GPoseActorId] ?? Dalamud.ClientState.LocalPlayer, + "self" => Dalamud.Objects[Interface.GPoseActorId] ?? Dalamud.ClientState.LocalPlayer, + "" => Dalamud.Targets.Target, + "target" => Dalamud.Targets.Target, + "" => Dalamud.Targets.FocusTarget, + "focus" => Dalamud.Targets.FocusTarget, + "" => Dalamud.Targets.MouseOverTarget, + "mouseover" => Dalamud.Targets.MouseOverTarget, + _ => Dalamud.Objects.LastOrDefault( + a => string.Equals(a.Name.ToString(), lowerName, StringComparison.InvariantCultureIgnoreCase)), }; } - public void CopyToClipboard(Actor actor) + public void CopyToClipboard(Character actor) { var save = new CharacterSave(); save.LoadActor(actor); - Clipboard.SetText(save.ToBase64()); + ImGui.SetClipboardText(save.ToBase64()); } - public void ApplyCommand(Actor actor, string target) + public void ApplyCommand(Character actor, string target) { CharacterSave? save = null; if (target.ToLowerInvariant() == "clipboard") try { - save = CharacterSave.FromString(Clipboard.GetText()); + save = CharacterSave.FromString(ImGui.GetClipboardText()); } catch (Exception) { - PluginInterface.Framework.Gui.Chat.PrintError("Clipboard does not contain a valid customization string."); + Dalamud.Chat.PrintError("Clipboard does not contain a valid customization string."); } else if (!Designs.FileSystem.Find(target, out var child) || child is not Design d) - PluginInterface.Framework.Gui.Chat.PrintError("The given path to a saved design does not exist or does not point to a design."); + Dalamud.Chat.PrintError("The given path to a saved design does not exist or does not point to a design."); else save = d.Data; @@ -205,7 +180,7 @@ namespace Glamourer UpdateActors(actor); } - public void SaveCommand(Actor actor, string path) + public void SaveCommand(Character actor, string path) { var save = new CharacterSave(); save.LoadActor(actor); @@ -219,8 +194,8 @@ namespace Glamourer } catch (Exception e) { - PluginInterface.Framework.Gui.Chat.PrintError("Could not save file:"); - PluginInterface.Framework.Gui.Chat.PrintError($" {e.Message}"); + Dalamud.Chat.PrintError("Could not save file:"); + Dalamud.Chat.PrintError($" {e.Message}"); } } @@ -228,8 +203,8 @@ namespace Glamourer { static void PrintHelp() { - PluginInterface.Framework.Gui.Chat.Print("Usage:"); - PluginInterface.Framework.Gui.Chat.Print($" {HelpString}"); + Dalamud.Chat.Print("Usage:"); + Dalamud.Chat.Print($" {HelpString}"); } arguments = arguments.Trim(); @@ -250,10 +225,10 @@ namespace Glamourer return; } - var actor = GetActor(split[1]); + var actor = GetActor(split[1]) as Character; if (actor == null) { - PluginInterface.Framework.Gui.Chat.Print($"Could not find actor for {split[1]}."); + Dalamud.Chat.Print($"Could not find actor for {split[1]} or it was not a Character."); return; } @@ -266,7 +241,7 @@ namespace Glamourer { if (split.Length < 3) { - PluginInterface.Framework.Gui.Chat.Print("Applying requires a name for the save to be applied or 'clipboard'."); + Dalamud.Chat.Print("Applying requires a name for the save to be applied or 'clipboard'."); return; } @@ -278,7 +253,7 @@ namespace Glamourer { if (split.Length < 3) { - PluginInterface.Framework.Gui.Chat.Print("Saving requires a name for the save."); + Dalamud.Chat.Print("Saving requires a name for the save."); return; } @@ -296,25 +271,24 @@ namespace Glamourer PlayerWatcher?.Dispose(); UnregisterFunctions(); _interface?.Dispose(); - PluginInterface.CommandManager.RemoveHandler("/glamour"); - PluginInterface.CommandManager.RemoveHandler("/glamourer"); - PluginInterface.Dispose(); + Dalamud.Commands.RemoveHandler("/glamour"); + Dalamud.Commands.RemoveHandler("/glamourer"); } // Update actors without triggering PlayerWatcher Events, // then manually redraw using Penumbra. - public void UpdateActors(Actor actor, Actor? gPoseOriginalActor = null) + public void UpdateActors(Character actor, Character? gPoseOriginalActor = null) { var newEquip = PlayerWatcher.UpdateActorWithoutEvent(actor); - Penumbra?.RedrawActor(actor, RedrawType.WithSettings); + Penumbra?.RedrawObject(actor, RedrawType.WithSettings); // Special case for carrying over changes to the gPose actor to the regular player actor, too. - if (gPoseOriginalActor != null) - { - newEquip.Write(gPoseOriginalActor.Address); - PlayerWatcher.UpdateActorWithoutEvent(gPoseOriginalActor); - Penumbra?.RedrawActor(gPoseOriginalActor, RedrawType.AfterGPoseWithSettings); - } + if (gPoseOriginalActor == null) + return; + + newEquip.Write(gPoseOriginalActor.Address); + PlayerWatcher.UpdateActorWithoutEvent(gPoseOriginalActor); + Penumbra?.RedrawObject(gPoseOriginalActor, RedrawType.AfterGPoseWithSettings); } } } diff --git a/repo.json b/repo.json index 0b33e73..872172d 100644 --- a/repo.json +++ b/repo.json @@ -4,11 +4,11 @@ "Name": "Glamourer", "Description": "Adds functionality to change appearance of actors. Requires Penumbra to be installed and activated to work.", "InternalName": "Glamourer", - "AssemblyVersion": "0.0.3.0", - "TestingAssemblyVersion": "0.0.3.0", + "AssemblyVersion": "0.0.4.0", + "TestingAssemblyVersion": "0.0.4.0", "RepoUrl": "https://github.com/Ottermandias/Glamourer", "ApplicableVersion": "any", - "DalamudApiLevel": 3, + "DalamudApiLevel": 4, "IsHide": "False", "IsTestingExclusive": "false", "DownloadCount": 1,