### Summary
Players reported an exploit: decipher a treasure map, then run a ClassicUO/Razor organizer agent that pulls the gold out of the chest in small amounts. Each pull spawned more monsters, turning one chest into an unbounded farmable spawn generator.
### Root cause
`TreasureMapChest.OnItemLifted` grants a 10% guardian spawn roll per first-time-lifted item, deduplicated by the instance-keyed `_lifted` set. But a partial lift goes through `Mobile.LiftItemDupe`, which re-adds the stack remainder to the chest as a **brand-new item instance** (engine-side `AddItem`, bypassing the `CheckHold` block on refilling). Every subsequent pull lifts an instance the `_lifted` set has never seen, so each one re-rolls the 10% spawn chance:
- A level 4 chest holds 4,000 gold → pulled coin by coin, ~400 spawned creatures (plus more from reagent stacks), hands-free, per chest.
- Spawns use `guardian: false`, so nothing tracks or caps them.
- Legit full-stack looting yields roughly 5–8 bonus spawns per chest for comparison.
The code is inherited from RunUO, so descendant shards likely share the hole.
### Fix
Mark every item that enters the chest **after the initial fill** as already lifted, via an `OnItemAdded` override gated by a non-serialized `_filled` flag (set at the end of the constructor and in `[AfterDeserialization]`). Ordering makes this exact: `LiftItemDupe` re-adds the remainder *before* the chest's `OnItemLifted` runs, so the lifted original still gets its one legitimate roll while the remainder is pre-marked.
This also covers packing items *into* the chest (e.g., merging gold back in to lift it out again) and bounce-backs — anything not part of the original loot can never grant a spawn roll.
### Tests
- `PartialLift_MarksSplitRemainderAsLifted` — drives the real `Mobile.Lift` path with a 1-coin pull and asserts the split remainder is marked (failed before the fix).
- `ItemAddedAfterFill_IsMarkedLifted` — post-fill additions are marked (failed before the fix).
- `OriginalFillLoot_IsNotMarkedLifted` — original loot keeps spawn-roll eligibility.
Full `UOContent.Tests` suite: 701 passed.
## Summary
Migrates the five-step SoulStone wizard and the TreasureMapChest remove-confirmation dialog from legacy `Gump` to the modern builder API.
Per-gump base type:
- **`SelectSkillGump` -> `DynamicGump`** -- the skill picker iterates the player's skill list and emits one button per non-zero skill, so the layout shape varies per instance.
- **`ConfirmSkillGump` -> `DynamicGump`** -- skill name uses `AosSkillBonuses.GetLabel(...)` which returns dynamic clilocs in the `1044060 + (int)skill` range, plus current/cap skill values rendered as text labels.
- **`ConfirmTransferGump` -> `DynamicGump`** -- same dynamic skill cliloc plus per-instance Base/Cap/Stored values.
- **`ConfirmRemovalGump` -> `StaticGump<ConfirmRemovalGump>`** -- only fixed clilocs (warning text, Continue, Cancel), so the layout caches.
- **`ErrorGump` -> `DynamicGump`** -- title and message clilocs are constructor parameters that vary per call site.
- **`TreasureMapChest.RemoveGump` -> `StaticGump<RemoveGump>`** -- fixed-cliloc confirmation prompt (no item list, despite the name); `Closable=false`/`Disposable=false` are now `builder.SetNoClose()`/`builder.SetNoDispose()`.
All six gumps are now `Singleton => true`, have private constructors, and expose a static `DisplayTo` entry point that validates `from`, `NetState`, and the underlying entity before constructing -- prevents the empty-gump leak. Wizard navigation between steps now goes through `DisplayTo` (e.g. `ConfirmSkillGump.DisplayTo(from, _stone, skill)` from the skill picker, `ErrorGump.DisplayTo(...)` from absorption pre-checks, `SelectSkillGump.DisplayTo(...)` from the "make another selection" button on `ConfirmSkillGump` and from `ErrorGump` bounce-back). Because each gump is Singleton, sending the same type again automatically closes any prior instance instead of stacking; the explicit `gumps.Close<T>()` chain on `OnDoubleClick` is preserved so opening the soulstone still resets any orphaned step from another wizard.
`OnResponse` now uses `in RelayInfo info`. All inline `AddX(...)` calls move to `builder.AddX(...)` inside `BuildLayout`. `Skill.Base.ToString("F1")` etc. are converted to `$"{value:F1}"` interpolation passed to `AddLabel(ReadOnlySpan<char>)`. Skill picker pagination still uses client-side `AddPage` / `GumpButtonType.Page` -- no server-state pagination to migrate.
> [!Important]
> **Developer Note**
> This code change will **completely move gumps out of the core**
### Summary
- Adds `GetGumps()` convenience which exposes methods to Find/Close/Send multiple gumps. This helper is a performance improvement by eliminating the Dictionary<Player, List> lookup for gumps.
## Summary
- Removes allocation of a `List<ContextMenuEntry>` every time a context menu is created.
- Moves packet/context menu creation logic out of the core
- Fixes tame entry
## BREAKING CHANGE
> [!Important]
> **Developer Note**
> ```cs
> public virtual void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
> ```
> and similar functions changed to
> ```cs
> public virtual void GetContextMenuEntries(Mobile from, ref PooledRefList<ContextMenuEntry> list)
> ```
### Summary
- Fixes an issue that causes CUO to crash due to bad string caching in static gumps
- Fixes wrong/bad 16bit html gump hues.
- Moves `C16232` (16-bit to 32-bit) and `C32216` (32-bit to 16-bit) to Utility class for broader use.
TODO:
- Some gumps have different 32bit (for string content) vs 16bit (for localized content) strings. Does this matter?
- [X] Caches DateTime.NowUtc on the game loop (not other threads)
- [X] Replaces all locations where it makes sense
- [X] Adds Min/Max for `IComparable` (TimeSpan, DateTimes, etc)
Closes#261
- [X] Fixes an issue where a buffer smaller than 8 bytes would not double with enough space in some cases.
- [X] Fixes an issue with dupe copying the savebuffer reference (ugh).
- [X] Streamlines the IGenericWriter API to use better generics.
- [X] Streamlines the IGenericReader API to use better generics.
- [X] Forces `tidying` of a List/HashSet to be done externally since Writers/Readers should not have side effects.
- [X] Fixes an issue where Tidying a list didn't TrimExcess, causing memory leaks.
- [X] Reverted the meaning of `World.Running` to specifically refer to any world state post world loading.
- NOTE: Do not use this if you want to block on world saves. Instead use checks against `WorldState.Saving` states.
- [X] Fixes an issue with serializing negative DateTime deltas.
- [X] Fixes a potential issue with serializing non-UTC DateTime.
Bumps release version