ModernUO/dev-docs/claude-skills/migrate-from-runuo/migrate-gumps.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

2 KiB

name description
migrate-gumps Trigger: when converting RunUO Gump classes, OnResponse handlers, or gump UI code to ModernUO DynamicGump/StaticGump. Covers: builder pattern, DisplayTo, response handling, empty gump rule.

RunUO -> ModernUO Gump Migration

When This Activates

  • Converting Gump subclasses
  • Converting OnResponse(NetState, RelayInfo) handlers
  • Updating gump sending/closing patterns

Conversion Steps

  1. Choose type: DynamicGump (variable layout) or StaticGump<T> (fixed layout)
  2. Change class declaration: class X : Gump -> class X : DynamicGump
  3. Add public override bool Singleton => true; if only one per player
  4. Make constructor private, add static DisplayTo() method
  5. Move all AddXxx() calls from constructor to BuildLayout(ref DynamicGumpBuilder builder)
  6. Prefix each call with builder.: AddLabel(...) -> builder.AddLabel(...)
  7. Convert properties: Closable = false -> builder.SetNoClose()
  8. Update OnResponse: OnResponse(NetState, RelayInfo) -> OnResponse(NetState, in RelayInfo)
  9. Update text entries: info.TextEntries[i].Text -> info.GetTextEntry(id)
  10. For StaticGump: extract variable text into placeholders + BuildStrings

Quick Mapping

RunUO ModernUO
class X : Gump class X : DynamicGump or StaticGump<X>
AddPage(0) builder.AddPage()
Closable = false builder.SetNoClose()
Dragable = false builder.SetNoMove()
OnResponse(NetState, RelayInfo) OnResponse(NetState, in RelayInfo)
info.TextEntries[i].Text info.GetTextEntry(id)
from.SendGump(new X(...)) X.DisplayTo(from, ...)
from.CloseGump(typeof(X)) from.CloseGump<X>()

Critical: Empty Gump Rule

Never create a gump with no visual elements. Use the DisplayTo() pattern -- validate before constructing.

See Also

  • dev-docs/runuo-migration-docs/04-gumps.md -- detailed migration reference
  • dev-docs/gump-system.md -- complete ModernUO gump system
  • dev-docs/claude-skills/modernuo-gump-system.md -- ModernUO gump skill