House of Maldorne

We play, host, build, develop and recover old and new retro online games, from muds to roguelikes.

Hexagon

A Town That Lives by Itself

It is common for a MUD room to own its NPCs. The pub clones its barman on reset, the gate clones its guards, and when the room leaves memory they go with it. The next barman is a fresh clone with the same name. That works until you want a town where people have a job, a house and hours to keep, and still have them after a reboot.

In Hexagon the people of a game belong to its areas. A location clones nobody: the area keeps its population as data, and when a location loads, the area brings in the people who stand there. This post follows that system from the template to the hourly round. It builds on the location system.

Read more →

Hexagon

Props: Things in a Location You Can Use

add_item is common in LPC mudlibs. A room calls it with a name and a description, and when a player types look chair, the chair is there. That is all it does. The chair cannot be sat on, it cannot be knocked over, and it says the same thing whether the room is empty or full.

Locations, the component-based replacement for rooms in Hexagon, needed something better for the things that fill them, so I built props instead of carrying add_item over. A prop belongs to the location, like an item added with add_item did, but it has a type, its own state, and actions that change that state.

Read more →

Hexagon

Rivers, Currents and Bridges

Hexagon has water now: rivers, lakes, the sea, underground streams. You swim them instead of walking, the current carries off whatever stops swimming, and a river can have a bridge over it. The first rivers are in Reinos de Leyenda: Aeternum, one of the games built on Hexagon.

The rules come from the system of oceans and seas I wrote for Ciudad Capital in 2009, ported and extended. They live in two shared files, lib/room/water.c and lib/room/coast.c. A game still made of rooms inherits them through the room bases /lib/water.c and /lib/coast.c. A game on locations gets the same rules from the water and coast components, and converting a room to a location attaches the component with the room’s own settings, so rooms and locations run the same code.

World map with a river drawn in blue between the forest and Naduk

The world map of Reinos de Leyenda: Aeternum, with the Anduin in blue. Each cell of the world map stands for 10×10 locations of the game.

Read more →

Hexagon

Adventuring Parties

Hexagon has adventuring parties now. You put one together on the spot, you share a channel nobody else hears, and you see on the map who is with you. When you are done with it, it is gone.

What a party is

Whoever creates it leads it, and is the only one who can invite, throw somebody out, rename it or hand it over. Five people fit in one, and an invitation has to be taken up shortly after it is offered. If the leader leaves the world, whether they quit or their link drops, the next member takes over: a party does not evaporate halfway through a dungeon because the one who called it had to go.

Creating a party is the one thing a brand new character cannot do: it asks for five hours of play behind that character, counting the time it has been connected across all its sessions. Being invited to somebody else’s party has no such condition, so a newcomer can be taken along from their first minute in the world. Both numbers, and the two above, are constants in a single header, so a game built on Hexagon can pick its own.

> party create Into the Caves
You create the party 'Into the Caves'.
> party invite dorian
You invite Dorian to your party.
> party list
Party 'Into the Caves':
Ilmarin (leading)
Dorian

Read more →

New hosting: moving from OVH to Hetzner

After several years hosted at OVH, we have migrated the muds and the rest of the associated services to a new provider, Hetzner. Nothing in terms of service or addresses changes for players and visitors — everything keeps working at the same URLs and ports — but behind the scenes we now have a bit more room to grow and better price-performance for what we need.

Hetzner

As longtime readers of this blog might remember, this is far from the first time we’ve moved the servers around. Over the years we have gone through small hostings, dedicated hardware at home, Amazon Web Services, OVH, and now Hetzner. Every migration has been an excuse to clean things up, update the stack and write a short note like this one.

If you notice anything odd please let us know.

Hosting history

A small timeline of where the servers have lived during the lifetime of the project, based on some notes I had in an old notebook:

  • ~2003 — Hosted on two different home servers for a long time, just testing as a hobby. Allowing connections from the outside was a bit of a hassle, but it was fun to learn how to do it and to have the servers at home.
  • 2013-07 — Amazon Web Services (EC2) - the first time we went to the cloud, which was a big step forward in terms of reliability and performance.
  • 2015-01 — OVH
  • 2016-07 — Amazon Web Services (EC2) (again)
  • 2017-08 — OVH (again)
  • 2026-04 — Hetzner (after a long time in OVH)

Implementing PROXY protocol in MUD drivers

This is a technical post about preserving real client IPs when running MUD servers behind reverse proxies in Docker containers.

If you run MUD servers inside Docker containers behind a reverse proxy like Traefik, HAProxy or nginx, you’ve probably noticed that every player connection appears to come from the same internal IP address — the proxy’s container IP. This breaks IP-based features like login logs, anti-multiplay checks, IP banning, and anything else that relies on query_ip_number() or its equivalent.

This post explains the problem, why it happens, and how we solved it by adding PROXY protocol v1 support to the MUD drivers we use at Maldorne.

Read more →

Migrating an LDMud mudlib from 3.3 to 3.6

Heads up: this is a technical post about porting an LDMud mudlib across 14 years of driver evolution. If you usually come here for game design or play notes, you can safely skip this one.

We run a small Spanish MUD called Endor that was built on LDMud 3.3.720, released in 2011. The mudlib had been running unchanged for years on a legacy host. When we decided to move it into our Docker cluster, we hit a wall: LDMud 3.3.720 has known 64-bit bugs that cause the driver to segfault on player login. The only way forward was to port the mudlib to the current stable version, LDMud 3.6.8.

This post documents every change we had to make.

Read more →

Compiling MudOS on Modern Linux: From Debian Sarge to Bookworm

MudOS

Heads up: this is a technical post about programming and, frankly, software archaeology — compilers, linkers, decades-old C, that sort of thing. If you usually come here for game design, mud lore or play notes, you can safely skip this one. We will be back to the regular topics in the next post.

Some of the muds we run at maldorne are still based on MudOS, a driver whose codebase was last seriously touched in the early 2000s. Until this week, the way we built that driver was to compile it inside a Debian Sarge (3.1, released in 2005) container, with gcc 3.3.5, on a 32-bit i386 base image. It worked, the binary was rock solid, but the surrounding userland was 20 years old: ancient glibc, no security patches, no current toolchain.

So we sat down to see if we could compile MudOS on a current Linux. Spoiler: we could. This post is a tour of what it took.

Read more →