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 <noreply@anthropic.com>
This commit is contained in:
Kamron Batman 2026-06-25 10:46:24 -07:00
parent d2a72f98f6
commit c41d6a89d3
3 changed files with 101 additions and 0 deletions

View file

@ -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<List<BaseSpawner>>(
new List<BaseSpawner> { spawner }, SpawnerJsonSerializer.Options);
Assert.Contains("\"$type\": \"ProximitySpawner\"", json);
Assert.Contains("\"triggerRange\": 4", json);
Assert.Contains("\"instant\": true", json);
var rt = JsonSerializer.Deserialize<List<BaseSpawner>>(json, SpawnerJsonSerializer.Options);
s = Assert.IsType<ProximitySpawner>(Assert.Single(rt));
Assert.Equal(4, s.TriggerRange);
Assert.True(s.InstantFlag);
Assert.Equal(500000, s.SpawnMessage.Number);
}
finally
{
s?.Delete();
spawner?.Delete();
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>. *
*************************************************************************/
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;
}
}

View file

@ -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()
{
}