Commit graph

7 commits

Author SHA1 Message Date
Kamron Batman
bf31bceea4 refactor(spawners): Approach A→B swap — deserialize via SpawnerDto records (atomic)
Replace the shadow-property (Approach A) JSON mechanism with plain DTO records
so malformed files fail as GC-only and never leak live world Items.

Changes:
- Add Json/SpawnerDto.cs: abstract SpawnerDto + SpawnerDataDto / RegionSpawnerDto /
  ProximitySpawnerDto, each [JsonDiscoverableType("<name>")] with ToSpawner()
- Add BaseSpawner.Dto.cs: internal ApplyDto(SpawnerDto) + private-protected Dto*
  export helpers (DtoGuid, DtoMinDelay, etc.)
- Add Spawner.Dto.cs, RegionSpawner.Dto.cs, ProximitySpawner.Dto.cs: ToDto() overrides
- Add public abstract SpawnerDto ToDto() to BaseSpawner
- Retarget SpawnerJsonSerializer: discovery filter BaseSpawner→SpawnerDto; polymorphism
  gate typeof(SpawnerDto); remove PruneToJsonProperties + AddOnDeserialized modifiers
- Delete BaseSpawner.Json.cs, Spawner.Json.cs, RegionSpawner.Json.cs,
  ProximitySpawner.Json.cs (Approach A shadow-property partials)
- Remove [JsonDiscoverableType] + [JsonConstructor] from Spawner/RegionSpawner/ProximitySpawner
- Rewire ExportSpawnersCommand: build List<SpawnerDto> via spawner.ToDto()
- Rewire ImportSpawnersCommand: Deserialize<List<SpawnerDto>> then dto.ToSpawner();
  map-null check now fires before ToSpawner(), so no orphan Items on bad map
- Delete 3 Approach-A round-trip tests; add SpawnerDtoRoundTripTests (4 cases)
- Update ExportImportFileTests + LegacyHomeRangeTests to use DTO path
- Add Import_MalformedFile_LeaksNoWorldItems to ImportCleanupTests

Build: dotnet build ModernUO.slnx → 0 errors, 0 warnings
Tests: dotnet test UOContent.Tests → 478/478 pass

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 15:46:47 -07:00
Kamron Batman
30d1542868 refactor(spawners): import via typed polymorphic deserialization with cleanup
- Add ImportLocation/ImportMap read-only accessors to BaseSpawner.Json.cs
  exposing _jsonLocation/_jsonMap for the importer post-STJ-deserialization.
- Rewrite ImportJsonSpawners to deserialize List<BaseSpawner> directly via
  SpawnerJsonSerializer.Options (polymorphic on $type), eliminating
  DynamicJson + AssemblyHandler.FindTypeByName + CreateInstance<ISpawner>.
- Enforce cleanup contract: every deserialized spawner (registered in World
  at Map.Internal by STJ) is either MoveToWorld'd or Delete()'d — map==null/
  Internal guard Deletes, inner catch Deletes on placement failure.
- Add internal ImportFile seam for testability (from=null safe; only used in
  JsonException path which valid files never hit).
- Add ImportCleanupTests: valid placement, no-map orphan rejected, duplicate
  location replaced — all with rigorous finally cleanup.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 11:04:01 -07:00
Bohica
e37ad17d7d
fix: Adds handling empty spawner files (#2360) 2026-03-10 23:04:39 -07:00
Kamron Batman
ebaf104935
chore: Use var everywhere (#2294) 2025-12-27 16:47:28 -08:00
Quick
0b34cc4417
feat: Changes Spawner HomeRange to SpawnBounds (#2290)
### Summary

This PR transitions the spawner system from a simple radius-based model to a flexible 3D boundary system.

### Core Changes

* **Replaced `HomeRange` with `SpawnBounds`**: Spawners now use a `Rectangle3D` to define spawn areas instead of a circular integer range.
* **Backward Compatibility**:
* The `HomeRange` property remains as a helper that generates square `SpawnBounds` centered on the spawner.
* Included a migration path (v10 to v11) that automatically converts old range data into new bounds during deserialization.


* **Dynamic Bounds Shifting**: If a spawner is moved, its `SpawnBounds` will automatically shift with it, provided the bounds are currently configured as a centered square.
* **New Spawn Logic**: Added `SpawnLocationIsHome` toggle. If enabled, spawned mobiles treat their exact spawn coordinates as their "Home" rather than the spawner's location.

### Implementation Details

* **Interface Updates**: Updated `ISpawner` to include `WalkingRange`, `SpawnBounds`, and `IsInSpawnBounds()`.
* **UI Enhancements**: The Spawner Controller Gump now displays "Custom" for complex bounds and allows copying of the new boundary properties between spawners.
* **Refactored Constructors**: Streamlined `BaseSpawner`, `ProximitySpawner`, and `RegionSpawner` constructors to support the new data types.
2025-12-26 18:07:26 -08:00
Kamron Batman
26dfde19ee
fix: Consolidates Color/Center html (#1762)
### Summary
- Fixes bad color in virtual check gump
- Consolidates the Color/Center html strings for all gumps
2024-05-07 23:56:32 -07:00
Kamron Batman
d0d7be8de0
fix: Fixes codegenned spawners and adds RunUO spawner import support (#1682)
> [!IMPORTANT]  
> This code change includes important fixes for all spawners after they were converted to codegen!

> [!NOTE] 
> **Developer Note**
> Usage/Description/Aliases attributes were moved to the core so they can be used by the command registration system.

### Summary
- **Fixes spawners not registering their spawns on world load**
- Changes `[GenerateSpawners` to `[ImportSpawners`
- Removes `ConvertPremiumSpawners`
- Adds Premium spawner import support to `[ImportSpawners`
- Adds RunUO XML import support: https://github.com/ruaduck/xmlspawner/blob/ServUOMaster/XmlSpawner/XmlSpawner%20Core/SpawnerExporter.cs
- Fixed an issue where not manually registering an alias meant it wasn't available as a command
2024-02-17 10:46:55 -08:00