More import changes and more options
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
using KamiToolKit.Classes;
|
using KamiToolKit.Classes;
|
||||||
|
|
||||||
namespace AetherBags.Configuration;
|
namespace AetherBags.Configuration;
|
||||||
@@ -33,8 +34,14 @@ public class CategoryRuleSet
|
|||||||
public List<uint> AllowedUiCategoryIds { get; set; } = new();
|
public List<uint> AllowedUiCategoryIds { get; set; } = new();
|
||||||
public List<int> AllowedRarities { get; set; } = new();
|
public List<int> AllowedRarities { get; set; } = new();
|
||||||
|
|
||||||
|
public RangeFilter<int> Level { get; set; } = new() { Enabled = false, Min = 0, Max = 200 };
|
||||||
public RangeFilter<int> ItemLevel { get; set; } = new() { Enabled = false, Min = 0, Max = 2000 };
|
public RangeFilter<int> ItemLevel { get; set; } = new() { Enabled = false, Min = 0, Max = 2000 };
|
||||||
public RangeFilter<uint> VendorPrice { get; set; } = new() { Enabled = false, Min = 0, Max = 9_999_999 };
|
public RangeFilter<uint> VendorPrice { get; set; } = new() { Enabled = false, Min = 0, Max = 9_999_999 };
|
||||||
|
public StateFilter Untradable { get; set; } = new();
|
||||||
|
public StateFilter Unique { get; set; } = new();
|
||||||
|
public StateFilter Collectable { get; set; } = new();
|
||||||
|
public StateFilter Dyeable { get; set; } = new();
|
||||||
|
public StateFilter Repairable { get; set; } = new();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class RangeFilter<T> where T : struct, IComparable<T>
|
public class RangeFilter<T> where T : struct, IComparable<T>
|
||||||
@@ -42,4 +49,24 @@ public class RangeFilter<T> where T : struct, IComparable<T>
|
|||||||
public bool Enabled { get; set; }
|
public bool Enabled { get; set; }
|
||||||
public T Min { get; set; }
|
public T Min { get; set; }
|
||||||
public T Max { get; set; }
|
public T Max { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class StateFilter
|
||||||
|
{
|
||||||
|
public int State { get; set; } = 0;
|
||||||
|
public int Filter { get; set; } = 0;
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public ToggleFilterState ToggleState
|
||||||
|
{
|
||||||
|
get => Enum.IsDefined(typeof(ToggleFilterState), State) ? (ToggleFilterState)State : ToggleFilterState.Ignored;
|
||||||
|
set => State = (int)value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ToggleFilterState
|
||||||
|
{
|
||||||
|
Ignored = 0,
|
||||||
|
Allow = 1,
|
||||||
|
Disallow = 2,
|
||||||
}
|
}
|
||||||
@@ -3,13 +3,12 @@ using System.Numerics;
|
|||||||
|
|
||||||
namespace AetherBags.Configuration.Import;
|
namespace AetherBags.Configuration.Import;
|
||||||
|
|
||||||
// Possible Mapping:
|
public sealed class SortaKindaImportFile
|
||||||
// Index -> Order
|
{
|
||||||
// Color/Id/Name
|
public List<SortaKindaCategory> Rules { get; set; } = new();
|
||||||
// AllowedItemNames -> AllowedItemNamePatterns
|
|
||||||
// AllowedItemTypes -> AllowedUiCategoryIds
|
public object? MainInventory { get; set; }
|
||||||
// AllowedItemRarities -> AllowedRarities
|
}
|
||||||
// ItemLevelFilter / VendorPriceFilter -> RangeFilter
|
|
||||||
|
|
||||||
public sealed class SortaKindaCategory
|
public sealed class SortaKindaCategory
|
||||||
{
|
{
|
||||||
@@ -19,15 +18,38 @@ public sealed class SortaKindaCategory
|
|||||||
public int Index { get; set; }
|
public int Index { get; set; }
|
||||||
|
|
||||||
public List<string> AllowedItemNames { get; set; } = new();
|
public List<string> AllowedItemNames { get; set; } = new();
|
||||||
|
|
||||||
|
public List<AllowedNameRegexDto> AllowedNameRegexes { get; set; } = new();
|
||||||
|
|
||||||
|
// Common
|
||||||
public List<uint> AllowedItemTypes { get; set; } = new();
|
public List<uint> AllowedItemTypes { get; set; } = new();
|
||||||
public List<int> AllowedItemRarities { get; set; } = new();
|
public List<int> AllowedItemRarities { get; set; } = new();
|
||||||
|
|
||||||
|
public ExternalRangeFilterDto<int>? LevelFilter { get; set; }
|
||||||
public ExternalRangeFilterDto<int> ItemLevelFilter { get; set; } = new();
|
public ExternalRangeFilterDto<int> ItemLevelFilter { get; set; } = new();
|
||||||
public ExternalRangeFilterDto<uint> VendorPriceFilter { get; set; } = new();
|
public ExternalRangeFilterDto<uint> VendorPriceFilter { get; set; } = new();
|
||||||
|
|
||||||
|
public ExternalStateFilterDto? UntradableFilter { get; set; }
|
||||||
|
public ExternalStateFilterDto? UniqueFilter { get; set; }
|
||||||
|
public ExternalStateFilterDto? CollectableFilter { get; set; }
|
||||||
|
public ExternalStateFilterDto? DyeableFilter { get; set; }
|
||||||
|
public ExternalStateFilterDto? RepairableFilter { get; set; }
|
||||||
|
|
||||||
public int Direction { get; set; }
|
public int Direction { get; set; }
|
||||||
public int FillMode { get; set; }
|
public int FillMode { get; set; }
|
||||||
public int SortMode { get; set; }
|
public int SortMode { get; set; }
|
||||||
|
public bool InclusiveAnd { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class AllowedNameRegexDto
|
||||||
|
{
|
||||||
|
public string Text { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class ExternalStateFilterDto
|
||||||
|
{
|
||||||
|
public int State { get; set; }
|
||||||
|
public int Filter { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class ExternalRangeFilterDto<T> where T : struct
|
public sealed class ExternalRangeFilterDto<T> where T : struct
|
||||||
|
|||||||
@@ -52,7 +52,19 @@ public static class SortaKindaImportExport
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var external = Util.DeserializeCompressed<SortaKindaCategory[]>(input.Trim(), ExternalJsonOptions);
|
string trimmed = input.Trim();
|
||||||
|
|
||||||
|
SortaKindaCategory[]? external = null;
|
||||||
|
|
||||||
|
SortaKindaImportFile? file = Util.DeserializeCompressed<SortaKindaImportFile>(trimmed, ExternalJsonOptions);
|
||||||
|
if (file?.Rules is { Count: > 0 })
|
||||||
|
{
|
||||||
|
external = file.Rules.ToArray();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
external = Util.DeserializeCompressed<SortaKindaCategory[]>(trimmed, ExternalJsonOptions);
|
||||||
|
}
|
||||||
|
|
||||||
if (external is null)
|
if (external is null)
|
||||||
{
|
{
|
||||||
@@ -104,10 +116,15 @@ public static class SortaKindaImportExport
|
|||||||
|
|
||||||
public static string ExportToJson(SystemConfiguration sourceConfig)
|
public static string ExportToJson(SystemConfiguration sourceConfig)
|
||||||
{
|
{
|
||||||
var exported = sourceConfig.Categories.UserCategories
|
var exported = new SortaKindaImportFile
|
||||||
.OrderBy(c => c.Order)
|
{
|
||||||
.Select(MapToExternal)
|
Rules = sourceConfig.Categories.UserCategories
|
||||||
.ToArray();
|
.OrderBy(c => c.Priority)
|
||||||
|
.Select(MapToExternal)
|
||||||
|
.ToList(),
|
||||||
|
|
||||||
|
// MainInventory = new { InventoryConfigs = new[] { new { } } }
|
||||||
|
};
|
||||||
|
|
||||||
return Util.SerializeCompressed(exported, ExternalJsonOptions);
|
return Util.SerializeCompressed(exported, ExternalJsonOptions);
|
||||||
}
|
}
|
||||||
@@ -122,14 +139,28 @@ public static class SortaKindaImportExport
|
|||||||
Name = external.Name,
|
Name = external.Name,
|
||||||
Description = string.Empty,
|
Description = string.Empty,
|
||||||
Order = external.Index,
|
Order = external.Index,
|
||||||
Priority = 100,
|
Priority = external.Index,
|
||||||
Color = external.Color,
|
Color = external.Color,
|
||||||
Rules = new CategoryRuleSet
|
Rules = new CategoryRuleSet
|
||||||
{
|
{
|
||||||
AllowedItemIds = new List<uint>(),
|
AllowedItemIds = new List<uint>(),
|
||||||
AllowedItemNamePatterns = external.AllowedItemNames?.ToList() ?? new List<string>(),
|
|
||||||
|
AllowedItemNamePatterns =
|
||||||
|
(external.AllowedItemNames ?? new List<string>())
|
||||||
|
.Concat((external.AllowedNameRegexes ?? new List<AllowedNameRegexDto>())
|
||||||
|
.Select(r => r.Text)
|
||||||
|
.Where(t => !string.IsNullOrWhiteSpace(t)))
|
||||||
|
.ToList(),
|
||||||
|
|
||||||
AllowedUiCategoryIds = external.AllowedItemTypes?.ToList() ?? new List<uint>(),
|
AllowedUiCategoryIds = external.AllowedItemTypes?.ToList() ?? new List<uint>(),
|
||||||
AllowedRarities = external.AllowedItemRarities?.ToList() ?? new List<int>(),
|
AllowedRarities = external.AllowedItemRarities?.ToList() ?? new List<int>(),
|
||||||
|
|
||||||
|
Level = new RangeFilter<int>
|
||||||
|
{
|
||||||
|
Enabled = external.LevelFilter?.Enable ?? false,
|
||||||
|
Min = external.LevelFilter?.MinValue ?? 0,
|
||||||
|
Max = external.LevelFilter?.MaxValue ?? 200,
|
||||||
|
},
|
||||||
ItemLevel = new RangeFilter<int>
|
ItemLevel = new RangeFilter<int>
|
||||||
{
|
{
|
||||||
Enabled = external.ItemLevelFilter?.Enable ?? false,
|
Enabled = external.ItemLevelFilter?.Enable ?? false,
|
||||||
@@ -141,7 +172,13 @@ public static class SortaKindaImportExport
|
|||||||
Enabled = external.VendorPriceFilter?.Enable ?? false,
|
Enabled = external.VendorPriceFilter?.Enable ?? false,
|
||||||
Min = external.VendorPriceFilter?.MinValue ?? 0u,
|
Min = external.VendorPriceFilter?.MinValue ?? 0u,
|
||||||
Max = external.VendorPriceFilter?.MaxValue ?? 9_999_999u,
|
Max = external.VendorPriceFilter?.MaxValue ?? 9_999_999u,
|
||||||
}
|
},
|
||||||
|
|
||||||
|
Untradable = new StateFilter { State = external.UntradableFilter?.State ?? 0, Filter = external.UntradableFilter?.Filter ?? 0 },
|
||||||
|
Unique = new StateFilter { State = external.UniqueFilter?.State ?? 0, Filter = external.UniqueFilter?.Filter ?? 0 },
|
||||||
|
Collectable= new StateFilter { State = external.CollectableFilter?.State ?? 0,Filter = external.CollectableFilter?.Filter ?? 0 },
|
||||||
|
Dyeable = new StateFilter { State = external.DyeableFilter?.State ?? 0, Filter = external.DyeableFilter?.Filter ?? 0 },
|
||||||
|
Repairable = new StateFilter { State = external.RepairableFilter?.State ?? 0, Filter = external.RepairableFilter?.Filter ?? 0 },
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -151,10 +188,26 @@ public static class SortaKindaImportExport
|
|||||||
Color = internalCat.Color,
|
Color = internalCat.Color,
|
||||||
Id = internalCat.Id,
|
Id = internalCat.Id,
|
||||||
Name = internalCat.Name,
|
Name = internalCat.Name,
|
||||||
Index = internalCat.Order,
|
Index = internalCat.Priority,
|
||||||
AllowedItemNames = internalCat.Rules.AllowedItemNamePatterns?.ToList() ?? new List<string>(),
|
|
||||||
|
AllowedItemNames = new List<string>(),
|
||||||
|
AllowedNameRegexes =
|
||||||
|
(internalCat.Rules.AllowedItemNamePatterns ?? new List<string>())
|
||||||
|
.Where(s => !string.IsNullOrWhiteSpace(s))
|
||||||
|
.Select(s => new AllowedNameRegexDto { Text = s })
|
||||||
|
.ToList(),
|
||||||
|
|
||||||
AllowedItemTypes = internalCat.Rules.AllowedUiCategoryIds?.ToList() ?? new List<uint>(),
|
AllowedItemTypes = internalCat.Rules.AllowedUiCategoryIds?.ToList() ?? new List<uint>(),
|
||||||
AllowedItemRarities = internalCat.Rules.AllowedRarities?.ToList() ?? new List<int>(),
|
AllowedItemRarities = internalCat.Rules.AllowedRarities?.ToList() ?? new List<int>(),
|
||||||
|
|
||||||
|
LevelFilter = new ExternalRangeFilterDto<int>
|
||||||
|
{
|
||||||
|
Enable = internalCat.Rules.Level.Enabled,
|
||||||
|
Label = "Level Filter",
|
||||||
|
MinValue = internalCat.Rules.Level.Min,
|
||||||
|
MaxValue = internalCat.Rules.Level.Max
|
||||||
|
},
|
||||||
|
|
||||||
ItemLevelFilter = new ExternalRangeFilterDto<int>
|
ItemLevelFilter = new ExternalRangeFilterDto<int>
|
||||||
{
|
{
|
||||||
Enable = internalCat.Rules.ItemLevel.Enabled,
|
Enable = internalCat.Rules.ItemLevel.Enabled,
|
||||||
@@ -169,8 +222,16 @@ public static class SortaKindaImportExport
|
|||||||
MinValue = internalCat.Rules.VendorPrice.Min,
|
MinValue = internalCat.Rules.VendorPrice.Min,
|
||||||
MaxValue = internalCat.Rules.VendorPrice.Max
|
MaxValue = internalCat.Rules.VendorPrice.Max
|
||||||
},
|
},
|
||||||
|
|
||||||
|
UntradableFilter = new ExternalStateFilterDto { State = internalCat.Rules.Untradable.State, Filter = internalCat.Rules.Untradable.Filter },
|
||||||
|
UniqueFilter = new ExternalStateFilterDto { State = internalCat.Rules.Unique.State, Filter = internalCat.Rules.Unique.Filter },
|
||||||
|
CollectableFilter= new ExternalStateFilterDto { State = internalCat.Rules.Collectable.State,Filter = internalCat.Rules.Collectable.Filter },
|
||||||
|
DyeableFilter = new ExternalStateFilterDto { State = internalCat.Rules.Dyeable.State, Filter = internalCat.Rules.Dyeable.Filter },
|
||||||
|
RepairableFilter = new ExternalStateFilterDto { State = internalCat.Rules.Repairable.State, Filter = internalCat.Rules.Repairable.Filter },
|
||||||
|
|
||||||
Direction = 0,
|
Direction = 0,
|
||||||
FillMode = 0,
|
FillMode = 0,
|
||||||
SortMode = 0
|
SortMode = 0,
|
||||||
|
InclusiveAnd = false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -56,6 +56,8 @@ public static unsafe class InventoryState
|
|||||||
|
|
||||||
private static readonly List<CategorizedInventory> FilteredCategories = new(capacity: 256);
|
private static readonly List<CategorizedInventory> FilteredCategories = new(capacity: 256);
|
||||||
|
|
||||||
|
private static readonly List<UserCategoryDefinition> UserCategoriesSortedScratch = new(capacity: 64);
|
||||||
|
|
||||||
private static readonly List<uint> RemoveKeysScratch = new(capacity: 256);
|
private static readonly List<uint> RemoveKeysScratch = new(capacity: 256);
|
||||||
|
|
||||||
private const uint UserCategoryKeyFlag = 0x8000_0000;
|
private const uint UserCategoryKeyFlag = 0x8000_0000;
|
||||||
@@ -149,9 +151,22 @@ public static unsafe class InventoryState
|
|||||||
|
|
||||||
if (userCategoriesEnabled && userCategories.Count > 0)
|
if (userCategoriesEnabled && userCategories.Count > 0)
|
||||||
{
|
{
|
||||||
for (int c = 0; c < userCategories.Count; c++)
|
UserCategoriesSortedScratch.Clear();
|
||||||
|
UserCategoriesSortedScratch.AddRange(userCategories);
|
||||||
|
UserCategoriesSortedScratch.Sort((a, b) =>
|
||||||
{
|
{
|
||||||
UserCategoryDefinition category = userCategories[c];
|
int p = b.Priority.CompareTo(a.Priority);
|
||||||
|
if (p != 0) return p;
|
||||||
|
|
||||||
|
int o = a.Order.CompareTo(b.Order);
|
||||||
|
if (o != 0) return o;
|
||||||
|
|
||||||
|
return string.Compare(a.Id, b.Id, StringComparison.OrdinalIgnoreCase);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (int c = 0; c < UserCategoriesSortedScratch.Count; c++)
|
||||||
|
{
|
||||||
|
UserCategoryDefinition category = UserCategoriesSortedScratch[c];
|
||||||
uint key = MakeUserCategoryKey(category.Order);
|
uint key = MakeUserCategoryKey(category.Order);
|
||||||
|
|
||||||
if (!BucketsByKey.TryGetValue(key, out CategoryBucket? bucket))
|
if (!BucketsByKey.TryGetValue(key, out CategoryBucket? bucket))
|
||||||
@@ -182,11 +197,15 @@ public static unsafe class InventoryState
|
|||||||
foreach (var itemKvp in ItemInfoByItemId)
|
foreach (var itemKvp in ItemInfoByItemId)
|
||||||
{
|
{
|
||||||
ItemInfo item = itemKvp.Value;
|
ItemInfo item = itemKvp.Value;
|
||||||
|
uint itemId = item.Item.ItemId;
|
||||||
|
|
||||||
|
if (claimedItemIds.Contains(itemId))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (UserCategoryMatcher.Matches(item, category))
|
if (UserCategoryMatcher.Matches(item, category))
|
||||||
{
|
{
|
||||||
bucket.Items.Add(item);
|
bucket.Items.Add(item);
|
||||||
claimedItemIds.Add(item.Item.ItemId);
|
claimedItemIds.Add(itemId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,12 @@ public sealed class ItemInfo : IEquatable<ItemInfo>
|
|||||||
|
|
||||||
public RowRef<ItemUICategory> UiCategory => Row.ItemUICategory;
|
public RowRef<ItemUICategory> UiCategory => Row.ItemUICategory;
|
||||||
|
|
||||||
|
public bool IsUntradable => Row.IsUntradable;
|
||||||
|
public bool IsUnique => Row.IsUnique;
|
||||||
|
public bool IsCollectable => Row.IsCollectable;
|
||||||
|
public bool IsDyeable => Row.DyeCount > 0;
|
||||||
|
public bool IsRepairable => Row.ItemRepair.RowId != 0;
|
||||||
|
|
||||||
private string Description => _description ??= Row.Description.ToString();
|
private string Description => _description ??= Row.Description.ToString();
|
||||||
|
|
||||||
public bool IsRegexMatch(string searchTerms)
|
public bool IsRegexMatch(string searchTerms)
|
||||||
|
|||||||
@@ -24,12 +24,21 @@ internal static class UserCategoryMatcher
|
|||||||
if (rules.AllowedRarities.Count > 0 && !rules.AllowedRarities.Contains(item.Rarity))
|
if (rules.AllowedRarities.Count > 0 && !rules.AllowedRarities.Contains(item.Rarity))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (rules.Level.Enabled && !InRange(item.Level, rules.Level.Min, rules.Level.Max))
|
||||||
|
return false;
|
||||||
|
|
||||||
if (rules.ItemLevel.Enabled && !InRange(item.ItemLevel, rules.ItemLevel.Min, rules.ItemLevel.Max))
|
if (rules.ItemLevel.Enabled && !InRange(item.ItemLevel, rules.ItemLevel.Min, rules.ItemLevel.Max))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (rules.VendorPrice.Enabled && !InRange(item.VendorPrice, rules.VendorPrice.Min, rules.VendorPrice.Max))
|
if (rules.VendorPrice.Enabled && !InRange(item.VendorPrice, rules.VendorPrice.Min, rules.VendorPrice.Max))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (!MatchesToggle(rules.Untradable, item.IsUntradable)) return false;
|
||||||
|
if (!MatchesToggle(rules.Unique, item.IsUnique)) return false;
|
||||||
|
if (!MatchesToggle(rules.Collectable, item.IsCollectable)) return false;
|
||||||
|
if (!MatchesToggle(rules.Dyeable, item.IsDyeable)) return false;
|
||||||
|
if (!MatchesToggle(rules.Repairable, item.IsRepairable)) return false;
|
||||||
|
|
||||||
if (rules.AllowedItemNamePatterns.Count > 0)
|
if (rules.AllowedItemNamePatterns.Count > 0)
|
||||||
{
|
{
|
||||||
bool any = false;
|
bool any = false;
|
||||||
@@ -63,4 +72,13 @@ internal static class UserCategoryMatcher
|
|||||||
|
|
||||||
private static bool InRange<T>(T value, T min, T max) where T : struct, IComparable<T>
|
private static bool InRange<T>(T value, T min, T max) where T : struct, IComparable<T>
|
||||||
=> value.CompareTo(min) >= 0 && value.CompareTo(max) <= 0;
|
=> value.CompareTo(min) >= 0 && value.CompareTo(max) <= 0;
|
||||||
|
|
||||||
|
private static bool MatchesToggle(StateFilter filter, bool itemHasProperty)
|
||||||
|
=> filter.ToggleState switch
|
||||||
|
{
|
||||||
|
ToggleFilterState.Ignored => true,
|
||||||
|
ToggleFilterState.Allow => itemHasProperty,
|
||||||
|
ToggleFilterState.Disallow => !itemHasProperty,
|
||||||
|
_ => true
|
||||||
|
};
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user