Allow for SortaKinda imports
This commit is contained in:
@@ -106,6 +106,12 @@ public class AddonInventoryWindow : NativeAddon
|
|||||||
base.OnUpdate(addon);
|
base.OnUpdate(addon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ManualRefresh()
|
||||||
|
{
|
||||||
|
InventoryState.RefreshFromGame();
|
||||||
|
RefreshCategoriesCore(true);
|
||||||
|
}
|
||||||
|
|
||||||
private void OnInventoryUpdate(AddonEvent type, AddonArgs args)
|
private void OnInventoryUpdate(AddonEvent type, AddonArgs args)
|
||||||
{
|
{
|
||||||
InventoryState.RefreshFromGame();
|
InventoryState.RefreshFromGame();
|
||||||
|
|||||||
@@ -0,0 +1,176 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.Json;
|
||||||
|
using AetherBags.Configuration;
|
||||||
|
using AetherBags.Configuration.Import;
|
||||||
|
|
||||||
|
namespace AetherBags.Helpers.Import;
|
||||||
|
|
||||||
|
public static class SortaKindaImportExport
|
||||||
|
{
|
||||||
|
private static readonly JsonSerializerOptions ExternalJsonOptions = new()
|
||||||
|
{
|
||||||
|
PropertyNameCaseInsensitive = true,
|
||||||
|
ReadCommentHandling = JsonCommentHandling.Skip,
|
||||||
|
AllowTrailingCommas = true,
|
||||||
|
WriteIndented = true,
|
||||||
|
IncludeFields = true
|
||||||
|
};
|
||||||
|
|
||||||
|
public static bool TryImportFromClipboard(
|
||||||
|
SystemConfiguration targetConfig,
|
||||||
|
bool replaceExisting,
|
||||||
|
out string error)
|
||||||
|
{
|
||||||
|
error = string.Empty;
|
||||||
|
string clipboard;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clipboard = Dalamud.Bindings.ImGui.ImGui.GetClipboardText();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
error = $"Failed to read clipboard: {ex.Message}";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TryImportFromJson(clipboard, targetConfig, replaceExisting, out error);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryImportFromJson(
|
||||||
|
string input,
|
||||||
|
SystemConfiguration targetConfig,
|
||||||
|
bool replaceExisting,
|
||||||
|
out string error)
|
||||||
|
{
|
||||||
|
error = string.Empty;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(input))
|
||||||
|
{
|
||||||
|
error = "Input was empty.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var external = Util.DeserializeCompressed<SortaKindaCategory[]>(input.Trim(), ExternalJsonOptions);
|
||||||
|
|
||||||
|
if (external is null)
|
||||||
|
{
|
||||||
|
error = "Failed to parse SortaKinda input.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var mapped = external
|
||||||
|
.Select(MapToUserCategory)
|
||||||
|
.OrderBy(c => c.Order)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var dest = targetConfig.Categories.UserCategories;
|
||||||
|
|
||||||
|
if (replaceExisting)
|
||||||
|
{
|
||||||
|
dest.Clear();
|
||||||
|
dest.AddRange(mapped);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var byId = dest
|
||||||
|
.Where(c => !string.IsNullOrWhiteSpace(c.Id))
|
||||||
|
.ToDictionary(c => c.Id, StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
foreach (var incoming in mapped)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(incoming.Id) && byId.TryGetValue(incoming.Id, out var existing))
|
||||||
|
{
|
||||||
|
existing.Name = incoming.Name;
|
||||||
|
existing.Description = incoming.Description;
|
||||||
|
existing.Order = incoming.Order;
|
||||||
|
existing.Priority = incoming.Priority;
|
||||||
|
existing.Color = incoming.Color;
|
||||||
|
existing.Rules = incoming.Rules;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dest.Add(incoming);
|
||||||
|
if (!string.IsNullOrWhiteSpace(incoming.Id))
|
||||||
|
byId[incoming.Id] = incoming;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
targetConfig.Categories.UserCategoriesEnabled = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ExportToJson(SystemConfiguration sourceConfig)
|
||||||
|
{
|
||||||
|
var exported = sourceConfig.Categories.UserCategories
|
||||||
|
.OrderBy(c => c.Order)
|
||||||
|
.Select(MapToExternal)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
return Util.SerializeCompressed(exported, ExternalJsonOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ExportToClipboard(SystemConfiguration sourceConfig)
|
||||||
|
=> Dalamud.Bindings.ImGui.ImGui.SetClipboardText(ExportToJson(sourceConfig));
|
||||||
|
|
||||||
|
private static UserCategoryDefinition MapToUserCategory(SortaKindaCategory external)
|
||||||
|
=> new()
|
||||||
|
{
|
||||||
|
Id = string.IsNullOrWhiteSpace(external.Id) ? Guid.NewGuid().ToString("N") : external.Id,
|
||||||
|
Name = external.Name,
|
||||||
|
Description = string.Empty,
|
||||||
|
Order = external.Index,
|
||||||
|
Priority = 100,
|
||||||
|
Color = external.Color,
|
||||||
|
Rules = new CategoryRuleSet
|
||||||
|
{
|
||||||
|
AllowedItemIds = new List<uint>(),
|
||||||
|
AllowedItemNamePatterns = external.AllowedItemNames?.ToList() ?? new List<string>(),
|
||||||
|
AllowedUiCategoryIds = external.AllowedItemTypes?.ToList() ?? new List<uint>(),
|
||||||
|
AllowedRarities = external.AllowedItemRarities?.ToList() ?? new List<int>(),
|
||||||
|
ItemLevel = new RangeFilter<int>
|
||||||
|
{
|
||||||
|
Enabled = external.ItemLevelFilter?.Enable ?? false,
|
||||||
|
Min = external.ItemLevelFilter?.MinValue ?? 0,
|
||||||
|
Max = external.ItemLevelFilter?.MaxValue ?? 2000,
|
||||||
|
},
|
||||||
|
VendorPrice = new RangeFilter<uint>
|
||||||
|
{
|
||||||
|
Enabled = external.VendorPriceFilter?.Enable ?? false,
|
||||||
|
Min = external.VendorPriceFilter?.MinValue ?? 0u,
|
||||||
|
Max = external.VendorPriceFilter?.MaxValue ?? 9_999_999u,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private static SortaKindaCategory MapToExternal(UserCategoryDefinition internalCat)
|
||||||
|
=> new()
|
||||||
|
{
|
||||||
|
Color = internalCat.Color,
|
||||||
|
Id = internalCat.Id,
|
||||||
|
Name = internalCat.Name,
|
||||||
|
Index = internalCat.Order,
|
||||||
|
AllowedItemNames = internalCat.Rules.AllowedItemNamePatterns?.ToList() ?? new List<string>(),
|
||||||
|
AllowedItemTypes = internalCat.Rules.AllowedUiCategoryIds?.ToList() ?? new List<uint>(),
|
||||||
|
AllowedItemRarities = internalCat.Rules.AllowedRarities?.ToList() ?? new List<int>(),
|
||||||
|
ItemLevelFilter = new ExternalRangeFilterDto<int>
|
||||||
|
{
|
||||||
|
Enable = internalCat.Rules.ItemLevel.Enabled,
|
||||||
|
Label = "Item Level Filter",
|
||||||
|
MinValue = internalCat.Rules.ItemLevel.Min,
|
||||||
|
MaxValue = internalCat.Rules.ItemLevel.Max
|
||||||
|
},
|
||||||
|
VendorPriceFilter = new ExternalRangeFilterDto<uint>
|
||||||
|
{
|
||||||
|
Enable = internalCat.Rules.VendorPrice.Enabled,
|
||||||
|
Label = "Vendor Price Filter",
|
||||||
|
MinValue = internalCat.Rules.VendorPrice.Min,
|
||||||
|
MaxValue = internalCat.Rules.VendorPrice.Max
|
||||||
|
},
|
||||||
|
Direction = 0,
|
||||||
|
FillMode = 0,
|
||||||
|
SortMode = 0
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using AetherBags.Configuration;
|
using AetherBags.Configuration;
|
||||||
|
using AetherBags.Helpers.Import;
|
||||||
using Dalamud.Bindings.ImGui;
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Game.ClientState.Keys;
|
using Dalamud.Game.ClientState.Keys;
|
||||||
using Dalamud.Interface.ImGuiNotification;
|
using Dalamud.Interface.ImGuiNotification;
|
||||||
@@ -62,4 +63,35 @@ public abstract class ImportExportResetHelper {
|
|||||||
);
|
);
|
||||||
Services.Logger.Info("Configuration reset to default.");
|
Services.Logger.Info("Configuration reset to default.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void TryImportSortaKindaFromClipboard(bool replaceExisting)
|
||||||
|
{
|
||||||
|
//if (!Services.KeyState[VirtualKey.SHIFT])
|
||||||
|
// return;
|
||||||
|
|
||||||
|
var notification = new Notification { Content = "SortaKinda categories imported.", Type = NotificationType.Success };
|
||||||
|
|
||||||
|
if (!SortaKindaImportExport.TryImportFromClipboard(System.Config, replaceExisting, out var error))
|
||||||
|
{
|
||||||
|
notification.Content = error;
|
||||||
|
notification.Type = NotificationType.Error;
|
||||||
|
Services.Logger.Warning(error);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Util.SaveConfig(System.Config);
|
||||||
|
Services.Logger.Info("SortaKinda categories imported from clipboard.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Services.NotificationManager.AddNotification(notification);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void TryExportSortaKindaToClipboard()
|
||||||
|
{
|
||||||
|
SortaKindaImportExport.ExportToClipboard(System.Config);
|
||||||
|
Services.NotificationManager.AddNotification(
|
||||||
|
new Notification { Content = "SortaKinda JSON exported to clipboard.", Type = NotificationType.Success }
|
||||||
|
);
|
||||||
|
Services.Logger.Info("SortaKinda JSON exported to clipboard.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,25 +53,31 @@ public static class Util
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string SerializeConfig(SystemConfiguration config)
|
public static string SerializeCompressed<T>(T value, JsonSerializerOptions? options = null)
|
||||||
{
|
{
|
||||||
var json = JsonSerializer.Serialize(config, ConfigJsonOptions);
|
var json = JsonSerializer.Serialize(value, options ?? ConfigJsonOptions);
|
||||||
return CompressToBase64(json);
|
return CompressToBase64(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SystemConfiguration? DeserializeConfig(string input)
|
public static T? DeserializeCompressed<T>(string input, JsonSerializerOptions? options = null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var json = DecompressFromBase64(input);
|
var json = DecompressFromBase64(input);
|
||||||
return JsonSerializer.Deserialize<SystemConfiguration>(json, ConfigJsonOptions);
|
return JsonSerializer.Deserialize<T>(json, options ?? ConfigJsonOptions);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
return null;
|
return default;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string SerializeConfig(SystemConfiguration config)
|
||||||
|
=> SerializeCompressed(config, ConfigJsonOptions);
|
||||||
|
|
||||||
|
public static SystemConfiguration? DeserializeConfig(string input)
|
||||||
|
=> DeserializeCompressed<SystemConfiguration>(input, ConfigJsonOptions);
|
||||||
|
|
||||||
public static void SaveConfig(SystemConfiguration config)
|
public static void SaveConfig(SystemConfiguration config)
|
||||||
{
|
{
|
||||||
FileInfo file = FileHelpers.GetFileInfo(SystemConfiguration.FileName);
|
FileInfo file = FileHelpers.GetFileInfo(SystemConfiguration.FileName);
|
||||||
|
|||||||
@@ -73,6 +73,12 @@ public class Plugin : IDalamudPlugin
|
|||||||
System.AddonInventoryWindow.Toggle();
|
System.AddonInventoryWindow.Toggle();
|
||||||
if(args == "config")
|
if(args == "config")
|
||||||
System.AddonInventoryWindow.Toggle();
|
System.AddonInventoryWindow.Toggle();
|
||||||
|
if (args == "import-sk")
|
||||||
|
{
|
||||||
|
// Manually import from SortaKinda for testing until we have a proper config window
|
||||||
|
ImportExportResetHelper.TryImportSortaKindaFromClipboard(true);
|
||||||
|
System.AddonInventoryWindow.ManualRefresh();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user