## 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
2 KiB
2 KiB
| name | description |
|---|---|
| migrate-timers | 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
Timersubclasses withOnTick() - Converting
Timer.DelayCall()patterns - Removing
TimerPriorityusage - Restoring timers after deserialization
Conversion Steps
- Move
OnTick()logic to a method on the parent class - Replace
new InternalTimer(this).Start()withTimer.StartTimer(..., callback, out _token) - Add
private TimerExecutionToken _token;(NOT serialized) - Cancel in
OnAfterDelete():_token.Cancel(); - Restore in
[AfterDeserialization]: re-callTimer.StartTimer(...) - Delete the nested Timer class entirely
- Remove all
TimerPriorityreferences
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.DelayCallwith state parameters instead
See Also
dev-docs/runuo-migration-docs/03-timers.md-- detailed migration referencedev-docs/timers.md-- complete ModernUO timer systemdev-docs/claude-skills/modernuo-timers.md-- ModernUO timer skill