## Summary `_statMods` and `_skillMods` are created lazily by `AddStatMod` / `AddSkillMod` and nulled when they empty, and every reader already null-checks. The eager `new List<T>()` in `DefaultMobileInit` and `Deserialize` therefore allocated two dead 32-byte objects for every mobile. On a ~500k-mobile world that is ~32 MB and 1M gen2 objects that hold nothing. - Removes the four eager allocations. - Removes the `StatMods` accessor (no references). - Documents `SkillMods` as `null` when no mods are active (its one caller in `Skills.cs` already checks). First of three PRs from the lazy per-mobile collections design; `DamageEntries` and `Aggressors`/`Aggressed` follow separately. ## Breaking change - `Mobile.SkillMods` may now be `null` (it was never null after construction before). External callers that enumerate it or read `.Count` must null-check. - `Mobile.StatMods` is removed. Use `GetStatMod(name)` / `AddStatMod` / `RemoveStatMod`. Save format is untouched: neither list is serialized. ## Testing - `dotnet build -c Release` clean. - New `MobileLazyModListTests` plus full `Server.Tests` (840) and `UOContent.Tests` (756). |
||
|---|---|---|
| .. | ||
| Mods | ||
| AggressorInfo.cs | ||
| BaseVendor.cs | ||
| Body.cs | ||
| IHasSteps.cs | ||
| IMount.cs | ||
| IVendor.cs | ||
| Mobile.cs | ||
| Mobile.Enumerators.cs | ||
| Mobile.Messages.cs | ||
| Mobile.Migrations.cs | ||
| Movement.cs | ||
| Notoriety.cs | ||
| SimplePrompt.cs | ||
| SimpleTarget.cs | ||