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.
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.
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.
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.
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
A video about the design challenges around the Jedi class in Star Wars Galaxies, and how trying to balance the most iconic fantasy of the franchise with the realities of a persistent online world shaped one of the most ambitious MMOs ever made.
We’ve reached the 1500 commits mark in the Hexagon mudlib project, since the first commit in 26 Aug 2014, when we started porting the ccmudlib project to DGD.
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.
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.
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.
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.