That’s awesome to hear!
Actually UOX3 is one of the inspirations behind Moongate. The way it approached the server architecture and scripting was really interesting and it influenced some of the ideas I’m exploring in the project.
Projects like UOX3 are a big part of the history of the Ultima Online emulator scene, so it’s great to hear from someone who helped maintain it.
Thanks! Yeah, one of the main motivations was exactly that — after years working with legacy UO codebases where networking, persistence, and game logic were deeply intertwined, I wanted to see what a clean-slate approach would look like with modern .NET.
On sector sync bursts — this is something I'm actively tuning. Right now when a player enters a new sector, we sync all ground items and mobiles in the surrounding sectors (configurable radius). For busy areas that can mean a lot of packets at once. The current approach is:
- Sector enter sync only sends the delta sectors the player wasn't already seeing, so a simple move into an adjacent sector doesn't resync everything
- Sectors close to the player (within 1 of center) are always resynced because the UO client silently drops items beyond its visual range (~18 tiles), so you need to re-send them when the player comes back
- The outgoing packet queue handles the actual send, so the game loop isn't blocked waiting for network I/O
That said, there's definitely room for prioritization (mobiles first, then nearby items, then distant items) and spreading the sync across multiple ticks instead of one burst. It's on the roadmap.
On NativeAOT — honestly, both. The single-binary deployment is great for Docker (small image, instant startup), but the real win is predictable performance. No JIT warmup, no tiered compilation surprises
mid-session. For a game server where you care about consistent tick timing, eliminating that variable is worth it. The tradeoff is you lose some runtime flexibility, but source generators fill most of that gap
(packet registration, serialization, etc.).
hank you! That separation was a very deliberate choice I've seen firsthand how quickly things degrade when packet handling leaks into game logic.
You're touching on a real pain point. Right now the Lua boundary does show measurable overhead under load, especially with per-tick callbacks across many entities (doors, spawners, etc.). MoonSharp's interop
cost adds up when you're calling into Lua thousands of times per tick.
I'm actively looking at batching script invocations per tick and capping the budget so a heavy script wave can't blow up tail latency. The goal is to keep the game loop deterministic if Lua eats too much of the tick budget, defer the rest to the next tick rather than letting the whole loop stall.
It's one of those problems where the architecture gives you a clean place to solve it (the boundary is explicit, so you can meter it), but the solution still needs work. Appreciate you calling it out — good toknow others think about the same tradeoffs.
Did you have to massage/guide the UI quite a bit? I've had terrible luck with codex, claude, and gemini at doing frontend. It's always so close but so far at the same time
So: I took most of the infrastructure from the my first attempt at moongate (https://github.com/moongate-community/moongate, which failed miserably along with https://github.com/tgiachi/Prima). From there, I had a good starting point to quickly build the foundations. I had already done the Lua scripting part in another project (https://github.com/tgiachi/Lilly.Engine). Codex helped me with all the testing, implementing functionality and creating tests, so at least I have a good sparring pattern. For the data import part (which I called FileLoaders), I took the logic from ModernUO. For the items part, I created a script (scripts/dfn_*.sh) to import items from POL! Thanks for the compliments! The way I am, if I fixate on something, it becomes an obsession!
while i understand the motivation to have codex like, do this problem for you, that's fine. what is the ethos of corresponding with people on Hacker News through the chatbot too? like i get that this particular comment i am replying to, you authored, but ChatGPT authored your post, and your documentation, and some of your other comments.
the big picture question is, if you can mess around with the bot to do anything, why spend it on this game? why not make your own original game instead?
I do use ChatGPT sometimes as a tool while working on the project (similar to using documentation, Stack Overflow, or an IDE assistant), but the post and the project direction are my own. So what?
Thanks! I've been developing in .NET for 20 years and it's come a long way , from the Windows-only Framework days to what it is now. NativeAOT, cross-platform, incredible performance. And if you've never tried it on Apple Silicon the M4 chips are absolutely insane. The server compiles to a single native binary and runs like a dream on ARM.
Outlands is impressive from a technical standpoint, they've put an insane amount of work into it and the player count speaks for itself. I played there for a while.
Personally though, I feel they've overengineered it a bit. So many custom systems layered on top that it starts to feel more like WoW with UO graphics than actual UO. The original charm was in the simplicity
you, a sword, and a world that didn't care about your feelings. But that's just my taste, and clearly thousands of players disagree with me, so what do I know.
And yes, the fact that official UO is still running in 2026 is both beautiful and insane
This was the bummer to me when I tried it. I liked the bug-ridden classic experience before the notoriety patch.
I recently tried https://www.classicuo.eu/ ClassicUO, and the nostalgia was incredible. Granted it is not playable, but there is something about that experience that all of the assistants, hotkeys, etc. fail to capture.
reply