fix(spawners): make SpawnerDto.ToSpawner() self-cleaning on failure
CreateEmpty() registers the Item in the world before population. If ApplyDto or subtype-field application throws, the import catch cannot reach the (unassigned) spawner local, re-opening the orphan leak Approach B prevents. Wrap population in try/catch in the base ToSpawner() and all three overrides: on failure Delete() the single Item and rethrow, so the import path only counts the failure. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
bf31bceea4
commit
ede4bcc718
1 changed files with 49 additions and 15 deletions
|
|
@ -51,8 +51,18 @@ public abstract record SpawnerDto
|
|||
public virtual BaseSpawner ToSpawner()
|
||||
{
|
||||
var spawner = CreateEmpty();
|
||||
spawner.ApplyDto(this);
|
||||
return spawner;
|
||||
try
|
||||
{
|
||||
spawner.ApplyDto(this);
|
||||
return spawner;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// CreateEmpty already registered the Item in the world; if population throws,
|
||||
// delete it here so no orphan can escape (the import catch can't reach it).
|
||||
spawner.Delete();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -66,12 +76,20 @@ public sealed record SpawnerDataDto : SpawnerDto
|
|||
public override BaseSpawner ToSpawner()
|
||||
{
|
||||
var spawner = (Spawner)base.ToSpawner();
|
||||
if (SpawnBounds is { } bounds && bounds != default)
|
||||
try
|
||||
{
|
||||
spawner.SpawnBounds = bounds;
|
||||
}
|
||||
if (SpawnBounds is { } bounds && bounds != default)
|
||||
{
|
||||
spawner.SpawnBounds = bounds;
|
||||
}
|
||||
|
||||
return spawner;
|
||||
return spawner;
|
||||
}
|
||||
catch
|
||||
{
|
||||
spawner.Delete();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -85,8 +103,16 @@ public sealed record RegionSpawnerDto : SpawnerDto
|
|||
public override BaseSpawner ToSpawner()
|
||||
{
|
||||
var spawner = (RegionSpawner)base.ToSpawner();
|
||||
spawner.SpawnRegion = Server.Region.Find(Region, Map) as BaseRegion;
|
||||
return spawner;
|
||||
try
|
||||
{
|
||||
spawner.SpawnRegion = Server.Region.Find(Region, Map) as BaseRegion;
|
||||
return spawner;
|
||||
}
|
||||
catch
|
||||
{
|
||||
spawner.Delete();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -103,14 +129,22 @@ public sealed record ProximitySpawnerDto : SpawnerDto
|
|||
public override BaseSpawner ToSpawner()
|
||||
{
|
||||
var spawner = (ProximitySpawner)base.ToSpawner();
|
||||
if (SpawnBounds is { } bounds && bounds != default)
|
||||
try
|
||||
{
|
||||
spawner.SpawnBounds = bounds;
|
||||
}
|
||||
if (SpawnBounds is { } bounds && bounds != default)
|
||||
{
|
||||
spawner.SpawnBounds = bounds;
|
||||
}
|
||||
|
||||
spawner.TriggerRange = TriggerRange;
|
||||
spawner.SpawnMessage = SpawnMessage;
|
||||
spawner.InstantFlag = Instant;
|
||||
return spawner;
|
||||
spawner.TriggerRange = TriggerRange;
|
||||
spawner.SpawnMessage = SpawnMessage;
|
||||
spawner.InstantFlag = Instant;
|
||||
return spawner;
|
||||
}
|
||||
catch
|
||||
{
|
||||
spawner.Delete();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue