Skip to main content

Merentha InterMUD System (MIS) v1.2.0-A

Network Architecture

The Merentha "Intermer" network is a full mesh of hosts that communicate via UDP.

Features

  • Pinging a host
  • Who - Get a (formatted) list of users from the remote host
  • Finger - Get information about a user
  • Tell - send a message to a user
  • Creator channel - send messages to admins of a remote server

Message Encoding

Messages are plain ASCII strings that consist of key/value pairs. Sometimes those values are key value pairs in itself. Than it gets nasty.

  • In the top level, pairs are divided by the string ||M||. Inside a key/value pair, key and value are divided by :||:||:
  • On the medium level, pairs are divided by the string ||MM||. Inside a key/value pair, key and value are divided by ::||::||::
  • On the lowest level, pairs are divided by the string ||MMM||. Inside a key/value pair, key and value are divided by :::||:::||:::

Example 1: Ping Request

name:||:||:GraphicMUD||M||port:||:||:4000||M||udp_port:||:||:10006||M||mudlib:||:||:GraphicMUD||M||driver:||:||:Java 24.0.1+9||M||service:||:||:ping_request||M||known_muds:||:||:1

Example Ping Reply: The mudlist is a level 3 encoding (see the ||MMM||)

udp_port:||:||:10006||M||service:||:||:ping_reply||M||driver:||:||:FluffOS v2017.2019||M||name:||:||:Merentha||M||port:||:||:10000||M||mudlib:||:||:Merentha/NM||M||args:||:||:Merentha-Builders::||::||::udp_port:::||:::||:::10007||MMM||pings:::||:::||:::1||MMM||address:::||:::||:::50.22.147.227||MMM||driver:::||:::||:::FluffOS v2017.2019||MMM||name:::||:::||:::Merentha-Builders||MMM||port:::||:::||:::10001||MMM||mudlib:::||:::||:::Merentha/NM||MM||GraphicMUD::||::||::udp_port:::||:::||:::10006||MMM||pings:::||:::||:::0||MMM||address:::||:::||:::212.60.194.176||MMM||driver:::||:::||:::Java 24.0.1+9||MMM||name:::||:::||:::GraphicMUD||MMM||port:::||:::||:::4000||MMM||mudlib:::||:::||:::GraphicMUD||M||remote_user:||:||:0

Messages for services

ping_request

This request announces your MUDs presence to the remote MUD. The response contains not only information about used Mudlib and driver, but also a list of other known MUDs.

The original implementation sends ping requests in a 15 minute interval and repeats them twice if needed.

ParametertypeExampleDescription
nameStringMerenthaThe name of your MUD. Should not contain spaces
portInteger10000Port players use to connect
udp_portInteger10006Port of the MIS service (you should already know this)
mudlibStringMerenthaName of the Mudlib
driverStringFluffOS v2017.2019Type and version of the Mudlib
serviceStringAlways "ping_request"
known_mudsStringIntegerNumber of MIS-connected MUDs your server is aware of
name:||:||:GraphicMUD||M||port:||:||:4000||M||udp_port:||:||:10006||M||mudlib:||:||:GraphicMUD||M||driver:||:||:Java 24.0.1+9||M||service:||:||:ping_request||M||known_muds:||:||:1

ping_response

rwho_request

rwho_response

rfinger_request

rfinger_response

rtell_request

Tell

rtell_response

rcre_request

Send a message on the Coder/Creater channel

rcre_response

MIS is designed to connect all Merentha MudLib MUDs together. It uses UDP datagram sockets, extreamly similar to I2 (InterMUD2). In fact with minor modifications the new network daemon can be converted to use with I2 instead of MIS.

There are several reasons why I chose to create MIS instead of just connecting the Merentha Lib to I2 (or I3).

  • I have no experience with I3
  • There is lots of spam on I2 already
  • This is a learning project for myself above all else
  • MIS is designed to promote and further develop the Mer Lib

All things considered I learn't more by attempting to create my own InterMUD System then just hooking up to an existing one.

By default the UDP port is your MUDport +6 (I2 uses +8). Since encoding of information on I2 is different then on MIS I have used a seperate port, this also enable people to incorperate both InterMUDs if they wish. I do not know what I3 uses. It should be noted that in reality both I2 and MIS could interact on port +8 together and have your daemons decode which is which, but I didn't want that.

mapping convert_string_to_map(string str) {
mapping tmp=([]);
string *parts=explode(str,"||M||");
string key, val;
int i=sizeof(parts);
while(i--) {
sscanf(parts[i], "%s:||:||:%s", key, val);
tmp[key]=val;
}
return tmp;
}
mapping convert_string_to_map2(string str) {
mapping tmp=([]);
string *parts=explode(str,"||MM||");
string key, val;
int i=sizeof(parts);
while(i--) {
sscanf(parts[i], "%s::||::||::%s", key, val);
tmp[key]=val;
}
return tmp;
}
mapping convert_string_to_map3(string str) {
mapping tmp=([]);
string *parts=explode(str,"||MMM||");
string key, val;
int i=sizeof(parts);
while(i--) {
sscanf(parts[i], "%s:::||:::||:::%s", key, val);
tmp[key]=val;
}
return tmp;
}
    message=convert_string_to_map(message);
sscanf(socket_address(s), "%s %s", junk, args);
if(junk=="0.0.0.0") sscanf(host, "%s %s", junk, args);
if(mapp(message)) {
if(!message["name"]) { return; }
if(!message["service"] || member_array(message["service"],__Services)==-1) { return; }
__MUDS[message["name"]]=([
"name":message["name"],
"address":junk,
"udp_port":message["udp_port"],
"port":message["port"],
"mudlib":message["mudlib"],
"driver":message["driver"],
"pings":0,
]);
args=call_other(this_object(),({message["service"],message}));
if(!args) { return; }
if(strsrch(message["service"],"_request")!=-1) {
open_socket_to_send(""+junk+" "+message["udp_port"],
(["name":mud_name(),
"port":query_host_port(),
"udp_port":MERENTHA_INTERMUD,
"mudlib":mudlib(),
"driver":driver(),
"remote_user":message["remote_user"],
"args":args,
"service":replace_string(message["service"],"_request","_reply"),
]) );
return;
}