More import changes and more options
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using System.Text.Json.Serialization;
|
||||
using KamiToolKit.Classes;
|
||||
|
||||
namespace AetherBags.Configuration;
|
||||
@@ -33,8 +34,14 @@ public class CategoryRuleSet
|
||||
public List<uint> AllowedUiCategoryIds { 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<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>
|
||||
@@ -42,4 +49,24 @@ public class RangeFilter<T> where T : struct, IComparable<T>
|
||||
public bool Enabled { get; set; }
|
||||
public T Min { 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;
|
||||
|
||||
// Possible Mapping:
|
||||
// Index -> Order
|
||||
// Color/Id/Name
|
||||
// AllowedItemNames -> AllowedItemNamePatterns
|
||||
// AllowedItemTypes -> AllowedUiCategoryIds
|
||||
// AllowedItemRarities -> AllowedRarities
|
||||
// ItemLevelFilter / VendorPriceFilter -> RangeFilter
|
||||
public sealed class SortaKindaImportFile
|
||||
{
|
||||
public List<SortaKindaCategory> Rules { get; set; } = new();
|
||||
|
||||
public object? MainInventory { get; set; }
|
||||
}
|
||||
|
||||
public sealed class SortaKindaCategory
|
||||
{
|
||||
@@ -19,15 +18,38 @@ public sealed class SortaKindaCategory
|
||||
public int Index { get; set; }
|
||||
|
||||
public List<string> AllowedItemNames { get; set; } = new();
|
||||
|
||||
public List<AllowedNameRegexDto> AllowedNameRegexes { get; set; } = new();
|
||||
|
||||
// Common
|
||||
public List<uint> AllowedItemTypes { 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<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 FillMode { 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
|
||||
|
||||
@@ -52,7 +52,19 @@ public static class SortaKindaImportExport
|
||||
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)
|
||||
{
|
||||
@@ -104,10 +116,15 @@ public static class SortaKindaImportExport
|
||||
|
||||
public static string ExportToJson(SystemConfiguration sourceConfig)
|
||||
{
|
||||
var exported = sourceConfig.Categories.UserCategories
|
||||
.OrderBy(c => c.Order)
|
||||
.Select(MapToExternal)
|
||||
.ToArray();
|
||||
var exported = new SortaKindaImportFile
|
||||
{
|
||||
Rules = sourceConfig.Categories.UserCategories
|
||||
.OrderBy(c => c.Priority)
|
||||
.Select(MapToExternal)
|
||||
.ToList(),
|
||||
|
||||
// MainInventory = new { InventoryConfigs = new[] { new { } } }
|
||||
};
|
||||
|
||||
return Util.SerializeCompressed(exported, ExternalJsonOptions);
|
||||
}
|
||||
@@ -122,14 +139,28 @@ public static class SortaKindaImportExport
|
||||
Name = external.Name,
|
||||
Description = string.Empty,
|
||||
Order = external.Index,
|
||||
Priority = 100,
|
||||
Priority = external.Index,
|
||||
Color = external.Color,
|
||||
Rules = new CategoryRuleSet
|
||||
{
|
||||
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>(),
|
||||
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>
|
||||
{
|
||||
Enabled = external.ItemLevelFilter?.Enable ?? false,
|
||||
@@ -141,7 +172,13 @@ public static class SortaKindaImportExport
|
||||
Enabled = external.VendorPriceFilter?.Enable ?? false,
|
||||
Min = external.VendorPriceFilter?.MinValue ?? 0u,
|
||||
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,
|
||||
Id = internalCat.Id,
|
||||
Name = internalCat.Name,
|
||||
Index = internalCat.Order,
|
||||
AllowedItemNames = internalCat.Rules.AllowedItemNamePatterns?.ToList() ?? new List<string>(),
|
||||
Index = internalCat.Priority,
|
||||
|
||||
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>(),
|
||||
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>
|
||||
{
|
||||
Enable = internalCat.Rules.ItemLevel.Enabled,
|
||||
@@ -169,8 +222,16 @@ public static class SortaKindaImportExport
|
||||
MinValue = internalCat.Rules.VendorPrice.Min,
|
||||
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,
|
||||
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<UserCategoryDefinition> UserCategoriesSortedScratch = new(capacity: 64);
|
||||
|
||||
private static readonly List<uint> RemoveKeysScratch = new(capacity: 256);
|
||||
|
||||
private const uint UserCategoryKeyFlag = 0x8000_0000;
|
||||
@@ -149,9 +151,22 @@ public static unsafe class InventoryState
|
||||
|
||||
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);
|
||||
|
||||
if (!BucketsByKey.TryGetValue(key, out CategoryBucket? bucket))
|
||||
@@ -182,11 +197,15 @@ public static unsafe class InventoryState
|
||||
foreach (var itemKvp in ItemInfoByItemId)
|
||||
{
|
||||
ItemInfo item = itemKvp.Value;
|
||||
uint itemId = item.Item.ItemId;
|
||||
|
||||
if (claimedItemIds.Contains(itemId))
|
||||
continue;
|
||||
|
||||
if (UserCategoryMatcher.Matches(item, category))
|
||||
{
|
||||
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 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();
|
||||
|
||||
public bool IsRegexMatch(string searchTerms)
|
||||
|
||||
@@ -24,12 +24,21 @@ internal static class UserCategoryMatcher
|
||||
if (rules.AllowedRarities.Count > 0 && !rules.AllowedRarities.Contains(item.Rarity))
|
||||
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))
|
||||
return false;
|
||||
|
||||
if (rules.VendorPrice.Enabled && !InRange(item.VendorPrice, rules.VendorPrice.Min, rules.VendorPrice.Max))
|
||||
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)
|
||||
{
|
||||
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>
|
||||
=> 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