8000 Add: MudMaster Chat Protocol (MMCP) by jmckisson · Pull Request #7765 · Mudlet/Mudlet · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Add: MudMaster Chat Protocol (MMCP) #7765

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 68 commits into
base: development
Choose a base branch
from

Conversation

jmckisson
Copy link
Contributor

Brief overview of PR changes/additions
Add MMCP Client and Server classes, Lua scriptability, and options for the MudMaster Chat Protocol

Motivation for adding to Mudlet
This is a feature largely requested by players of the Medievia MUD, it allows peer to peer client communication integrated directly into the main console.

Other info (issues closed, discussion etc)
Starting a new PR as the original PR 7155 was unintentionally closed/deleted from my local disk

Copy link
Contributor
github-actions bot commented Mar 1, 2025
Warnings
⚠️ PR makes changes to 18 source files. Double check the scope hasn't gotten out of hand

Generated by 🚫 dangerJS against b010263

@add-deployment-links
Copy link
add-deployment-links bot commented Mar 1, 2025

Hey there! Thanks for helping Mudlet improve. 🌟

Test versions

You can directly test the changes here:

@jmckisson jmckisson marked this pull request as ready for review March 5, 2025 18:53
@jmckisson jmckisson requested a review from a team as a code owner March 5, 2025 18:53
@jmckisson
Copy link
Contributor Author

Ok, bit of a headache there as I had to do this with a new fork. Finally heard back from GitHub they will restore my old fork but I'd need to delete this one first and of course I had already made the PR.
This has been stable for months for my use case and all of the people using the build from PR 7155 (most Medievia people), but it could still use a looking over.

@atari2600tim
Copy link
Contributor
atari2600tim commented Apr 10, 2025

Trying out 80c7, the bot comment still says an older one. This time I'm throwing in KildClient, which has a plugin that is questionable.

Seems like everything I wrote about on March 28 is good now aside from the server staying open that SlySven is going to do.

March 31 stuff seems all good aside from it still thinks that it successfully listened on port tied up by other program.

Would be good to say which peer is the one that refused connection or timed out.

Can't tell who the snooped messages are coming from. Actually I can't tell who I have snooped either. On Wintin I started sending without requesting it from this side, so maybe there is no negotiation required for that as part of the protocol? At least there is notification line that it has started. MUSHclient and Tintin do not indicate who a snooped message came from. KildClient puts each connection in separate windows. I don't know if having the name or the ID number in front would be a good approach, or if it is rare for people to snoop multiple that nobody would ever need it.

I don't think you can find the flags from lua script.

unChat is weird name.

I had only tried things I saw in lua-function-list.json, but now I notice there are events too, sysMMCPMessage when I send out a chat or chat comes in to me or when I list the peers, and sysChatChannelMessage. Approach is similar to sysIrcMessage where variety of messages are handled similar, which seems workable, but I'd like to see who the message came from. I was able to make a separate chat window by doing decho("myConsoleWindow",ansi2decho(args[2])), and plain text is possible with ansi2dstring, though scripters would have to be aware of that. Doesn't seem to be an event for incoming snooped messages. With the events being available, maybe a checkbox to refrain from displaying the messages in main window could be good.

@jmckisson jmckisson requested a review from atari2600tim April 13, 2025 22:27
@atari2600tim
Copy link
Contributor

I got far along before I realized that it was not accepting calls from Tintin. Apparently I did not try that earlier. When I get some time I'll experiment maybe tomorrow and see if it says hello in a different way. I was able to call in from MushClient and KildClient.

Everything else works pretty good and it's mostly final polish stuff I'm making note of, I was using 8979a and wrote most of this a couple days ago.

Keyboard navigation, the tab order is weird. You want to go to line 4646 of profile_preferences.ui and list the new named items after the discord user discriminator, in order a column at a time.

Looking at the IRC and Discord sections, the existing XML is in order a row at a time, so I'd rearrange that too for readability.

"Chatname" on preferences -> "Chat Name". "Add Newline to Chat Messages" is missing hover text. Looks like established pattern of capitalization is usually just first word capitalized. "Newline" I'd probably reword too.

Peek requests are for looking to see who your friend is connected to, and connection request is to do that and then connect to them, I don't have a good suggestion of how to rephrase tooltips on those to make it clear. Since peek tells them the addresses and ports that you are connected to, the specs are kind of weird to have them be two things. Is it common that clients have separate permissions on those? It works but just seems weird.

I see in the specs page that the list is tilde delimited, so probably good to restrict setting a name with a tilde in it. Tintin is perfectly happy to name myself with tilde in it though. It really confuses the other instance of Tintin. I'm not sure if anyone would intentionally want tilde in name.

.arg(RST, pClient->getInfoString(), pClient->getVersion());
}

const QString strMessage = tr("%1Id Name Address Port Group Flags ChatClient\n"
Copy link
Contributor
@atari2600tim atari2600tim Apr 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the CrowdIn translation system, I do not know what they will do with a nicely formatted table. I know with the tr() function we can either add an argument or a comment nearby and maybe tell the translator to keep the characters aligned. Or maybe split it up and translate each part and arrange it with padding. Someone who does translation stuff would have to chime in on how to approach that. Maybe even have it be untranslated and always English like the debugging stuff is.

@jmckisson
Copy link
Contributor Author

I got far along before I realized that it was not accepting calls from Tintin. Apparently I did not try that earlier. When I get some time I'll experiment maybe tomorrow and see if it says hello in a different way. I was able to call in from MushClient and KildClient.

Hmm this was definitely working at one point, I'll get to the bottom of it...

Keyboard navigation, the tab order is weird. You want to go to line 4646 of profile_preferences.ui and list the new named items after the discord user discriminator, in order a column at a time.

Looking at the IRC and Discord sections, the existing XML is in order a row at a time, so I'd rearrange that too for readability.

"Chatname" on preferences -> "Chat Name". "Add Newline to Chat Messages" is missing hover text. Looks like established pattern of capitalization is usually just first word capitalized. "Newline" I'd probably reword too.

Thanks I had overlooked this and will resolve it!

Peek requests are for looking to see who your friend is connected to, and connection request is to do that and then connect to them, I don't have a good suggestion of how to rephrase tooltips on those to make it clear. Since peek tells them the addresses and ports that you are connected to, the specs are kind of weird to have them be two things. Is it common that clients have separate permissions on those? It works but just seems weird.

It does seem a bit weird, I can combine the two options into a single checkbox.

I see in the specs page that the list is tilde delimited, so probably good to restrict setting a name with a tilde in it. Tintin is perfectly happy to name myself with tilde in it though. It really confuses the other instance of Tintin. I'm not sure if anyone would intentionally want tilde in name.

It wou 6D40 ldn't hurt to disallow tilde in a chat name, I don't think the other clients do, at least not the ones that I have source access to (namely MudMaster which is what I based my initial port on, and what most Medievia people are used to/are switching from).

@atari2600tim
Copy link
Contributor

It does seem a bit weird, I can combine the two options into a single checkbox.

I haven't even tried MudMaster myself. If it has separate checkboxes then that's what users will expect. Even if there's no difference in privacy, using one and not both is a sign that you're not inviting guests to connect to your other peers, so I can see some value there. But either way, some tooltips explaining exactly what it does would be good.

I was pretty sure that I connected from Tintin into Mudlet earlier. I retried the old builds in my downloads folder and they have same problem. There is a static IP on some of my computers and dynamic on this one, so maybe I always called in the one direction out of convenience. I didn't have logging on so can't check back on the earlier sessions. You'll probably narrow it down before I experiment with it.

@jmckisson
Copy link
Contributor Author
jmckisson commented Apr 20, 2025

I haven't even tried MudMaster myself. If it has separate checkboxes then that's what users will expect. Even if there's no difference in privacy, using one and not both is a sign that you're not inviting guests to connect to your other peers, so I can see some value there. But either way, some tooltips explaining exactly what it does would be good.

MudMaster options are very simplistic and don't offer any checkboxes for those options, instead there is a /chatprivate command which programmatically toggles:

ChatPrivate
                                                                                
Format: /chatprivate {reference number}
Format: /chatprivate {chat name}

ChatPrivate toggles the Private flag of a chat connection. Private connections
are not returned when somebody requests your connections.

   þ {reference number} The number of the chat connection you want to change.
   þ {chat name} The name of the chat connection you want to change.

I think I initially added the checkbox so users could default the option to OFF, globally, which I still think is reasonable for privacy. Then we also support Private which is on a per-client basis.

I was pretty sure that I connected from Tintin into Mudlet earlier. I retried the old builds in my downloads folder and they have same problem. There is a static IP on some of my computers and dynamic on this one, so maybe I always called in the one direction out of convenience. I didn't have logging on so can't check back on the earlier sessions. You'll probably narrow it down before I experiment with it.

I wonder if something in TinTin has changed, it it sending <Unknown> as its IP address in the connection handshake, which is failing when I try to convert to QHostAddress. I have never seen this before..

@nstockton
Copy link
nstockton commented May 2, 2025

Hello,
I have been working on a stand-alone MMCP relay server, and discovered this pull request after searching to see if Mudlet had support for MMCP. After reading through the source of the original MudMaster console version, TinTin++, and MUSHclient, as well as the protocol spec, I've found a few issues that can arise when implementing MMCP, due to omissions in the specification. I thought I would write my observations down here, in case they are useful.

Character Set

The protocol specification does not specify the expected character set for the chat name, group name, and message body for chats, but from the various implementations including the original MudMaster console client its self, it appears to be extended ASCII / Latin-1. This is not surprising, due to the age of the protocol.
It is worth noting that the original MudMaster chat console client restricted chat names to a subset of ASCII, allowing only characters 32 through 122 inclusive. That is to say, only printable characters, except for "{|}~". This means that at least as far as the original MudMaster is concerned, chat names may not be anything other than ASCII. This also has implications for string sanitization (see below).

Proper string Sanitization of User Inputs

  • End of command bytes (0xFF/255) should be removed or replaced with a different value from all user inputs, chat name, group name, message body, ETC, to prevent the peer from sending malformed messages which would confuse other peers.
    Note that of the implementations I looked at, MUSHclient was the only one that explicitly did this, replacing end of command bytes with an ASCII "y", with the comment:

    // can't have 0xFF imbedded in messages, except file blocks :)
    // 0xFF is y with 2 dots on it so y will look reasonable 
    

    If only the protocol used UTF-8 and restricted user inputs to UTF-8 for encoding, this would not be necessary, as 0xFF cannot and will never appear in valid UTF-8 encoded strings. Alas, I digress.

  • VT100/102 escape sequences should be removed from all user inputs to prevent the peer from sending strings which would interfere with other peer's terminals.
    For example, if peer sends a message with an opening color code, but doesn't send the ending/reset color code, the other peer's terminal could then be stuck printing out text in that color.

  • Line-feed characters ("\n") should be removed from chat names, as they could interfere with the initial handshake. They should also be removed from group names.
    Consider:

    Caller sends: "CHAT:<chat name>\n<ip address><port>"
    Receiver responds: "YES:<chat name>\n"
    

    Since the line-feed character is used as a delimiter/terminator, a peer having a line-feed in the chat name would likely confuse other peers during the handshake.
    I think line-feed characters should also be removed from group names as well; because even though MUD clients that implement MMCP according to the specification shouldn't have a problem parsing multi-line group names, it makes no sense for group names to be multi-line, and this could mess up the display of group names for peers that format them in tables, ETC.

  • The tilde character ("~") should be removed or replaced from chat names, to prevent misaligned output when sending peek lists.
    Referring to the choice to use tildes "~" as the delimiter/terminator for peek lists instead of commas "," as was done for connection lists, the MMCP specification has this comment:

    It's been too long since I wrote this to remember why I changed it, but this uses a slightly different format than the Request Connection list.

    The reason which the author was unable to remember at the time of writing the specification is that peek lists include the chat name, while connection lists do not. Commas are valid characters for chat names (in ASCII range 32-122), while tildes (ASCII 126) fall outside the valid range. There fore, the author decided to use dildes as the delimiter character for peek lists, to prevent misaligned values in the output.

A Note On Length of Chat Name

The original MudMaster expects chat names to be less than or equal to 30, while TinTin++ expects less than or equal to 20. For my implementation, I have opted to go with TinTin's more conservative limit.

A Note on Connection List Verses Peek List Output

It is worth noting that not only does the output of the connections list and peek list differ in choice of delimiter, but also how that delimiter is used.
Looking at the original MudMaster source, each item in the connection list is formatted like this:

"%s,%u"  # IP, port.

While each item in the peek list is formatted this way:

"%s~%u~%s~"  # IP, port, chat name.

In other words, the connections list will contain commas but will never end with a comma, while the peek list will always end with exactly 1 tilde, unless of course there were no items to output. The specification I was working from does not note this, and is outright misleading in its examples. The specification on the Mudhalla site is correct however, so I guess I should have used that one.

A Note On Connections

During the initial handshake, The caller informs the receiver of the caller's address IP/port. The address must be IPV4. It must not be IPV6.

Caller sends: "CHAT:<chat name>\n<ip address><port>"

The IP and port by design may differ from the address of the incoming socket.
The MudMaster source contains this comment:

// Real machine address.  This is the actual address, not the
// address that a firewall would nomally scramble.  Should fix
// the problems I've been having with firewalls giving me a
// different address than the machine really has.

When the peer responds to a connection or peek list request, the IP and ports that it responds with should be the same as what was provided from the connected peers during the handshake, not the socket address.
Also note that according to the source code and the protocol spec, if the caller doesn't want to provide its IP address or can't, it may pass the literal string "<Unknown>" (case sensitive without the quotes) in place of its IP address. The caller should still provide a port number regardless.

A Note On Message Loops

Due to the lack of robustness of the protocol, it is possible for clients to become stuck in a message loop in more complex setups. As far as I know, MUSHclient is the only client that takes steps to mitigate this. See:
https://mushclient.com/forum/bbshowpost.php?id=1654&page=6

I seem to have solved the loop problem for now, by remembering the last message sent, and then discarding that message if it is received again in the next 10 seconds.

In the MUSHclient source as of today, it is actually 5 seconds.
In my relay server implementation, I have done a similar approach, remembering the last messages received for each of the send everyone, send group, ETC commands, and discarding them if they are received again on that command within 5 seconds.

A Note On Reserved Commands

The MudMaster source defines 2 additional commands, not found in the protocol spec, nor in any of the other implementations. It is probably good to consider these as reserved when extending the protocol.

#define CHAT_SNOOP_COLOR				32		// Sends current color for start of snoop block.
#define CHAT_SEND_SUBSTITUTE			33

@jmckisson
Copy link
Contributor Author

Thanks @nstockton for the detailed analysis! Some of these issues re: port/ip reporting is something @SlySven had fixes in one of his branches that have not yet been merged with this PR. I'll certainly take the other issues into consideration.

Just curious, what are you writing the relay server in? I'm aware of a couple different implementations namely a Lua one https://github.com/mikejsavage/hirveserv and my own in Java https://github.com/jmckisson/ChatServer both of which are used by players/clans in the game I play (Medievia). And they're not perfect by any means :P

@nstockton
Copy link

My relay is written in Python. It's not on GitHub yet, but it will be. That's awesome others have done the same thing. If I had known there were existing projects I probably would have used one of them.

@jmckisson
Copy link
Contributor Author

The more the merrier MMCP is underutilized IMO especially in combat heavy games where you may be lagged/delayed by actions but want to report to chat calling out targets in a pvp brawl or your current health.. such like that. It is absolutely essential in Medievia for any high level play and has been a barrier to people upgrading to Mudlet from MudMaster (we still have about 2/3 of our players on MM, about 30% on Mudlet and a light spattering of TinTin, raw telnet?? and some mobile clients) in particular where people have extensive scripts focused on reporting over chat.

@nstockton
Copy link
nstockton commented May 2, 2025

I can see where that would be extremely valuable. My use case is for playing MUME, the MMapper software that 99% of the players use currently has a peer-to-peer chat system, as well as transferring character stats over the same connection to be displayed graphically. Recently, support for pushing character stats has been added server-side over GMCP, removing the need for the peer-to-peer system, the code for which has already been removed from the MMapper source. Separate chat through the MUD client is still useful however when first logging to determine which of your friends is on before you log, asking what class would best fit an existing group before logging, and communicating with minimal lag (server is in Europe, and most of us are in the U.S), not to mention people like to just idle and chat without being logged into the game world. We could use Discord for this, however, people aren't always paying attention to Discord when they are playing. Thus, I went down the rabbit hole of MMCP. I'm a MUSHclient user, but if I can be of any assistance in getting MMCP support into Mudlet, I'd be happy to. Most of the MUME players are on Mudlet, with a very small minority on TinTin, blind players mostly on MUSHclient, and a hand full of holdouts on ancient clients like JMC and Powwow. By far, Mudlet is used by the current majority.

@jmckisson
Copy link
Contributor Author

Any testing of this PR would be quite useful! I don't currently support the file transfer protocol, it was useful back when MudMaster users would share scripts that way but now there are better ways to do that. I had some plans in the back of my mind to host a script repository on my Java server, as those servers for my game at least are ran by individual clans that may create private scripts. Being able to initiate a download from the server and have it install a Mudlet package may be neat..

Additionally I've added a Mudlet specific "Side Channel" to the MMCP protocol. The aim for that is to provide a GMCP'esque out of band data transfer that triggers an event, my server supports forwarding that data to all other Mudlet clients. So perhaps similar to your use case but keeps the actual chat clear of that data. I have a mudlet package "Virtual Frames" which provides health/mana bars for all connected clients, to allow for easy monitoring and click-to-heal functionality of people in your formation (or rather whoever you're connected with on the server). Similar to how WoW raid frames worked which is what inspired me to do that.

@SlySven
Copy link
Member
SlySven commented May 3, 2025

@nstockton You've raised some far points although I think we area aware of most of them - and some of the details are going to be awkward to work around. When MMCP came out I think it was only intended to be ASCII and in English AFAICT. Handling any other encodings for working in other locales is tricky.

Like you say the use of 0xff as a terminator is a problem for many encodings (apart from UTF-8 fortunately). TBH I think UTF-8 would be the way to go but that is going to break on many of the existing - especially the unmaintained - implementations - and the almost arbitrary delimiters (, and ~) for different things which excludes them being in "names" further compounds things.

I think @jmckisson has recently picked up on that - although he might not have considered that : and . - as used in IPv4 and/or IPv6 addresses may also break things if used in names. IPv6 is also an issue because not all clients (actually, any?) support it - I know that TinTin++ didn't and I'm not aware of that having changed - furthermore a "proper" "dual-stack" implementation (if it exists) would have to also deal with other peers that are also dual-stack and work out how to avoid sending the same message down both paths. I think the ZChat alternative/extension from ZuggSoft included a message index or some such at the start of the message that each one was different but if the same text came via multiple paths the duplicates were silently dropped - or it might have been something to do with the "encryption" that it offered/used in it's "extension".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs documentation This pull request changes things the players would use/see and thus needs an update in the manual
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants
0