RunUO was built using C# from .NET 1.1 in 2002. There have been massive changes to technology in the past 20+ years. We believe it is time for Ultima Online to take advantage of this technology so a server can provide a richer experience with never before seen scale.
While it is possible (and many have done it) to migrate an active server from RunUO to ModernUO, it is a daunting task. Please ask for help in our discord!
RunUO | ModernUO | |
---|---|---|
Language | C# 4 | C# 11 (.NET 6/7) |
Supported OS | 32 & 64bit Windows or Mono | 64bit Windows, MacOS & Linux |
IDEs | VS, VSCode | VS 2022+ or Rider 2022+ |
- ModernUO can use source generators to serialization/deserialization automatically.
- This is the biggest change to the API! While intimidating and different, it unlocks the ability for ModernUO to only serialize data that has changed.
- We estimate a world save with 10mill objects on a busy server will take less than 1 second.
- This feature is optional and will remain optional indefinitely.
Serialize(GenericWriter writer)
and equiv deserialize was changed toSerialize(IGenericWriter writer)
.- The following now use generics, e.g.
BeginAction(typeof(X))
is nowBeginAction<X>
.- CanBeginAction, BeginAction and EndAction
- FindRegion and IsPartOf
- FindGump, HasGump, and CloseGump
- Functions such as
OnAdded(object)
for both Items/Mobiles are nowOnAdded(IEntity)
. - Most
delegate
have been changed toAction
.- Example:
EventSink.PlayerDeath += new PlayerDeathEventHandler(EventSink_PlayerDeath);
is nowEventSink.PlayerDeath += EventSink_PlayerDeath;
.
- Example:
ObjectPropertyList
is nowIPropertyList
,- Example:
GetProperties(ObjectPropertyList list)
is nowGetProperties(IPropertyList list)
.
- Example:
[Constructable]
attribute is now[Constructible]
.
ObjectPropertyList has been drastically optimized, which means the API has been modernized:
❌ Not valid
list.Add(1061837, "{0}\t{1}", m_CurArcaneCharges, m_MaxArcaneCharges);
✅
list.Add(1061837, $"{_curArcaneCharges}\t{_maxArcaneCharges}");
Clilocs that use arguments:
❌ Not valid
list.Add(1060659, "Level\t{1}", m_Level);
✅ - Note the string as an argument, this is mandatory!
list.Add(1060659, $"{"Level"}\t{Level}"); // ~1_val~: ~2_val~
Clilocs that use other clilocs as an argument:
❌ Do not prepend #
list.Add(1060830, $"#{dirt.ToString()}");
✅ Use the new custom cliloc argument formatter
list.Add(1060830, $"{dirt:#}");
- ModernUO is not inherently thread safe. Overall infrastructure improved with CPU and minimizing memory garbage in mind.
- Timer system improved drastically by using Timer Wheels.
- Networking is 5-10x faster by using fixed Circular Buffers.
- Network packets are no longer objects and write directly to the network buffer, improving performance by 10x.
- World saves are 10x faster by saving to memory and flushing to disk in the background.
- Improved RNG accuracy and performance by 5x using Xoshiro256++
- Converted quite a bit of configuration to JSON with a central settings file.
- Logging changed from Console.WriteLine to Serilog (still work in progress).
- Eliminated calling
DateTime.Now
which had a huge performance penalty. - Accounts are now saved to a binary file (will eventually change to a databse) to improve world save performance by eliminating XML.
- Strings are now built using the new interpolated string syntax, and highly performant string builders.
- IPv6 support.
- Generic serialization that is automatically done in parallel with the world save.
- The faction system is no longer powered by a single item and instead uses generic persistence.
- Timezone support for custom scripts that might need it.
- Hourly/daily/weekly/monthly backups & archiving using Z-Standard.
- Client version detection (including CUO) for easy configuration.
- Localization (Cliloc) support.
- Better encryption for passwords using Argon2.
- Packet throttling that is configurable per packet and per connection.
- Enable packet logging per connection.
- Owner accounts can be protected from being locked out. The first account created is automatically added to this list.
- Use optional arguments from constructors for Add command.
- Captures Razor version and displays it in client gump
- Spawners can be exported/imported using commands and use a GUID for replacement.
- By default, world saves are now every 5th minute of a real world hour.
- E.g. 5:00, 5:05, 5:10, regardless of when the server is booted.
- Some items have their constructor arguments rearranged.
- Min/max skill requirements for magery adjusted to be accurate to OSI
- Buffs/Curses now apply appropriately
- Reporting
- Remote Admin
- My RunUO
- Event Log
- DocsGen command
- Added a shared list/queue for temporary processing such as accumulating players to damage/kill.
- Adds HashSet that is ordered by insertion time
- Adds StringBuilder that is fast and does not impose garbage collection.
- Adds BitArray that can be serialized/deserialized directly to a buffer.
- Adds performant JSON support with simple API.
- Adds performant, thread unsafe, ArrayPool
- Adds highly performant and easy to use converters for HexString representation of data