feat(objects): DiscoverConstructibleTypes — all constructible Item/Mobile types

Implement DiscoverConstructibleTypes() method with HasConstructibleCtor helper
to enumerate every non-abstract Item/Mobile subclass in AssemblyHandler.Assemblies
that has at least one [Constructible] ctor.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kamron Batman 2026-07-19 11:05:15 -07:00
parent c71bc4bcd5
commit ee0c8c256d
No known key found for this signature in database
GPG key ID: 7D81DF26D9A5D94A
2 changed files with 60 additions and 0 deletions

View file

@ -0,0 +1,19 @@
using Server.Commands;
using Server.Items;
using Xunit;
namespace UOContent.Tests.Commands.Objects;
[Collection("Sequential UOContent Tests")]
public class ObjectDiscoveryTests
{
[Fact]
public void Discover_includes_concrete_constructibles_and_excludes_abstract()
{
var types = ObjectIntrospection.DiscoverConstructibleTypes();
Assert.Contains(typeof(Katana), types);
Assert.Contains(typeof(Runebook), types);
Assert.DoesNotContain(typeof(BaseWeapon), types); // abstract
}
}

View file

@ -184,4 +184,45 @@ public static class ObjectIntrospection
return lines;
}
public static List<Type> DiscoverConstructibleTypes()
{
var results = new List<Type>();
foreach (var asm in AssemblyHandler.Assemblies)
{
foreach (var type in AssemblyHandler.GetTypeCache(asm).Types)
{
if (type.IsAbstract)
{
continue;
}
if (!typeof(Item).IsAssignableFrom(type) && !typeof(Mobile).IsAssignableFrom(type))
{
continue;
}
if (HasConstructibleCtor(type))
{
results.Add(type);
}
}
}
return results;
}
private static bool HasConstructibleCtor(Type type)
{
foreach (var ctor in type.GetConstructors())
{
if (Attributes.IsConstructible(ctor, AccessLevel.Developer))
{
return true;
}
}
return false;
}
}