From c41d6a89d364da8c0ffcf338ecdf1ec7c1864150 Mon Sep 17 00:00:00 2001 From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com> Date: Thu, 25 Jun 2026 10:46:24 -0700 Subject: [PATCH] feat(spawners): add typed JSON binding for ProximitySpawner - Add ProximitySpawner.Json.cs with shadow properties for triggerRange, spawnMessage, and instant; OnAfterJsonDeserialize calls base then applies them - Mark ProximitySpawner [JsonDiscoverableType] and its parameterless ctor [JsonConstructor] for STJ polymorphism discovery - Add ProximitySpawnerRoundTripTests with test-hygiene finally cleanup Co-Authored-By: Claude Sonnet 4.6 --- .../Json/ProximitySpawnerRoundTripTests.cs | 41 +++++++++++++ .../Engines/Spawners/ProximitySpawner.Json.cs | 58 +++++++++++++++++++ .../Engines/Spawners/ProximitySpawner.cs | 2 + 3 files changed, 101 insertions(+) create mode 100644 Projects/UOContent.Tests/Tests/Engines/Spawners/Json/ProximitySpawnerRoundTripTests.cs create mode 100644 Projects/UOContent/Engines/Spawners/ProximitySpawner.Json.cs diff --git a/Projects/UOContent.Tests/Tests/Engines/Spawners/Json/ProximitySpawnerRoundTripTests.cs b/Projects/UOContent.Tests/Tests/Engines/Spawners/Json/ProximitySpawnerRoundTripTests.cs new file mode 100644 index 000000000..2f66e92d8 --- /dev/null +++ b/Projects/UOContent.Tests/Tests/Engines/Spawners/Json/ProximitySpawnerRoundTripTests.cs @@ -0,0 +1,41 @@ +using System.Collections.Generic; +using System.Text.Json; +using Server; +using Server.Engines.Spawners; +using Xunit; + +namespace UOContent.Tests.Engines.Spawners.Json; + +[Collection("Sequential UOContent Tests")] +public class ProximitySpawnerRoundTripTests +{ + [Fact] + public void ProximitySpawner_RoundTrips_ProximityFields() + { + ProximitySpawner spawner = null; + ProximitySpawner s = null; + try + { + spawner = new ProximitySpawner("Fisherman") { TriggerRange = 4, InstantFlag = true }; + spawner.SpawnMessage = 500000; + spawner.MoveToWorld(new Point3D(120, 120, 0), Map.Felucca); + + var json = JsonSerializer.Serialize>( + new List { spawner }, SpawnerJsonSerializer.Options); + Assert.Contains("\"$type\": \"ProximitySpawner\"", json); + Assert.Contains("\"triggerRange\": 4", json); + Assert.Contains("\"instant\": true", json); + + var rt = JsonSerializer.Deserialize>(json, SpawnerJsonSerializer.Options); + s = Assert.IsType(Assert.Single(rt)); + Assert.Equal(4, s.TriggerRange); + Assert.True(s.InstantFlag); + Assert.Equal(500000, s.SpawnMessage.Number); + } + finally + { + s?.Delete(); + spawner?.Delete(); + } + } +} diff --git a/Projects/UOContent/Engines/Spawners/ProximitySpawner.Json.cs b/Projects/UOContent/Engines/Spawners/ProximitySpawner.Json.cs new file mode 100644 index 000000000..ad91755b6 --- /dev/null +++ b/Projects/UOContent/Engines/Spawners/ProximitySpawner.Json.cs @@ -0,0 +1,58 @@ +/************************************************************************* + * ModernUO * + * Copyright 2019-2026 - ModernUO Development Team * + * Email: hi@modernuo.com * + * File: ProximitySpawner.Json.cs * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *************************************************************************/ + +using System.Text.Json.Serialization; + +namespace Server.Engines.Spawners; + +public partial class ProximitySpawner +{ + private int _jsonTriggerRange; + private TextDefinition _jsonSpawnMessage; + private bool _jsonInstant; + + [JsonInclude] + [JsonPropertyName("triggerRange")] + public int JsonTriggerRange + { + get => TriggerRange; + set => _jsonTriggerRange = value; + } + + [JsonInclude] + [JsonPropertyName("spawnMessage")] + public TextDefinition JsonSpawnMessage + { + get => SpawnMessage; + set => _jsonSpawnMessage = value; + } + + [JsonInclude] + [JsonPropertyName("instant")] + public bool JsonInstant + { + get => InstantFlag; + set => _jsonInstant = value; + } + + protected internal override void OnAfterJsonDeserialize() + { + base.OnAfterJsonDeserialize(); + + TriggerRange = _jsonTriggerRange; + SpawnMessage = _jsonSpawnMessage; + InstantFlag = _jsonInstant; + } +} diff --git a/Projects/UOContent/Engines/Spawners/ProximitySpawner.cs b/Projects/UOContent/Engines/Spawners/ProximitySpawner.cs index 90dae2d43..47f4f6a0d 100644 --- a/Projects/UOContent/Engines/Spawners/ProximitySpawner.cs +++ b/Projects/UOContent/Engines/Spawners/ProximitySpawner.cs @@ -22,6 +22,7 @@ using Server.Mobiles; namespace Server.Engines.Spawners; [SerializationGenerator(0)] +[JsonDiscoverableType] public partial class ProximitySpawner : Spawner { [SerializableField(0)] @@ -37,6 +38,7 @@ public partial class ProximitySpawner : Spawner private bool _instantFlag; [Constructible(AccessLevel.Developer)] + [System.Text.Json.Serialization.JsonConstructor] public ProximitySpawner() { }