using System; using System.Collections.Generic; using System.Linq; using Server.Items; namespace Server.Commands; public sealed record SyncReport(List Appended, List Orphaned); public static class CategorizationSync { public static (List updated, SyncReport report) Reconcile( List categorization, IReadOnlyList discovered ) { var categorizedTypes = new HashSet(); foreach (var cag in categorization) { foreach (var obj in cag.Objects ?? []) { if (obj.Type != null) { categorizedTypes.Add(obj.Type); } } } var discoveredSet = new HashSet(discovered); var orphaned = categorizedTypes .Where(t => !discoveredSet.Contains(t)) .Select(t => t.Name) .OrderBy(n => n, StringComparer.Ordinal) .ToList(); var updated = new List(categorization); var appended = new List(); var itemAppend = new List(); var mobileAppend = new List(); foreach (var type in discovered) { if (categorizedTypes.Contains(type)) { continue; } appended.Add(type.Name); var target = typeof(Mobile).IsAssignableFrom(type) ? mobileAppend : itemAppend; target.Add(new CAGObject { Type = type }); } AppendUncategorized(updated, "Items.Uncategorized", itemAppend); AppendUncategorized(updated, "Mobiles.Uncategorized", mobileAppend); return (updated, new SyncReport(appended, orphaned)); } private static void AppendUncategorized(List updated, string category, List toAdd) { if (toAdd.Count == 0) { return; } var existing = updated.FirstOrDefault(c => c.Category == category); if (existing == null) { updated.Add(new CAGJson { Category = category, Objects = toAdd.ToArray() }); return; } var merged = new List(existing.Objects ?? []); merged.AddRange(toAdd); updated[updated.IndexOf(existing)] = existing with { Objects = merged.ToArray() }; } }