## 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.5 KiB
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
- Add
using ModernUO.Serialization; - Add
[SerializationGenerator(0, false)]to class (version 0, false for Item/Mobile) - Add
partialto class declaration - Convert each serialized field:
private int m_X->[SerializableField(N)] private int _x - Add
[SerializedCommandProperty(AccessLevel.X)]if RunUO had[CommandProperty] - Add
[InvalidateProperties]if setter calledInvalidateProperties() - DELETE the
Serialconstructor - DELETE
Serialize()andDeserialize()overrides - Change
[Constructable]to[Constructible] - 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
partialkeyword -> 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/afterdev-docs/serialization.md-- complete ModernUO serialization systemdev-docs/claude-skills/modernuo-serialization.md-- ModernUO serialization skill (patterns, attributes, examples)