NHSE/NHSE.Core/Editing/Batch/ItemReflection.cs
Kurt b88c518d5c
Update FieldItemEditor for 3.0.0 (#716)
Updates the Field Item Editor to render layers based on the entire map, and the per-patch positioning of each layer.
Import/export will gracefully handle upgrade/downgrade, and viewport import/export will gracefully update tiles rather than a per-acre basis.

Performance has also been slightly improved; no allocation is done anymore when updating the image.
2026-01-25 16:55:38 -06:00

84 lines
2.7 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace NHSE.Core;
public sealed class ItemReflection
{
public static ItemReflection Default { get; } = new();
public readonly Type[] Types = [typeof(Item), typeof(VillagerItem)];
public string[][] Properties => GetProperties.Value;
/// <summary>
/// Extra properties to show in the list of selectable properties (GUI)
/// </summary>
private static readonly string[] CustomProperties =
[
];
public readonly Dictionary<string, PropertyInfo>.AlternateLookup<ReadOnlySpan<char>>[] Props;
private readonly Lazy<string[][]> GetProperties;
public ItemReflection()
{
Props = GetPropertyDictionaries(Types);
GetProperties = new Lazy<string[][]>(() => GetPropArray(Props, CustomProperties));
}
private static Dictionary<string, PropertyInfo>.AlternateLookup<ReadOnlySpan<char>>[] GetPropertyDictionaries(ReadOnlySpan<Type> types)
{
var result = new Dictionary<string, PropertyInfo>.AlternateLookup<ReadOnlySpan<char>>[types.Length];
for (int i = 0; i < types.Length; i++)
result[i] = GetPropertyDictionary(types[i], ReflectUtil.GetAllPropertyInfoPublic).GetAlternateLookup<ReadOnlySpan<char>>();
return result;
}
private static Dictionary<string, PropertyInfo> GetPropertyDictionary(Type type, Func<Type, IEnumerable<PropertyInfo>> selector)
{
const int expectedMax = 8;
var dict = new Dictionary<string, PropertyInfo>(expectedMax);
var props = selector(type);
foreach (var p in props)
dict.TryAdd(p.Name, p);
return dict;
}
private static string[][] GetPropArray<T>(Dictionary<string, T>.AlternateLookup<ReadOnlySpan<char>>[] types, ReadOnlySpan<string> extra)
{
// Create a list for all types, [inAny, ..types, inAll]
var result = new string[types.Length + 2][];
var p = result.AsSpan(1, types.Length);
for (int i = 0; i < p.Length; i++)
{
var type = types[i].Dictionary;
string[] combine = [.. type.Keys, .. extra];
Array.Sort(combine);
p[i] = combine;
}
// Properties for any PKM
// Properties shared by all PKM
var first = p[0];
var any = new HashSet<string>(first);
var all = new HashSet<string>(first);
foreach (var set in p[1..])
{
any.UnionWith(set);
all.IntersectWith(set);
}
var arrAny = any.ToArray();
Array.Sort(arrAny);
result[0] = arrAny;
var arrAll = all.ToArray();
Array.Sort(arrAll);
result[^1] = arrAll;
return result;
}
}