I'm getting very involved in some interesting things with respect to my most recent MUD adventures. Latest thing is I have found out that GCMP (and others) exists. How exactly does one implement this into their SMAUG?
If I'm the coder, what exactly would I be doing to get data flowing within these little GCMP 'tunnels/channels' and then what would I need to do on the client side (MUSH) to get it to be used?
I've looked at the Aardwolf client stuff a bit, and is there a way for me to implement this on a mud if it currently doesn't have GCMP on it.
I believe this is a huge endeavour, but hey there are times to sit back, and there are times to start digging in code, right? (I'm also just sitting at home lately and have some time to burn...).
Quote: If I'm the coder, what exactly would I be doing to get data flowing within these little GCMP 'tunnels/channels'
Very little. Negotiation of capability at connection startup aside, the basic nutshell is that instead of just sending text to the player, you name the kind of data that you're sending, then assemble a json object (see https://json.org), and then put the bytes 0xFF 0xFA 0xC9 at the front and the bytes 0xFF 0xF0 at the end before sending it.
Like if you want to send the character name and level, you could send
Aside from the "Core" messages, I don't think there was ever agreement on what the standard names or json collections should be, so you can kinda do whatever you want with those.
Beyond that, the IAC WILL/WONT/DO/DONT/Supports negotiation stuff is just so that you can decide whether it's worth your bandwidth to bother sending certain details if the player's client doesn't indicate support for them. Honestly with bandwidth and stream compression being what they are these days, I don't think that part is very important and you can just send everything to everyone. The first and last bytes already protect non-GMCP clients from doing anything with those messages anyway.
Quote: Thanks Fiendish! You are being optimistic and I like that.
Honestly, for most programming, knowing what to do at a logical level based on practice thinking like a computer is much more difficult than knowing how to write the instruction syntax. The latter is just translation. So you don't need to understand all the coding aspects as long as we can get you to understand the philosophy.
For your benefit I'd like to approach this conversationally. It will take slightly longer but I think it will be worthwhile.
Let's start by asking how you would send a message to the player. Any message at all. Like "hello <playername>" for instance.
That's definitely one perspective of how to send a message. But how does the server do it if the server wants to send you a message? Say for instance that the server wants to send you your prompt. At the very last step, after it has assembled the content of your prompt together from your stats, how does it finally transmit that information to you? Is there a function in the SMAUG code that does "send this message to player"?
Sorry, you can tell I'm a bit on the flustered side of things.
I need to examine more of the mud files to actually get you that information, I don't have full access to everything with respect to the mud at this moment. I'm trying to get a testport created so that I don't break anything in the meantime.
Give me some time to collect an answer for you. Then I will come back and hopefully have more to give.
Ok great. So you're close but not quite right, but we can get to the right place from there. In LOP in the file you mentioned, you pointed to the line that says
act( blah blah blah )
That use of "act" with the parentheses and stuff is a call to a function defined in comm.c. It's the line that starts "void act". Looks like line 3378 in that file. In _that_ function is some more stuff, most of which you don't care about, but peppered throughout that function are some more function calls to things like "ch_printf" and "send_to_char". "send_to_char" definitely sounds promising and ch_printf probably stands for something like "print out this message to the character". Now those functions are defined in color.c. Do you see those functions in color.c?
Now from there you should see that ch_printf itself calls send_to_char, so maybe we can ignore it. And from there you should see that send_to_char in turn calls send_to_desc, and that send_to_desc calls write_to_buffer with some colorization (which we don't care about). Now write_to_buffer is defined back in comm.c. Do you see write_to_buffer? At this point nothing else is being called, so that makes it our stopping point. I believe that write_to_buffer with the appropriate inputs will send a message to a client. Does your inspection of the code agree with that? Does it make sense based on how it's used elsewhere?
I would look for an existing message, for example, from comm.c:
if( sysdata.wizlock && !IS_IMMORTAL( ch ) )
{
write_to_buffer( d, "The game is wizlocked. Only immortals can connect now.\r\n", 0 );
write_to_buffer( d, "Please try back later.\r\n", 0 );
close_socket( d, FALSE );
return;
}
Basically the argument "d" there is the socket descriptor (the thing you write to). The descriptor is stored in the character data (ch->desc). So send_to_char extracts that for you:
I get pretty confused with all the diff namings, i think in the ref post it's tt vice Char.Status..
Yes, well that post shows different ways of doing it. If you want to send:
hp=1234
Then you can. Then you make the client interpret that.
Or you can send it the JSON way:
Char.Status {"hp": 1234}
Now you make the client interpret that JSON string (which obviously isn't too hard, in that particular case). Using JSON has a bit more flexibility, if you want that, because you can add extra things, like mana, movement points, room number, etc. now or later if you want to.
So sorry about the acronym error. I really ought to know better. I'm in the military and we live for acronyms... I have updated my posts to reflect GMCP.
As for the comm.c default_prompt function ( I also said char default instead of void default in an earlier post, was reading the wrong line)
Interpreting inline color codes. The primary difference between send_to_desc and write_to_buffer is that send_to_desc first converts SMAUG color codes into a form that the client understands as colors.
Nick suggests using ch_printf because it lets you format your messages a particular comfortable way (if you know printf format). Just keep in mind that that will also interpret any color codes you include because it's higher in the chain than send_to_desc. If you don't want ampersands etc to get converted into colorized text in your GMCP messages, I think you'll need to bypass the colorization by calling write_to_buffer directly or do whatever SMAUG needs you to do to get them sent literally.
I think you'll need to bypass the colorization by calling write_to_buffer directly or do whatever SMAUG needs you to do to get them sent literally.
There is no need for me to have the client get colour codes in this way. So you are suggesting that I use write_to_buffer instead of ch_printf? I'm just trying to see where to put this.
From the beginning, you read me before I even started asking questions! The logic is the important part - and this is where I have great difficulty.
i'm trying to track my way through the files so I can understand.
In write_to_buffer, it already has all the data from the prompt all packaged up. I'm not sure I know how something like hp would be written in or look like by this time. I can't follow it enough.
If you don’t want ampersands etc to get converted into colorized text
in your GMCP messages, I think you’ll need to bypass the colorization by
calling write_to_buffer directly or do whatever SMAUG needs you to do to
get them sent literally.
Note that if they turn the prompt off, they wouldn’t get the GMCP
either. You might want to find where display_prompt is called (there is
an “if” test in front of it) and do the GMCP stuff there, regardless of
whether they want the prompt or not.
However even doing it here should be enough for you to test it.
The reason I suggest doing it here or near where the prompt is
displayed is because the prompt is usually updated when the HP changes,
and that is what you are trying to send.
From reading up on GMCP on some of the other sites and reading some of the refs on your page about standards, it looks like I'm going to have to document a lot of this so I don't get mixed up the further I go.
I read in many places that things such as hp/sp/ep are Char.Vitals, whereas Char.Status is for stats such as int/dex/wealth/etc.
As you state in your guide, should I just take a standard and go with that? Is there one you recommend, more complete/less complete?
I am going to try and implement this, along with using the tools for MUSHclient you have written to see if I can't get something to work!
Not in that, but the moment you decide to start sending more than just stats, things like room names and descriptions for easier script handling, then you're likely to start seeing some. So it's good to be aware of the differences between the different functions.
this means and how it works. But isn't there something I need to put before this to enable the telnet negotiations? I haven't got through the whole thread (as the link suggests) but I'm hoping it will outline a bit more on what other amendments I need to do to my codebase?
I did see on one of the pages some edits that @Nick made to a few of the files. I'm not sure I understand why all of them were made yet, and perhaps there will be more further on.
Thanks again for your support folks, I really appreciate this and am learning how to implement this.
But isn't there something I need to put before this to enable the telnet negotiations?
Technically no. I'm pretty sure that negotiating activation is just a courtesy between the client and server. Any subnegotiation messages that you send that the client can't understand _should_ just be ignored. Though I guess I don't remember whether MUSHclient cares if you send it IAC SB 201 without ever first saying that you're going to be sending them.
I have a strange suspicion that I am not getting quite what I'm looking for. In other words, I haven't set it up correctly to send me the right information.
I was about to suggest you do something like that. Yes, you are on
the right track. When I tested by forcing through the packet by using
the Game -> Test Trigger (Ctrl+Shift+F12) and entering:
\FF\FA\C9Char.Status {"hp":42}\FF\F0
I got displayed, from the GMCP_handler_NJG plugin, and with gmcpdebug
set to 2, the following:
Char.Status {"hp":42}
Then I added the line of code you quoted into my SmaugFUSS comm.c
file, compiled and tested. It also worked. In this case:
<24hp145m110mv><#10300>Char.Status {"hp":24}
You can see that it correctly showed the HP as being 24.
So, I don’t know what you have done. Did you copy and paste the exact
code you put into the file? Did you get any compiler warnings?
If I were to read the GMCP_handler_NJG plugin notes correctly, I would know that there are more than just 0 and 1, but in fact 0,1,and 2 debug modes!
Alright, So the server is sending the correct information. The whole goal of this is to have it on a miniwindow such as all the examples here are so great at doing.
Now I'm having trouble understanding the Health_Bar_Miniwindow_Telnet. I have looked at reply 133 of http://www.gammon.com.au/forum/bbshowpost.php?id=10043 but I can't seem to find where the script is catching the information or it is missing some steps..
Just to have the most up to date and bug free system. I've redone the changes and have the same results so far. Still investigating how to use the miniwindow plugins to capture that data.
Basically, the plugin, which you installed, called GMCP_handler_NJG, detects the GMCP messages. It then does a BroadcastPlugin function call to send that message to any "listening" plugins.
GMCP_message_receiver_test is an example of such a plugin. It detects the message name (eg. "char.vitals") and then decodes the JSON which is the rest of the message into a Lua table.
It then calls a handler for that message type, for example for char.vitals:
function gotCharacterVitals (vitals)
-- tprint (vitals)
-- example:
print ("HP is now:", tonumber (vitals.hp))
end -- gotCharacterVitals
Now instead of doing a print, you could update a health bar.
That part would be like the standard health bar plugin, except getting the data from a trigger it gets it from the GMCP data.
Thank you so much folks! Your help is setting me up to implement a whole lot of new tantalising features in my MUD!
I was having a bunch of problems with syntax, but I have successfully been able to get an infobox working with HP/SP!
I am still working on using a simple miniwindow perhaps as I want the ability to move them around..
I think there is the ability to just add that to an infobox? But I also want to learn how the miniwindows work in general so may go back to my other posts and get that going.
Ok, I am trying to sit down and plan out my way forward so that I can make this project something manageable.
First I want to say that over the past couple weeks, I've been reading and searching the web - to the two main people that have helped me: I am so lucky to be able to get your help! Right now, to me, you are celebrities when it comes to MUD stuffs, server and client.
Thank YOU!
That aside, I am going to work towards having a similar concept to how Aardwolf modules. It seems fairly straight forward. ref: http://www.aardwolf.com/wiki/index.php/Clients/GMCP#aardmodules_room
What I am wondering, as I'm going to start with some char. modules, how would I go about efficiently putting the right lines of code into the codebase? Here for a start you've suggested in display_prompt, but in post 7 of http://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=10043
You have made a lot of other changes, e.g. show_status, fixup_lua_strings, want_telnet_info. I suppose to make GMCP work efficiently, there is a lot of optimisation that can be done; I don't think I'm in a position to do all that at this time.
I believe that most char. modules would be best positioned to be within display_prompt; would you suggest that victim/fighting be here as well?
I've also seen the use of snprintf(), whereas in this thread I have been suggested to use ch_printf() (essentially printf()). Is there a preference here?
Quote: I've also seen the use of snprintf(), whereas in this thread I have been suggested to use ch_printf() (essentially printf()). Is there a preference here?
printf and snprintf are part of a family of system-level functions in the C language that put data into a computer memory buffer. printf is for streams, sprintf is for character arrays, snprintf is like sprintf but safer because it won't write more bytes than you explicitly tell it to write (like if you're unsure how long your total text is and you don't want to overrun the finite space that has been preallocated for storing the result). Etc (there are more). They all use the same style of syntax with %-symbol format specifiers that are then replaced by the subsequent variable values according their meaning. We can call that style printf-family syntax.
ch_printf is a SMAUG function that uses printf-family syntax to send colorized messages to a character. ch_printf may use print/sprintf/snprintf internally, but is is not interchangeable with them.
Ok, so I added that little bit of code the way that it was shown in my earlier post.
I got the strangest replies from a couple of the players... the ones using Gmud can actually see the text... Obviously from MUSHclient there was nothing to be seen, we tried Mudlet and nothing could be seen either. I didn't have access to c/zmud to test.
Is this something you know of? Is there a way to fix it?
The server should send (when connecting to the client, eg. after establishing the player name):
IAC WILL GMCP (ie. 0xFF 0xFB 0xC9)
Then if you receive (sooner or later):
IAC DO GMCP (ie. 0xFF 0xFD 0xC9)
Then you turn on a flag, which you use in your code to decide whether or not to send the GMCP messages. Obviously this flag has to be stored on a per-player basis, so it is part of the player struct (or possibly the descriptor struct).
And, if you receive:
IAC DONT GMCP (ie. 0xFF 0xFE 0xC9)
Or, no response at all, then you set the flag to false (ie. that would be its default value) and don't send GMCP messages.
You will need to add telnet negotiation code to the place where the server receives incoming data from the client, if it isn't there already. It might be.
should change clients for their own good. Gmud is not compliant with the telnet specification. Nobody should use it. Gmud will just ignore your attempts to negotiate per KaVir's comment in this thread: http://www.mudbytes.net/forum/comment/51717/
As per my suggestion though, if the client ignores the negotiation you can assume it doesn't support it. So you should really be waiting for "IAC DO GMCP" before sending GMCP stuff.
One thing I encourage you to do is send the room number (vnum). This
greatly improves the ability of the mapper to know where you are.
Preferably also send known exits and where they lead. For example from
https://www.ironrealms.com/gmcp-doc:
As per my suggestion though, if the client ignores the negotiation you can assume it doesn't support it. So you should really be waiting for "IAC DO GMCP" before sending GMCP stuff.
This sounds like a plan that doesn't force a playerbase to do something they don't want to, even though they should!
I suppose I will go scouring the forum on how to implement this before I emerge in glorious defeat and come begging back here for more juicy knowledge.
Nick Gammon said:
One thing I encourage you to do is send the room number (vnum). This greatly improves the ability of the mapper to know where you are.
I certainly will be following all protocols and recommendations. I want this to enhance the playability, I dont want to move in the wrong direction!
Though this is one of the first posts done on brainstorming the gmcp protocol, is this still a valid way to implement the negotiation? I need to read it all to see if I understand everything it is doing. There are a few random edits that I'm not quite sure I get yet.
Checking if the ch is 'blind' is essentially what we are doing?
Going through that bit of code changing I am wondering about the part about:
+char * fixup_lua_strings (const char * sce)
Is this a MUSH specific thing? If not implemented, does it cause issues? Or if it is, will it cause issues for other clients? Of course if you are aware.
I am certainly using MUSH and will be moving forward with using the wonderful plugins that gmcp can offer!
That thread mixes a lot of things together. If all you want to do right now is discover whether the client accepts telnet subnegotiations, then most of that code is unrelated. Also it defines "MUD_SPECIFIC" as \x66 (102), but GMCP would be \xC9 (201), which means that that code predates GMCP.
But did not have any luck as I believe there is more to it than just those lines. It also would not compile in my version of SMAUGFUSS194 (as stated in an earlier post).
However, I do believe that it belongs within this space in the read_from_buffer similar to how MCCP is negotiated here (TELOPT_COMPRESS2)...
Should I create a new thread for this one, or is this still close enough to the same subject to keep going?
In particular, the read_from_buffer function, at line 1300 onwards.
There is a state machine there that handles whether or not we are telnet
negotiating.
I notice that you've commented out line 1416. https://github.com/DBNU-Braska/SMAUG_GMCP/blob/master/comm.c#L1416
Please delete that line entirely. That placement is dangerous because you don't have braces around the intended scope of your "if" statement. If you don't know what that means or why it's a problem, I can explain, but history is absolutely littered with avoidable catastrophic bugs because someone thought it would be ok to omit curly braces on single line ifs.
But with that line gone though you would not be seeing that funny version message in your output, so what happens now?
The error still persists. And, it only does so when I have the handler plugin enabled.
Of course if I commend out line 1090 the error goes away, so maybe that is just in the wrong place? If I comment that out, then the server doesn't send GMCP data.
Quote: Do you believe this could be part of the reason I am getting the login error? it's sending the wrong info to buffer?
Without really thinking much about it, my first guess is that the error is caused by the the server doing the wrong thing when handler plugin sends the GMCP "hello" message.
But you've only shown us that _something_ didn't work. It would be more informative if you added debug logging to the server to show what it received that it didn't like.
I thought of using Nick's version, however there are a lot of changes involved in that one. I wasn't going to jump into that unless I had to. First off is the codebase i'm using doesn't have the std::string defined. So that would be a start I suppose.
I hadn't wanted to do a whole rewrite to a mud if I could help it.
Maybe it is something I should do however, but this is all just to help me get this working on a more heavily modified codebase that is 'like' SMAUGFUSS1.9. I don't want to change too much in a vanilla type just to see that it will be even more work on this more modified version. But maybe updating read from buffer won't change too much...
Thanks for sharing that commit, I hadn't found that one and it is effectively what I did to my version.
Just to go over the changes that I have done, I have changed the read_from_buffer to enable negotiation for the MUD_SPECIFIC items, and I have put in the fixup_lua_strings so that I can get name/victim names to work in MUSHclient.
What exactly do you want me to do to help debug. I'm not very good at knowing where/what to slip in there to enable the server to spit out the errors it is getting. I've never used gdb before so I'm trying to read some tutorials on this but would like some assistance if possible.
note, you can see my complete source on my git. Perhaps you can replicate the problem I am having.
You said you're getting "Illegal name, try another."
When the server sends that, what exactly was the name that it thinks it got? Ideally I would like to see a printout of every single message coming into the server from the client at the time that occurs.
You haven't made the changes I suggested in reply #57.
The "illegal name" thing sounds like you have put into the input buffer some of the IAC stuff, which suggests that the telnet negotiation stuff isn't working, which you already know anyway.
I'm looking at trying to do what is done in the 'status messages' commit.
As I've been doing these changes, I am getting a bit more comfortable in how navigate the mud. I do like the case format a lot better, it just looks really nice and it probably runs a heck of a lot smoother.
If I am trying to implement this in to a modified MUD based off SMAUGFUSS1.9 and I wanted to begin the process of updating parts to the 'status_messages' (https://github.com/nickgammon/smaugfuss/tree/status_messages), where would you suggest I actually start? Looking at the commits from Git, it doesn't 'look' like all files have been modified within /src but is there a way to be able to iteratively get this started?
I thought of using Nick's version, however there are a lot of changes involved in that one. I wasn't going to jump into that unless I had to. First off is the codebase i'm using doesn't have the std::string defined. So that would be a start I suppose.
I think you compile with g++ rather than gcc to fix that.
I'm working on getting a test-copy of the actual mud I want to be doing this implementation on. I am getting discouraged doing all these changes just on a blank slate and it doesn't mean it will work on the production MUD.
I'm going to take a few days to get setup. I'll be back soon!
Suuupper thank you! I am learning so much. My wife has also pulled out some of her old books and is super interested in this. She doesn't like gaming, but the coding part has sparked her interest.
Right now, I am a bit stuck between a rock and a hard place. I have requested to become a coder for a specific MUD, but they have given me a task to prove myself and it is a bit of a movement backwards. Backwards meaning that the task is to get an old version of a mud working, it's based on SMAUG 1.4, it compiles only in gcc-3.4 and try and implement gmcp to prove how I would do it. With this, I can then get access to the actual MUD codebase.
Like a previous post here, when I get those code snippets implemented I end up with a login error wherein I have to put in the name twice (in MUSHClient) before it will work. It also seems that GMCP is always enabled, even for a client that has no telnet negotiation capability (I'm thinking of GMUD in this case). I was hoping that by default it would be off, and that if someone was using an old client such as gmud (we try to tell them not to) they wouldn't see the code. But so far it still shows up.
So it boils down to the fact that I have it working but there are still a few bugs to iron out and I would like a bit of guidance. Not sure if this forum is the right place to do so, but you guys seem at least active and responsive so I thought I would try here.
How can I get this working on a very old codebase (I can share it if needed as I just downloaded it from afkmuds and can post it to git for ease of collaboration).
Once I can get this shown to work (without the negotiation error) I will then be able to implement it on a MUD that is compiled in g++, and hopefully will be able to use more of the snippets from the github link stated above.
I have enough of my own projects that I don't really want to "collaborate" on this, but I can answer specific questions and give guidance about how to debug code. Though if you want to be a coder for that MUD, these are the kinds of things that you're going to need to be able to figure out.
Quote: I end up with a login error wherein I have to put in the name twice
Add print statements in the server code that display everything being received and sent, so that you can see everything that goes back and forth in the order that it is sent and received. You can't fix what you don't see.
Quote: It also seems that GMCP is always enabled, even for a client that has no telnet negotiation capability (I'm thinking of GMUD in this case). I was hoping that by default it would be off
It should be. Maybe you didn't apply the changes correctly.
... when I get those code snippets implemented I end up with a login error wherein I have to put in the name twice (in MUSHClient) before it will work
This was a thing in the past, and it was because the server wasn't processing IAC ... message properly. For example, the client might be sending some sort of subnegotiation query. Now if you login with your name, and the query response has been automatically sent by the client, and the server hasn't processed it and stripped it out then the IAC stuff becomes part of the player name and it is rejected.
Is there a way to implement (enable/disable) GMCP through similar method through config such as how ANSI or TELNET_GA is turned on and off?
Right now, I'm not savvy enough in C to convert update the whole of read_from_buffer so that IAC will work correctly with MCCP and GMCP simultaneously.
I've been trying to look within act_info and create the link between a gmcp toggle and the ability to enable the messages. Any recommendations on this way ahead?
Would this remove the requirement for auto-telnet-negotiation, or am I just making more work for myself before I get this working correctly?
Alright, so I want to explain how/what I have done and because I do not have a lot of experience with the do's and don'ts of MUDs I hope that you can tell me if I have done a grave error or not.
What I opted for doing at this time due to my limited knowledge in C is to create a GMCP toggle (such as the ANSI/RIP toggle) under the config command.
Now I do understand that this does not work if prompt is turned off. But all I would have to do in this case is declare a void show_status( CHAR_DATA *ch ); and append the right info inside of it.
If possible, please put your code up on github somewhere and then reference code sections by permalinking multiline selections so that we can see all of the context. ( https://help.github.com/en/github/managing-your-work-on-github/creating-a-permanent-link-to-a-code-snippet )
Or maybe just show more context.
Quote: Alright, so I want to explain how/what I have done and because I do not have a lot of experience with the do's and don'ts of MUDs I hope that you can tell me if I have done a grave error or not.
Honestly when it comes to MUDs (servers anyway) I'm an extreme novice. I'm a rather good programmer, though, so maybe I'll be able to follow.
Quote: What I opted for doing at this time due to my limited knowledge in C is to create a GMCP toggle (such as the ANSI/RIP toggle) under the config command.
I'm sure you understand why that's not ideal, but for now if it works then ok.
I assume that it doesn't actually look exactly like this and that this is merely a condensed view of the player_flags enum with all the other values hidden away?
Quote: bool is_gmcp args( ( CHAR_DATA *ch ) );
What is args here? A typical function declaration does not say "args".
Quote: #define MUD_SPECIFIC '\xC9'
Are you using this?
Quote: Does this sound/look like a good way forward?
It sounds like it should work as long as the client doesn't care whether you've negotiated. It's obviously not as good as negotiating with the client automatically.
After all that work, a few months of discussions - I have found out that the mud I am looking to code for has a protocol snippet by Kavir installed. Included in that snippet is (as the readme states):
https://github.com/Xavious/MSDP_Protocol_Handler
Out-of-band communication between mud and client (MSDP);
Extended colours (xterm);
Client detection;
Clickable links;
Unicode support;
MSSP; and
Sound support
Once I showed the snippet of GMCP that I added as an example, he wanted to know if it would conflict with Kavir's snipped. After looking into the snippet, if most certainly would.
When I asked him why he didn't just tell me he added this snippet, he said he didn't know about MSDP and only added the snippet to get xterm colour support! Haha.
So, I've cobbled together a handler and am trying to find out all the diff items I am able to receive from the MUD.
I have learned so much! Not even a waste of time and I wan to thank all of you for it.
I believe I will let this discussion end here for now as my next step I will be towards jumping into MUSHclient plugins.
I just want to point out that GMCP and MSDP do not have to clash at
all. They are both telnet subnegotiation protocols, and the messages
will be distinguished by the protocol number. That is, you could
have:
IAC SB MSDP ... some stuff ... IAC SE
And then:
IAC SB GMCP ... some stuff ... IAC SE
The client will parse them separately and hand them off to the
appropriate plugin, if any.
I agree that they should work very well alongside eachother and even should be able to complement each other.
The implementation of MSDP,as I have been told, followed the SMAUG readme as per: https://github.com/Xavious/MSDP_Protocol_Handler?files=1
I didn't go into the code as I pretty much wanted to start writing plugins since it had a lot of data already available. However, I did see that somewhere in there it said that it currently was not compatible with GMCP as currently, MSDP strips out any other AIC SB...