feat(objects): cache DTOs + chunk-key/friendly-type naming helpers

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

View file

@ -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));
}
}

View file

@ -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<ObjectIndexEntry> 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<ParamDoc> 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<CtorDoc> Ctors { get; set; } = [];
[JsonPropertyName("properties")] public List<PropertyDoc> Properties { get; set; } = [];
[JsonPropertyName("opl")] public List<OplLine> Opl { get; set; } = [];
}