using AcDream.Plugin.Abstractions; using OpenAC.MosswartMassacre.Backend; using OpenAC.MosswartMassacre.Streams; namespace OpenAC.MosswartMassacre.Tests.Streams; /// The character_stats frame as the original's CharacterStats.CollectAndSend wrote it. public sealed class CharacterStatsTests { private const string Stamp = "2026-09-25T08:30:15.1230000Z"; private static PluginHarness Arranged() { var harness = new PluginHarness("Mossy"); var c = harness.Host.Automation.Character; c.Level = 126; c.Attributes = [ new PluginAttributeInfo(0, "Strength", 300u) { Base = 290u, Ranks = 190u }, new PluginAttributeInfo(1, "Endurance", 200u) { Base = 200u, Ranks = 100u }, ]; c.Vitals = [new PluginVitalInfo(0, "Health", 300u, 341u) { Base = 331u }]; c.Skills.Add(new PluginSkillInfo(34u, "War Magic", PluginSkillTraining.Specialized, 540u) { Base = 533u }); c.Skills.Add(new PluginSkillInfo(6u, "Melee Defense", PluginSkillTraining.Trained, 400u) { Base = 388u }); harness.Host.Automation.Objects.Properties[0x50000001] = new PluginItemProperties( new Dictionary { [5] = 9000, // burden units (blacklisted from properties) [24] = 3, // skill credits (blacklisted) [43] = 12, // deaths (blacklisted) [98] = 1_000_000_000, // creation time (blacklisted) [230] = 2, // carrying-capacity augmentations [218] = 1, // an augmentation: kept }, new Dictionary { [1] = 123_456_789_012L, [2] = 5_000L, [6] = 500_000L }, new Dictionary(), new Dictionary(), new Dictionary { [3] = "Male", [4] = "Aluvian" }, new Dictionary(), new Dictionary()); harness.Login(); harness.Frames.Clear(); return harness; } [Fact] public void The_frame_keeps_the_originals_fields_order_and_types() { // CharacterStats.cs:252-383. burden = (int)((float)9000 / (300*150) * 100) = 20; // capacity = 150*300 + 2*30*300 = 63000; birth = 1970 + 1e9 s in en-US. using var harness = Arranged(); var stream = harness.Feature(); stream.CurrentTitle = () => 42; stream.Titles = () => ["Adventurer", "Sawato Resident"]; stream.Allegiance = () => new AllegianceSummary( "Mossy Club", new AllegianceMember("King", 1, 8, 1), null, 3, 17); string json = Wire.Serialize(stream.Build()); Assert.Equal( "{\"type\":\"character_stats\",\"timestamp\":\"" + Stamp + "\",\"character_name\":\"Mossy\"," + "\"level\":126,\"race\":\"Aluvian\",\"gender\":\"Male\",\"birth\":\"9/9/2001 1:46:40 AM\"," + "\"total_xp\":123456789012,\"unassigned_xp\":5000,\"skill_credits\":3,\"deaths\":12," + "\"burden\":20,\"burden_units\":9000,\"encumbrance_capacity\":63000," + "\"luminance_earned\":500000,\"luminance_total\":null,\"current_title\":42," + "\"attributes\":{\"strength\":{\"base\":290,\"creation\":100},\"endurance\":{\"base\":200,\"creation\":100}}," + "\"vitals\":{\"health\":{\"base\":331}}," + "\"skills\":{\"melee_defense\":{\"base\":388,\"training\":\"Trained\"},\"war_magic\":{\"base\":533,\"training\":\"Specialized\"}}," + "\"allegiance\":{\"name\":\"Mossy Club\",\"monarch\":{\"name\":\"King\",\"race\":1,\"rank\":8,\"gender\":1},\"patron\":null,\"rank\":3,\"followers\":17}," + "\"properties\":{\"230\":2,\"218\":1}," + "\"titles\":[\"Adventurer\",\"Sawato Resident\"]}", json); } [Fact] public void Unknown_title_and_allegiance_are_null() { using var harness = Arranged(); string json = Wire.Serialize(harness.Feature().Build()); Assert.Contains("\"current_title\":null,", json, StringComparison.Ordinal); Assert.Contains("\"allegiance\":null,", json, StringComparison.Ordinal); Assert.EndsWith("\"titles\":null}", json, StringComparison.Ordinal); } [Fact] public void Sent_five_seconds_after_login_then_every_ten_minutes() { using var harness = Arranged(); harness.Run(4.5, 0.5); Assert.Empty(harness.FramesOfType("character_stats")); harness.Run(0.6, 0.1); Assert.Single(harness.FramesOfType("character_stats")); harness.Run(600, 5); Assert.Equal(2, harness.FramesOfType("character_stats").Count()); } }