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

name description
migrate-serialization Trigger: when converting RunUO Serialize/Deserialize methods, adding [SerializableField], converting [Constructable] to [Constructible], or migrating manual serialization code. Covers: source-generated serialization, field conversion, version handling, TypeAlias.

RunUO -> ModernUO Serialization Migration

When This Activates

  • Converting Serialize(GenericWriter)/Deserialize(GenericReader) overrides
  • Converting [Constructable] to [Constructible]
  • Adding [SerializableField] attributes
  • Handling save compatibility with [TypeAlias]

Conversion Steps

  1. Add using ModernUO.Serialization;
  2. Add [SerializationGenerator(0, false)] to class (version 0, false for Item/Mobile)
  3. Add partial to class declaration
  4. Convert each serialized field: private int m_X -> [SerializableField(N)] private int _x
  5. Add [SerializedCommandProperty(AccessLevel.X)] if RunUO had [CommandProperty]
  6. Add [InvalidateProperties] if setter called InvalidateProperties()
  7. DELETE the Serial constructor
  8. DELETE Serialize() and Deserialize() overrides
  9. Change [Constructable] to [Constructible]
  10. Timer fields: leave unserialized, add [AfterDeserialization] method

Quick Mapping

RunUO ModernUO
public class Foo : Item [SerializationGenerator(0, false)] public partial class Foo : Item
private int m_X + manual Serialize [SerializableField(0)] private int _x
[CommandProperty(GM)] on property [SerializedCommandProperty(GM)] on field
Foo(Serial serial) : base(serial) DELETE
Serialize(GenericWriter) DELETE -- auto-generated
Deserialize(GenericReader) DELETE -- auto-generated
Custom setter with InvalidateProperties() [InvalidateProperties] attribute
Custom setter logic [SerializableProperty(N)] with this.MarkDirty()
reader.ReadMobile() reader.ReadEntity<Mobile>()
reader.ReadItem() reader.ReadEntity<Item>()

Anti-Patterns

  • Missing partial keyword -> build error
  • Serializing TimerExecutionToken -> build error
  • Missing this.MarkDirty() in [SerializableProperty] setter -> changes not saved
  • Wrong field prefix (m_ instead of _)

See Also

  • dev-docs/runuo-migration-docs/02-serialization.md -- detailed migration reference with before/after
  • dev-docs/serialization.md -- complete ModernUO serialization system
  • dev-docs/claude-skills/modernuo-serialization.md -- ModernUO serialization skill (patterns, attributes, examples)