ModernUO/dev-docs/claude-skills/migrate-from-runuo/migrate-timers.md
Kamron Batman 4f9bc1d9f6
feat: Adds AI skills to migrate from RunUO (#2366)
## Summary

Adds comprehensive RunUO → ModernUO migration documentation and Claude AI skills to help shard owners and script authors convert RunUO 2.7 code to ModernUO.

- **10 migration skills** (`dev-docs/claude-skills/migrate-from-runuo/`) — system-by-system conversion guides (foundation, serialization, timers, gumps, packets, property lists, commands/events, persistence, items/mobiles, systems/engines)
- **12 reference docs** (`dev-docs/runuo-migration-docs/`) — deep-reference with before/after examples, API mapping tables, edge cases, and gotchas
- **Updated existing skills** — `modernuo-timers`, `modernuo-serialization`, and `modernuo-threading` now document that `Serialize()` runs on background threads and timers are not thread-safe
- **Updated `CLAUDE.md`** — added migration skill lookup table

### Key migration patterns covered
- Manual `Serialize()`/`Deserialize()` → source-generated `[SerializableField]`
- `Packet` class hierarchy → static `SpanWriter`/`SpanReader` methods
- `Timer` subclasses → `TimerExecutionToken` fire-and-forget
- `Gump` → `StaticGump<T>`/`DynamicGump` with builders
- `EventSink.WorldSave` → `GenericPersistence`
- `ObjectPropertyList` → `IPropertyList` with string hole rules
- Universal changes: naming (`m_` → `_`), `[Constructable]` → `[Constructible]`, logging, spatial queries
2026-03-13 00:33:45 -07:00

44 lines
2 KiB
Markdown

---
name: migrate-timers
description: >
Trigger: when converting RunUO Timer subclasses, Timer.DelayCall patterns, or TimerPriority usage to ModernUO fire-and-forget timers.
Covers: Timer subclass elimination, TimerExecutionToken, callback patterns, timer restoration.
---
# RunUO -> ModernUO Timer Migration
## When This Activates
- Converting nested `Timer` subclasses with `OnTick()`
- Converting `Timer.DelayCall()` patterns
- Removing `TimerPriority` usage
- Restoring timers after deserialization
## Conversion Steps
1. Move `OnTick()` logic to a method on the parent class
2. Replace `new InternalTimer(this).Start()` with `Timer.StartTimer(..., callback, out _token)`
3. Add `private TimerExecutionToken _token;` (NOT serialized)
4. Cancel in `OnAfterDelete()`: `_token.Cancel();`
5. Restore in `[AfterDeserialization]`: re-call `Timer.StartTimer(...)`
6. Delete the nested Timer class entirely
7. Remove all `TimerPriority` references
## Quick Mapping
| RunUO | ModernUO |
|---|---|
| `new Timer(delay).Start()` | `Timer.StartTimer(delay, callback)` |
| `new Timer(delay, interval).Start()` | `Timer.StartTimer(delay, interval, callback, out token)` |
| `timer.Stop()` | `token.Cancel()` |
| `Timer.DelayCall(delay, callback)` | `Timer.StartTimer(delay, callback)` |
| `Timer.DelayCall(delay, stateCallback, state)` | `Timer.DelayCall(delay, callback, state)` |
| `TimerPriority.XXX` | Remove -- timer wheel auto-schedules |
| Timer started in `Deserialize()` | `[AfterDeserialization]` method |
## Anti-Patterns
- Serializing `TimerExecutionToken` -- it's a struct tracking a pooled timer
- Starting timers in `Deserialize()` -- world isn't loaded yet, use `[AfterDeserialization]`
- Lambda closures on hot paths -- use `Timer.DelayCall` with state parameters instead
## See Also
- `dev-docs/runuo-migration-docs/03-timers.md` -- detailed migration reference
- `dev-docs/timers.md` -- complete ModernUO timer system
- `dev-docs/claude-skills/modernuo-timers.md` -- ModernUO timer skill