feat(objects): ExtractOpl — decode OPL buffer into cliloc/args/text lines
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
685fbc146e
commit
c71bc4bcd5
2 changed files with 81 additions and 0 deletions
|
|
@ -0,0 +1,17 @@
|
|||
using Server.Commands;
|
||||
using Server.Items;
|
||||
using Xunit;
|
||||
|
||||
namespace UOContent.Tests.Commands.Objects;
|
||||
|
||||
[Collection("Sequential UOContent Tests")]
|
||||
public class ObjectIntrospectionOplTests
|
||||
{
|
||||
[Fact]
|
||||
public void ExtractOpl_captures_the_runebook_name_cliloc()
|
||||
{
|
||||
// Runebook.LabelNumber is 1041267 ("runebook") — it appears as an OPL line.
|
||||
var opl = ObjectIntrospection.ExtractOpl(typeof(Runebook));
|
||||
Assert.Contains(opl, line => line.Cliloc == 1041267);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
using System;
|
||||
using System.Buffers.Binary;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using Server.Items;
|
||||
|
||||
namespace Server.Commands;
|
||||
|
|
@ -120,4 +122,66 @@ public static class ObjectIntrospection
|
|||
|
||||
return docs;
|
||||
}
|
||||
|
||||
public static List<OplLine> ExtractOpl(Type type)
|
||||
{
|
||||
if (type.IsAssignableTo(typeof(Item)))
|
||||
{
|
||||
var item = type.CreateInstance<Item>();
|
||||
try
|
||||
{
|
||||
var opl = new ObjectPropertyList(item);
|
||||
item.GetProperties(opl);
|
||||
return DecodeOpl(opl);
|
||||
}
|
||||
finally
|
||||
{
|
||||
item.Delete();
|
||||
}
|
||||
}
|
||||
|
||||
if (type.IsAssignableTo(typeof(Mobile)))
|
||||
{
|
||||
var m = type.CreateInstance<Mobile>();
|
||||
try
|
||||
{
|
||||
var opl = new ObjectPropertyList(m);
|
||||
m.GetProperties(opl);
|
||||
return DecodeOpl(opl);
|
||||
}
|
||||
finally
|
||||
{
|
||||
m.Delete();
|
||||
}
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
private static List<OplLine> DecodeOpl(ObjectPropertyList opl)
|
||||
{
|
||||
opl.Terminate();
|
||||
var buffer = opl.Buffer;
|
||||
var lines = new List<OplLine>();
|
||||
var pos = 15; // fixed OPL header length
|
||||
|
||||
while (pos + 4 <= buffer.Length)
|
||||
{
|
||||
var cliloc = BinaryPrimitives.ReadInt32BigEndian(buffer.AsSpan(pos));
|
||||
pos += 4;
|
||||
if (cliloc == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
var byteLen = BinaryPrimitives.ReadUInt16BigEndian(buffer.AsSpan(pos));
|
||||
pos += 2;
|
||||
var args = byteLen > 0 ? Encoding.Unicode.GetString(buffer, pos, byteLen) : null;
|
||||
pos += byteLen;
|
||||
|
||||
lines.Add(new OplLine { Cliloc = cliloc, Args = args, Text = Localization.GetText(cliloc) });
|
||||
}
|
||||
|
||||
return lines;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue