ModernUO/Projects/UOContent/Items/Misc
Kamron Batman 2935eafe24
feat: convert all delta-time serialization to anchored time (#2589)
## Summary

Phase 3 of the anchored-time work: **every actively-written delta-time value in the engine now stores an anchored timestamp** — absolute on the wire, shifted forward by the downtime at load. Remaining time survives restarts (as delta did), and unlike delta, the bytes do not change on every save, so an idle world serializes identically save after save.

The answer to "is it possible everywhere": **yes** — including the one case that looked impossible.

## The GenericPersistence problem, solved

`GenericPersistence` bins (`Virtues.bin`, `StealableArtifacts.bin`, …) are raw payloads with no idx header, so they have no anchor of their own — anchored reads there would silently apply zero shift. But the anchor is a property of the **save**, not the file: every file in one save shares one `World.SaveStartTime`, and `Persistence.Load` reads **all** entity indexes (phase 1) before **any** persistence payload (phase 2). So the idx v5 header stamps a save-wide `World.LoadTimeShift`, and generic persistence readers inherit it. No file-format change, no per-bin header, old bins unaffected.

## Converted

- **Item v10 → v11**: `LastMoved` — previously whole-minute delta, rewritten every save for every item, the single largest source of idle-save churn — and `DecayResetTime` (retiring the TODO from #2583). **Mobile v37 → v38**: the three stat-gain stamps. **BaseCreature v20 → v21**: `SummonEnd`.
- **17 code-generated classes** (`[DeltaDateTime]` → `[AnchoredDateTime]`, version bump + `MigrateFrom` each): the five field spells, TransientItem, VirtueContext (×7 fields), PuzzleChestSolutionAndTime, BaseCamp, BaseBoat, RentedVendor, PlayerVendor, Ethics Player, Sheep, StarRoomGate, ChampionSpawn (×3), Corpse (`TimeOfDeath`, v19). The `MigrateFrom` bodies were generated from each class's current migration schema and are compiler-verified; VirtueContext's save-flagged nullables fall back to the same defaults the old deserialize left in place. Corpse's six migrations moved to a new `Corpse.Migrations.cs`.
- **Hand-written sites**: StealableArtifacts (v2), VendorInventory (v1), ML quest objectives (persistence v3) — each gated on its own version.

**Not converted, deliberately**: the ~25 read-only `ReadDeltaTime` sites in legacy version fallbacks and migration replays — they decode existing old bytes and must never change. `[DeltaDateTime]`/`WriteDeltaTime` remain available for them.

## Verification

- Build 0 errors / 0 warnings; **837 + 708 tests green**.
- Schema regeneration produced exactly the 17 expected new `vN.json` files (all `AnchoredTime` rule args), nothing else touched.
- **New acceptance tests** pin the point of the whole effort: serializing the same item at two save times **5 hours apart produces byte-identical output**, and `LastMoved`/`DecayResetTime` round-trip **exactly** at sub-minute precision (the old minutes encoding destroyed both properties).

## Notes for review

- `LastMoved` grows from a 1–3 byte encoded minutes value to 8-byte ticks per item — the price of byte-stability; it repays itself in incremental-save behavior since unchanged items now produce unchanged bytes.
- BaseEscortable-style semantics are unchanged: anchored shift preserves *remaining* time exactly, the same contract delta provided, so no gameplay-visible behavior changes — deadlines simply stop being consumed by downtime that delta already protected against, now with stable bytes.

## Enforcement

`WriteDeltaTime` is now `[Obsolete]` (interface + implementation). With the repo's warnings-as-errors, any new delta-time write — hand-written or emitted by a still-unconverted `[DeltaDateTime]` field — fails the build, with the migration instructions in the message. That the full solution still builds with **zero warnings** is itself the proof no active delta writer survived the conversion. `ReadDeltaTime` deliberately stays un-attributed: its remaining callers decode existing old bytes and are correct forever; its XML docs now state the legacy-decode-only contract.
2026-08-22 19:34:43 -07:00
..
Bedlam fix: Codegens misc ML items (#1213) 2022-10-28 20:44:08 -07:00
Blighted Grove fix: Fixes splitting potions before error (#1862) 2024-07-06 16:39:47 -07:00
Corpses feat: convert all delta-time serialization to anchored time (#2589) 2026-08-22 19:34:43 -07:00
Labyrinth fix: Optimizes items to use default weights. (Part 3) (#2242) 2025-07-24 16:21:27 -07:00
Painted Caves fix: Codegens misc ML items (#1213) 2022-10-28 20:44:08 -07:00
Palace of Paroxysmus fix: Codegens misc ML items (#1213) 2022-10-28 20:44:08 -07:00
Prism of Light fix: Codegens misc ML items (#1213) 2022-10-28 20:44:08 -07:00
The Citadel fix: Codegens misc ML items (#1213) 2022-10-28 20:44:08 -07:00
Twisted Weald fix: Codegens misc ML items (#1213) 2022-10-28 20:44:08 -07:00
Acid.cs feat: Adds new decay system and SkipSerialization (#2311) 2026-01-08 11:43:51 -08:00
ArcaneGem.cs fix: Optimizes items to use default weights. (Part 3) (#2242) 2025-07-24 16:21:27 -07:00
BankCheck.cs fix: Fixes exploits with bank box deposits. Makes stacking more efficient (#2337) 2026-02-13 20:34:35 -08:00
Beeswax.cs fix: Optimizes items to use default weights. (Part 3) (#2242) 2025-07-24 16:21:27 -07:00
Blocker.cs chore: Use var everywhere (#2294) 2025-12-27 16:47:28 -08:00
Blood.cs fix: Codegens more misc items (#1214) 2022-10-29 00:43:30 -07:00
Bola.cs fix: Optimizes items to use default weights. (Part 3) (#2242) 2025-07-24 16:21:27 -07:00
BolaBall.cs fix: Optimizes items to use default weights. (Part 3) (#2242) 2025-07-24 16:21:27 -07:00
ClockworkAssembly.cs chore: Use var everywhere (#2294) 2025-12-27 16:47:28 -08:00
CommunicationCrystals.cs refactor: fold hand-written serializable property setters into field hooks (#2587) 2026-08-22 18:20:39 -07:00
DeceitBrazier.cs fix: Consolidates Color/Center html (#1762) 2024-05-07 23:56:32 -07:00
EffectController.cs fix: Fixes NPE with effect controller (#1406) 2023-05-21 23:29:16 -07:00
EffectItem.cs feat: Adds new decay system and SkipSerialization (#2311) 2026-01-08 11:43:51 -08:00
ExecutionersCap.cs fix: Optimizes items to use default weights. (Part 1) (#2240) 2025-07-24 14:44:39 -07:00
Firebomb.cs fix: Optimizes items to use default weights. (Part 2) (#2241) 2025-07-24 15:41:44 -07:00
FlippableAddonAttribute.cs feat: Replaces params array with params ReadOnlySpan (#2125) 2025-02-13 21:19:02 -08:00
FlippableAttribute.cs fix: Adds command help, webpage, and fixes issues with other commands (#1669) 2024-02-10 00:19:19 -08:00
GlassItems.cs fix: Optimizes items to use default weights. (Part 1) (#2240) 2025-07-24 14:44:39 -07:00
Gold.cs fix: Codegens more misc items (#1216) 2022-10-29 16:08:23 -07:00
Guillotine.cs fix: Fixes crafter deserialize, cleans up bandages, and codegens misc items (#1350) 2023-02-25 00:54:12 -08:00
GumpToggleItems.cs fix: Fixes edge cases with on off items (#1832) 2024-06-10 18:11:35 -07:00
HairDye.cs fix: Optimizes items to use default weights. (Part 1) (#2240) 2025-07-24 14:44:39 -07:00
HoveringWisp.cs fix: Codegens more misc items (#1216) 2022-10-29 16:08:23 -07:00
IDurability.cs fix: Codegens more misc items (#1216) 2022-10-29 16:08:23 -07:00
InteriorDecorator.cs perf: Migrate Item Interaction gumps to DynamicGump/StaticGump (#2421) 2026-04-26 11:31:49 -07:00
Key.cs fix: Fixes container enumeration not recycling pooled arrays (#2341) 2026-02-17 09:54:32 -08:00
KeyRing.cs fix: Optimizes items to use default weights. (Part 3) (#2242) 2025-07-24 16:21:27 -07:00
LOSBlocker.cs chore: Use var everywhere (#2294) 2025-12-27 16:47:28 -08:00
Moonstone.cs feat: Adds Mobile.Murderer virtual property, consolidates kill-threshold checks (#2355) 2026-03-06 08:36:41 -08:00
MoonstoneGate.cs feat: Adds Mobile.Murderer virtual property, consolidates kill-threshold checks (#2355) 2026-03-06 08:36:41 -08:00
MorphItem.cs refactor: fold hand-written serializable property setters into field hooks (#2587) 2026-08-22 18:20:39 -07:00
OilCloth.cs fix: Fixes crafter deserialize, cleans up bandages, and codegens misc items (#1350) 2023-02-25 00:54:12 -08:00
OilFlask.cs fix: Fixes arrow animations by using 0xC7 when possible. (#2343) 2026-03-05 23:23:20 -08:00
Origami.cs fix: Codegens more misc items (#1216) 2022-10-29 16:08:23 -07:00
PlayerBulletinBoards.cs perf: Migrate Bulletin/Poll/SOS gumps to DynamicGump (#2418) 2026-04-25 20:49:12 -07:00
PlayerVendorDeed.cs fix: Optimizes items to use default weights. (Part 1) (#2240) 2025-07-24 14:44:39 -07:00
PowerCrystal.cs fix: Optimizes items to use default weights. (Part 1) (#2240) 2025-07-24 14:44:39 -07:00
PowerGenerator.cs perf: Migrate Item Interaction gumps to DynamicGump/StaticGump (#2421) 2026-04-26 11:31:49 -07:00
ProjectedItem.cs fix: Removes unnecessary dictionary removal guards (#2565) 2026-08-08 11:50:01 -07:00
PromotionalToken.cs perf: Migrate Item Interaction gumps to DynamicGump/StaticGump (#2421) 2026-04-26 11:31:49 -07:00
PublicMoongate.cs perf: Migrate Travel/Moongate gumps to DynamicGump (#2412) 2026-04-25 17:03:24 -07:00
Rares.cs fix: Optimizes items to use default weights. (Part 3) (#2242) 2025-07-24 16:21:27 -07:00
Scales.cs fix: Optimizes items to use default weights. (Part 2) (#2241) 2025-07-24 15:41:44 -07:00
SerpentPillar.cs feat: Adds SerializedCommandProperty (#1249) 2022-11-14 18:24:33 -08:00
SpecialBeardDye.cs fix: Optimizes items to use default weights. (Part 3) (#2242) 2025-07-24 16:21:27 -07:00
SpecialHairDye.cs perf: Migrate Item Interaction gumps to DynamicGump/StaticGump (#2421) 2026-04-26 11:31:49 -07:00
Static.cs feat: Adds SerializedCommandProperty (#1249) 2022-11-14 18:24:33 -08:00
SwarmOfFlies.cs fix: Finishes code gen for misc items (#1248) 2022-11-13 23:10:13 -08:00
Teleporter.cs feat: Adds rope teleporter for New Haven Mines (#2439) 2026-05-03 17:23:31 -07:00
TrashBarrel.cs fix: Codegens evil decor. Fixes trash items (#1362) 2023-03-06 19:28:58 -08:00
TrashChest.cs fix: Fixes crafter deserialize, cleans up bandages, and codegens misc items (#1350) 2023-02-25 00:54:12 -08:00
TribalBerry.cs fix: Optimizes items to use default weights. (Part 3) (#2242) 2025-07-24 16:21:27 -07:00
TribalPaint.cs fix: Optimizes items to use default weights. (Part 3) (#2242) 2025-07-24 16:21:27 -07:00
UnholyBone.cs fix: Finishes code gen for misc items (#1248) 2022-11-13 23:10:13 -08:00
WarningItem.cs refactor: fold hand-written serializable property setters into field hooks (#2587) 2026-08-22 18:20:39 -07:00
WayPoint.cs fix: Fixes missing methods. Adds more admin gump world building (#1675) 2024-02-10 20:31:25 -08:00
WindChimes.cs feat: Moves gumps out of the core (#1916) 2024-08-09 19:07:32 -07:00