From d8acde2b0af4fb081d882f60f5b782d04a7ab03f Mon Sep 17 00:00:00 2001 From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com> Date: Sun, 19 Jul 2026 10:35:33 -0700 Subject: [PATCH] feat(objects): cache DTOs + chunk-key/friendly-type naming helpers Co-Authored-By: Claude Opus 4.8 (1M context) --- .../Commands/Objects/ObjectNamingTests.cs | 29 ++++++ .../Commands/Object Creation/ObjectDocs.cs | 93 +++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 Projects/UOContent.Tests/Tests/Commands/Objects/ObjectNamingTests.cs create mode 100644 Projects/UOContent/Commands/Object Creation/ObjectDocs.cs diff --git a/Projects/UOContent.Tests/Tests/Commands/Objects/ObjectNamingTests.cs b/Projects/UOContent.Tests/Tests/Commands/Objects/ObjectNamingTests.cs new file mode 100644 index 000000000..f24216df8 --- /dev/null +++ b/Projects/UOContent.Tests/Tests/Commands/Objects/ObjectNamingTests.cs @@ -0,0 +1,29 @@ +using System; +using Server.Commands; +using Xunit; + +namespace UOContent.Tests.Commands.Objects; + +public class ObjectNamingTests +{ + [Theory] + [InlineData("Items.Skill Items.Magical", "items.skill-items.magical")] + [InlineData("Items.Weapons.Swords", "items.weapons.swords")] + [InlineData("Mobiles.Uncategorized", "mobiles.uncategorized")] + public void ChunkKey_lowercases_and_replaces_spaces(string category, string expected) + { + Assert.Equal(expected, ObjectNaming.ChunkKey(category)); + } + + [Theory] + [InlineData(typeof(int), "int")] + [InlineData(typeof(bool), "bool")] + [InlineData(typeof(string), "string")] + [InlineData(typeof(double), "double")] + [InlineData(typeof(int?), "int?")] + [InlineData(typeof(Server.Items.WeaponQuality), "WeaponQuality")] + public void FriendlyTypeName_maps_primitives_and_keeps_enum_names(Type t, string expected) + { + Assert.Equal(expected, ObjectNaming.FriendlyTypeName(t)); + } +} diff --git a/Projects/UOContent/Commands/Object Creation/ObjectDocs.cs b/Projects/UOContent/Commands/Object Creation/ObjectDocs.cs new file mode 100644 index 000000000..8f18dd8fc --- /dev/null +++ b/Projects/UOContent/Commands/Object Creation/ObjectDocs.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Server.Commands; + +public static class ObjectNaming +{ + public static string ChunkKey(string category) => category.ToLowerInvariant().Replace(' ', '-'); + + public static string FriendlyTypeName(Type t) + { + if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>)) + { + return $"{FriendlyTypeName(Nullable.GetUnderlyingType(t))}?"; + } + + return t switch + { + _ when t == typeof(int) => "int", + _ when t == typeof(uint) => "uint", + _ when t == typeof(bool) => "bool", + _ when t == typeof(string) => "string", + _ when t == typeof(double) => "double", + _ when t == typeof(float) => "float", + _ when t == typeof(long) => "long", + _ when t == typeof(ulong) => "ulong", + _ when t == typeof(short) => "short", + _ when t == typeof(ushort) => "ushort", + _ when t == typeof(byte) => "byte", + _ when t == typeof(sbyte) => "sbyte", + _ when t == typeof(char) => "char", + _ when t == typeof(decimal) => "decimal", + _ => t.Name + }; + } +} + +public sealed class ObjectIndexEntry +{ + [JsonPropertyName("type")] public string Type { get; set; } + [JsonPropertyName("entity")] public string Entity { get; set; } + [JsonPropertyName("category")] public string Category { get; set; } + [JsonPropertyName("chunk")] public string Chunk { get; set; } + [JsonPropertyName("gfx")] public int ItemID { get; set; } + [JsonPropertyName("hue")] public int Hue { get; set; } + [JsonPropertyName("name")] public string Name { get; set; } + [JsonPropertyName("cliloc")] public int? Cliloc { get; set; } +} + +public sealed class ObjectIndexFile +{ + [JsonPropertyName("generatedUtc")] public string GeneratedUtc { get; set; } + [JsonPropertyName("objects")] public List Objects { get; set; } = []; +} + +public sealed class ParamDoc +{ + [JsonPropertyName("name")] public string Name { get; set; } + [JsonPropertyName("type")] public string Type { get; set; } + [JsonPropertyName("default")] public string Default { get; set; } + [JsonPropertyName("isParams")] public bool IsParams { get; set; } +} + +public sealed class CtorDoc +{ + [JsonPropertyName("parameters")] public List Parameters { get; set; } = []; +} + +public sealed class PropertyDoc +{ + [JsonPropertyName("name")] public string Name { get; set; } + [JsonPropertyName("type")] public string Type { get; set; } + [JsonPropertyName("readLevel")] public string ReadLevel { get; set; } + [JsonPropertyName("writeLevel")] public string WriteLevel { get; set; } + [JsonPropertyName("readOnly")] public bool ReadOnly { get; set; } + [JsonPropertyName("enumValues")] public string[] EnumValues { get; set; } +} + +public sealed class OplLine +{ + [JsonPropertyName("cliloc")] public int Cliloc { get; set; } + [JsonPropertyName("args")] public string Args { get; set; } + [JsonPropertyName("text")] public string Text { get; set; } +} + +public sealed class ObjectDetail +{ + [JsonPropertyName("baseType")] public string BaseType { get; set; } + [JsonPropertyName("ctors")] public List Ctors { get; set; } = []; + [JsonPropertyName("properties")] public List Properties { get; set; } = []; + [JsonPropertyName("opl")] public List Opl { get; set; } = []; +}