25 Feb, 2009, Scandum wrote in the 1st comment:
Votes: 0
Continuation of MSSP discussion, the version that will loosely abide the telnet protocol.

Current specs:

Server Commands                                                                                                                                                                       
——————————————————————————–
IAC WILL MSSP indicates the server supports MSSP.

Client Commands
——————————————————————————–
IAC DO MSSP indicates the client is willing to receive server status data.
IAC DONT MSSP indicates the client doesn't support MSSP.

Handshake
——————————————————————————–
When a client connects to a server the server should send IAC WILL MSSP.
The client should respond with either IAC DO MSSP or IAC DONT MSSP.
If the server receives IAC DO MSSP it should respond with: IAC SB MSSP MSSP_VAR
"variable" MSSP_VAL "value" MSSP_VAR "variable" MSSP_VAL "value" IAC SE.

Variables and Values
——————————————————————————–
If a variable is omitted it is assumed the previously reported value for that
value should be used. The "PLAYERS" and "UPTIME" variables should always be
included. Variables and values should only contain alpha numeric characters and
spaces.

MSSP definitions
——————————————————————————–
MSSP 70

MSSP_VAL 1
MSSP_VAR 2


Example MSSP handshake
——————————————————————————–

server - IAC WILL MSSP
client - IAC DO MSSP
server - IAC SB MSSP MSSP_VAR "PLAYERS" MSSP_VAL "52" MSSP_VAR "UPTIME" MSSP_VAL "1234567890" IAC SE


Official MSSP_VAR values:
——————————————————————————–

"CODEBASE" Name of the codebase, eg "Merc"
"CONTACT" Email address for contacting the MUD.
"CREATED" Year the MUD was created.
"HOSTNAME" Current or new hostname. Can be used multiple times if you
have several hostnames, most important hostname last.
"ICON" URL to 32x32 256 color icon in bmp, gif, or jpg format.
"IP" Current or new IP address.
"LANGUAGE" Name of the language used, eg "German" or "English"
"LOCATION" Name of the location of the server, eg "Sweden" or "USA"
"MINIMUM AGE" Current minimum age requirement, use "0" if not applicable.
"NAME" Current or new name of the MUD.
"PORT" Current or new port number. Can be used multiple times if
you have several ports, most important port last.
"PREROGATIVE" Name of the prerogative codebase, eg "DikuMUD" or "Custom"
"WEBSITE" URL to MUD website.

"GENRE" "Adult", "Educational", "Fantasy", "Historical", "Horror",
"Modern", "Science Fiction"
"STATUS" "ALPHA", "CLOSED BETA", "OPEN BETA", "LIVE"
"SUBGENRE" "LASG", "Medieval Fantasy", "World War II", "Frankenstein",
"Cyberpunk", "Dragonlance", "Etc"
"GAMEPLAY" "Adventure", "Educational", "Hack and Slash",
"Player versus Player", "Roleplaying", "Social",
"Strategy"
"GAMESYSTEM" "d20", "D&D", "Etc". Omit or use "Custom" if using a custom
gamesystems.

"PLAYERS" Current number of players online, if multi-playing is
allowed report unique IPs instead.
"UPTIME" Unix time value of the startup time of the MUD.

The following values should use "0" or be omitted if not applicable.
——————————————————————————–

"AREAS" Current number of areas.
"HELPFILES" Current number of help files.
"MOBILES" Current number of unique mobiles.
"OBJECTS" Current number of unique objects.
"SCRIPTLINES" Current number of world related script lines.
"WORLDS" Current number of worlds.

"CLASSES" Number of classes, use "0" if classless.
"LEVELS" Number of levels, use "0" if leveless.
"RACES" Number of races, use "0" if raceless.
"ROOMS" Number of rooms, use "0" if roomless.


The following values should use "1" for yes, and "0" for no.
——————————————————————————–

"ANSI" Supports ANSI colors ?
"MCCP" Supports MCCP ?
"MCP" Supports MCP ?
"MSP" Supports MSP ?
"MXP" Supports MXP ?
"PUEBLO" Supports Pueblo ?
"VT100" Supports VT100 interface ?
"XTERM 256 COLORS" Supports xterm 256 colors ?

"PAY TO PLAY" Pay to play ?
"PAY FOR PERKS" Pay for perks ?

"HIRING BUILDERS" Game is hiring builders ?
"HIRING CODERS" Game is hiring coders ?


Current point of discussion:

How to negotiate an open skill system?
25 Feb, 2009, KaVir wrote in the 2nd comment:
Votes: 0
Scandum said:
How to negotiate an open skill system?

What would you consider an "open skill system"? Pretty much every mud gives you at least a certain degree of choice, but I'm guessing you don't want every mud selecting the option…
26 Feb, 2009, Scandum wrote in the 3rd comment:
Votes: 0
The only codebase that really comes to mind right now is Emlen which doesn't have classes and has a skill tree that is available to all races, though skills tend to have stat requirements that are more easily met by some races than others. Then again, classless will do, and even if you consider your mud classless, seeing how mages are a race in Tolkien's works, the races function as classes if each has their own skill group.

Regarding the "SCRIPTLINES" option, I'm wondering if it'd be better to split those up into:
"MPROGS"             Current number of mobile program lines.
"OPROGS" Current number of object program lines.
"RPROGS" Current number of room program lines.

Or rename as:
"MUDPROGS"           Current number of mud program lines.

I'm not sure how big the emphasis nowadays is on mud progs in muds, specifically area based quests.

Also:
"WORLDS"             Current number of worlds, use "0" if worldless.

I can't readily think of a worldless mud though, but it'd avoid muds accidentally listing themselves as 0 instead of 1.

Also a potential addition:
"SKILLS"             Number of skills, use "0" if skill-less.


And:
"RESETS"             Current number of resets.
26 Feb, 2009, quixadhal wrote in the 4th comment:
Votes: 0
Scandum said:
Regarding the "SCRIPTLINES" option, I'm wondering if it'd be better to split those up into:
"MPROGS"             Current number of mobile program lines.
"OPROGS" Current number of object program lines.
"RPROGS" Current number of room program lines.

Or rename as:
"MUDPROGS"           Current number of mud program lines.

I'm not sure how big the emphasis nowadays is on mud progs in muds, specifically area based quests.


I would strongly suggest changing that from "number of lines" to "number of scripts". We don't need to go back to the Bad Old Days of padding code to inflate line counts. Beyond that…. I guess I'd be inclined to want to brag about the number of scripts + special procedures I had, regardless of how big they were, or which were in the driver vs. in the scripting system.

For example, my MUD has no scripting support of any kind, but I probably have 100 or so special procedures that give particular mobs, or particular types of mobs, more interesting behaviour than normal.
26 Feb, 2009, Scandum wrote in the 5th comment:
Votes: 0
Why pad code if you can simply return mud->total_mprog_lines * 2 ?

I could add "MUDTRIGS" Current number of mud program triggers. I don't think that should include fun specs though.

I wrote a bare bone new_environ parser for the telnet snippet:
int process_sb_new_environ( DESCRIPTOR_DATA *d, unsigned char *src, int srclen )
{
char var[MAX_INPUT_LENGTH], val[MAX_INPUT_LENGTH];
char *pto;
int i;

var[0] = val[0] = 0;

i = 4;

while (i < srclen && src[i] != SE)
{
switch (src[i])
{
case ENV_VAR:
case ENV_USR:
i++;
pto = var;

while (i < srclen && src[i] >= 32 && src[i] != IAC)
{
*pto++ = src[i++];
}
*pto = 0;
break;

case ENV_VAL:
i++;
pto = val;

while (i < srclen && src[i] >= 32 && src[i] != IAC)
{
*pto++ = src[i++];
}
*pto = 0;

if (!strcasecmp(var, "SYSTEMTYPE") && !strcasecmp(val, "WIN32"))
{
RESTRING(d->terminal_type, "WIN32");
SET_BIT(d->comm_flags, COMM_FLAG_ECHO);
}
break;

default:
i++;
break;
}
}
return UMIN(i + 1, srclen);
}
26 Feb, 2009, Scandum wrote in the 6th comment:
Votes: 0
I wrote a function to send MSSP data, which is easy as pie and looks easy enough to maintain. The output is a 659 bytes long string.

It should also be fairly easy for muds to add olc code to edit most of these fields online.

int process_do_mssp( DESCRIPTOR_DATA *d, unsigned char *src, int srclen )
{
char buf[MAX_STRING_LENGTH], tmp[MAX_STRING_LENGTH];

sprintf(buf, "%c%c%c", IAC, SB, TELOPT_MSSP);


sprintf(tmp, "%c%s%c%d" "%c%s%c%d",
MSSP_VAR, "PLAYERS", MSSP_VAL, mud->total_plr,
MSSP_VAR, "UPTIME", MSSP_VAL, mud->boot_time);
strcat(buf, tmp);

sprintf(tmp, "%c%s%c%s" "%c%s%c%s" "%c%s%c%s" "%c%s%c%s" "%c%s%c%s" "%c%s%c%s" "%c%s%c%s" "%c%s%c%s" "%c%s%c%s" "%c%s%c%s" "%c%s%c%s" "%c%s%c%s" "%c%s%c%s",
MSSP_VAR, "CODEBASE", MSSP_VAL, "BubbaMud 1.3",
MSSP_VAR, "CONTACT", MSSP_VAL, "pumpkin@bubba.com",
MSSP_VAR, "CREATED", MSSP_VAL, "1999",
MSSP_VAR, "HOSTNAME", MSSP_VAL, "bubba.com",
MSSP_VAR, "ICON", MSSP_VAL, "http://bubba.com/icon.gif",
MSSP_VAR, "IP", MSSP_VAL, "204.123.20.117",
MSSP_VAR, "LANGUAGE", MSSP_VAL, "English",
MSSP_VAR, "LOCATION", MSSP_VAL, "Sweden",
MSSP_VAR, "MINIMUM AGE", MSSP_VAL, "15",
MSSP_VAR, "NAME", MSSP_VAL, "Bubba Mud",
MSSP_VAR, "PORT", MSSP_VAL, "4321",
MSSP_VAR, "PREROGATIVE", MSSP_VAL, "BobMud",
MSSP_VAR, "WEBSITE", MSSP_VAL, "http://bubba.com");
strcat(buf, tmp);

sprintf(tmp, "%c%s%c%s" "%c%s%c%s" "%c%s%c%s" "%c%s%c%s" "%c%s%c%s",
MSSP_VAR, "GENRE", MSSP_VAL, "Fantasy",
MSSP_VAR, "STATUS", MSSP_VAL, "LIVE",
MSSP_VAR, "SUBGENRE", MSSP_VAL, "Medieval Fantasy",
MSSP_VAR, "GAMEPLAY", MSSP_VAL, "Hack and Slash",
MSSP_VAR, "GAMESYSTEM", MSSP_VAL, "Custom");
strcat(buf, tmp);

sprintf(tmp, "%c%s%c%d" "%c%s%c%d" "%c%s%c%d" "%c%s%c%d" "%c%s%c%d" "%c%s%c%d",
MSSP_VAR, "AREAS", MSSP_VAL, mud->top_area,
MSSP_VAR, "HELPFILES", MSSP_VAL, mud->top_help,
MSSP_VAR, "MOBILES", MSSP_VAL, mud->top_mob_index,
MSSP_VAR, "OBJECTS", MSSP_VAL, mud->top_obj_index,
MSSP_VAR, "ROOMS", MSSP_VAL, mud->top_room,
MSSP_VAR, "RESETS", MSSP_VAL, mud->top_reset);
strcat(buf, tmp);

sprintf(tmp, "%c%s%c%d" "%c%s%c%d",
MSSP_VAR, "MUDPROGS", MSSP_VAL, mud->top_mprog,
MSSP_VAR, "MUDTRIGS", MSSP_VAL, mud->top_mtrig);
strcat(buf, tmp);

sprintf(tmp, "%c%s%c%d" "%c%s%c%d" "%c%s%c%d" "%c%s%c%d" "%c%s%c%d",
MSSP_VAR, "CLASSES", MSSP_VAL, MAX_CLASS,
MSSP_VAR, "LEVELS", MSSP_VAL, MAX_LEVEL,
MSSP_VAR, "RACES", MSSP_VAL, MAX_RACE,
MSSP_VAR, "SKILLS", MSSP_VAL, MAX_SKILL,
MSSP_VAR, "WORLDS", MSSP_VAL, 1);
strcat(buf, tmp);

sprintf(tmp, "%c%s%c%d" "%c%s%c%d" "%c%s%c%d" "%c%s%c%d" "%c%s%c%d" "%c%s%c%d" "%c%s%c%d" "%c%s%c%d",
MSSP_VAR, "ANSI", MSSP_VAL, 1,
MSSP_VAR, "MCCP", MSSP_VAL, 1,
MSSP_VAR, "MCP", MSSP_VAL, 0,
MSSP_VAR, "MSP", MSSP_VAL, 0,
MSSP_VAR, "MXP", MSSP_VAL, 0,
MSSP_VAR, "PUEBLO", MSSP_VAL, 0,
MSSP_VAR, "VT100", MSSP_VAL, 1,
MSSP_VAR, "XTERM 256 COLORS", MSSP_VAL, 1);
strcat(buf, tmp);

sprintf(tmp, "%c%s%c%d" "%c%s%c%d" "%c%s%c%d" "%c%s%c%d",
MSSP_VAR, "PAY TO PLAY", MSSP_VAL, 0,
MSSP_VAR, "PAY FOR PERKS", MSSP_VAL, 0,
MSSP_VAR, "HIRING BUILDERS", MSSP_VAL, 0,
MSSP_VAR, "HIRING CODERS", MSSP_VAL, 0);
strcat(buf, tmp);

sprintf(tmp, "%c%c", IAC, SE);
strcat(buf, tmp);

log_printf("strlen: %d", strlen(buf));

write_to_descriptor(d, buf, 0);

return 3;
}
26 Feb, 2009, Scandum wrote in the 7th comment:
Votes: 0
Anyone in the mood for proofreading 700 lines of code?
26 Feb, 2009, David Haley wrote in the 8th comment:
Votes: 0
Maybe you can find an elite programmer to do it for you. :wink:
26 Feb, 2009, Grimble wrote in the 9th comment:
Votes: 0
Scandum said:
Continuation of MSSP discussion, the version that will loosely abide the telnet protocol.

Here's a YAML example for comparison, with a few additions. If nothing else, it provokes some thinking on how a MUD site will organize all the proposed attributes for display and comparison purposes.

— !mssp-response-begin
version: 1.0
name : BubbaMud
status :
state : Live
uptime : 34d:13h:26m
players: 3
who :
- name: Inky
desc: blah blah blah
- name: Pinky
desc: blah blah blah
- name: Stinky
desc: blah blah blah
motd : >
Double experience for smurfs!
Triple experience for clowns!
description:
genre : Fantasy
subgenre : Cartoon Fantasy
gameplay : Hack-n-Slash
system : Custom
races : 8
classes : 4
levels : 50
skills : 129
language : English
min-age : 16
pay-to-play : false
pay-for-perks: false
server:
location : Bolivia
hostname : bubba.com
address : 204.123.20.117
port : 4321
website : http://bubba.com
icon : http://bubba.com/icon.gif
contact : pumpkin@bubba.com
created : 1999
codebase : BubbaMud 1.3
ancestor : BobMud
hiring builders: true
hiring coders : false
statistics:
worlds : 1
areas : 43
rooms : 3621
mobiles : 2310
items : 1965
programs : 0
scripts : 157
helpfiles: 351
reset : 99
support:
ansi : true
mccp : true
mcp : false
msp : false
mxp : false
pueblo : false
vt100 : false
xterm256: false
comments: >
Friendly and helpful players.
Daily staff-run quests.
— !mssp-response-end
26 Feb, 2009, elanthis wrote in the 10th comment:
Votes: 0
quixadhal said:
I guess I'd be inclined to want to brag about the number of scripts + special procedures I had, regardless of how big they were, or which were in the driver vs. in the scripting system.


The whole stat is (like the vast majority of the rest of these) meaningless anyway. A C MUD is going to have more lines/procedures/whatever than most Ruby MUDs, which might have more function objects than a .NET MUD, which might have more XML data files than a Perl MUD, which might have more regular expressions than a… you get the point. It's a meaningless but fun stat. If you really, really feel like competing on the number of lines of code your MUD has, I'd suggest walking away from the computer and finding a girlfriend.

Many of the other stats just aren't even relevant to many MUDs. I don't code MUDs that have "triggers" in the classical ROM sense, but I do have events and event handlers… but counting those would spit out some quite huge numbers, depending on if you count them per-instance, per-class, per-blueprint, per-zone, per-room, etc…

Scandum said:
I wrote a function to send MSSP data, which is easy as pie and looks easy enough to maintain. The output is a 659 bytes long string.


If that's your idea of easy to maintain, I hope to god you're not a professional programmer writing software other people have to work with.

Try something more like:

void printf_descriptor(DESCRIPTION_DATA* d, const char* fmt, …) {
/* formats and appends to the descriptor's output buffer
after doing IAC byte escaping for solid TELNET compliance.
if your MUD doesn't have a function like this, add one,
because your MUD sucks donkey nuts without it. */
}

void printf_descriptor_noescape(DESCRIPTION_DATA* d, const char* fmt, …) {
/* same as above without the IAC escaping */
}

void send_mssp_string(DESCRIPTION_DATA* d, const char* key, const char* value) {
printf_descriptor(d, "%c%s%c%s", VAR, key, VALUE, value);
}

void send_mssp_int(DESCRIPTION_DATA* d, const char* key, int value) {
printf_descriptor(d, "%c%s%c%s", VAR, key, VALUE, value);
}

int process_do_mssp( DESCRIPTOR_DATA *d, unsigned char *src, int srclen )
{
printf_descriptor_noescape(d, "%c%c%c", IAC, SB, TELOPT_MSSP);

send_mssp_int ("PLAYERS", mud->total_plr);
send_mssp_string ("CODEBASE", "ActuallyReadableMud 0.5");
/* etc */

printf_descriptor_noescape(d, "%c%c", IAC, SE);
}
26 Feb, 2009, Scandum wrote in the 11th comment:
Votes: 0
Quote
If that's your idea of easy to maintain, I hope to god you're not a professional programmer writing software other people have to work with.

It's a snippet so I'm keeping it as short and simple as possible. Besides, I need to leave something to fiddle with for the girlie programmers.
26 Feb, 2009, David Haley wrote in the 12th comment:
Votes: 0
If your idea of 'manly programming' is writing code that's hard to maintain, I'd be awfully happy to be as "girly" as possible.
27 Feb, 2009, quixadhal wrote in the 13th comment:
Votes: 0
Scandum said:
… Bunch of scary, fragile C code deleted by Coding Health Department …


Wow, I didn't think ANYONE still used sprintf to temp buffers in NEW code. That went out of fashion in the 90's. Use varargs already.

Oh, and stuffing all that into a single buffer is inviting an overrun. This isn't multi-threaded happy land… you can use write_to_buffer directly and it won't actually go anywhere until the update loop gets around to flushing the output buffers. If you must use temp buffers, at least use strncpy/snprintf/etc.

Wait…. I think I hear the 90's calling! Yes, they want your Certificate of 1337-Programming Skillz back. :devil:

Seriously though, the reason DikuMUD's are in the mess they're in is because people keep insisting on making snippets for the brain-dead code of the original authors. Enough already! People are sheep, and if you keep throwing bad code around, they'll learn to write that kind of code assuming it HAS to be good, or it wouldn't be used by so many MUD's out there!
27 Feb, 2009, elanthis wrote in the 14th comment:
Votes: 0
Quote
Wow, I didn't think ANYONE still used sprintf to temp buffers in NEW code.


… so how does the sand look in the bottom of that hole your head is stuck in? ;)

Quote
Seriously though, the reason DikuMUD's are in the mess they're in is because people keep insisting on making snippets for the brain-dead code of the original authors.


By Jove, I think he's got it!
27 Feb, 2009, quixadhal wrote in the 15th comment:
Votes: 0
elanthis said:
Quote
Wow, I didn't think ANYONE still used sprintf to temp buffers in NEW code.

… so how does the sand look in the bottom of that hole your head is stuck in? ;)


Kind of dry. ;)
27 Feb, 2009, Tyche wrote in the 16th comment:
Votes: 0
elanthis said:
void printf_descriptor(DESCRIPTION_DATA* d, const char* fmt, …) {
/* formats and appends to the descriptor's output buffer
after doing IAC byte escaping for solid TELNET compliance.
if your MUD doesn't have a function like this, add one,
because your MUD sucks donkey nuts without it. */
}

void printf_descriptor_noescape(DESCRIPTION_DATA* d, const char* fmt, …) {
/* same as above without the IAC escaping */
}

exactly so
but your…
void send_mssp_int(DESCRIPTION_DATA* d, const char* key, int value) {
printf_descriptor(d, "%c%s%c%s", VAR, key, VALUE, value);
}


ought be…
void send_mssp_int(DESCRIPTION_DATA* d, const char* key, int value) {
printf_descriptor(d, "%c%s%c%d", VAR, key, VALUE, value);
}


And the rest is good.
27 Feb, 2009, Scandum wrote in the 17th comment:
Votes: 0
quixadhal said:
Oh, and stuffing all that into a single buffer is inviting an overrun. This isn't multi-threaded happy land… you can use write_to_buffer directly and it won't actually go anywhere until the update loop gets around to flushing the output buffers. If you must use temp buffers, at least use strncpy/snprintf/etc.

It's only like 700 bytes, but don't worry, most people can't count very well past 10. Your example suggestion for printf_descriptor shows you've never dealt with more advanced telopt negotiations before. I'll tune it up a notch though for those poor souls who haven't discovered stdarg.h yet, so they can get as excited about it as you.

quixadhal said:
Seriously though, the reason DikuMUD's are in the mess they're in is because people keep insisting on making snippets for the brain-dead code of the original authors.

Weren't you the one insisting on MSSP for Donkeys because the brain-dead DikuMUD code didn't add a telopt handler?
27 Feb, 2009, quixadhal wrote in the 18th comment:
Votes: 0
Scandum said:
It's only like 700 bytes, but don't worry, most people can't count very well past 10.

Hence my suggestion to either use snprintf (length-limited, since you don't seen to get it), or better yet, use varargs which are far simpler to maintain than countless "%c%s%c%s" cut-and-paste strings.

Scandum said:
Your example suggestion for printf_descriptor shows you've never dealt with more advanced telopt negotiations before.

Ok, I'll inflate your ego a bit more (maybe it'll burst!) and bite. HOW does my suggesting the use of d_printf() imply that I've never dealt with advanced telnet option negotiation? I can't wait to hear this one.

Scandum said:
I'll tune it up a notch though for those poor souls who haven't discovered stdarg.h yet, so they can get as excited about it as you.

Better that, than they get excited about yet another potential segmentation fault from a mistyped printf string or a buffer overrun.

Scandum said:
Weren't you the one insisting on MSSP for Donkeys because the brain-dead DikuMUD code didn't add a telopt handler?

I'm pretty sure it was MSSP for Llamas, but… DikuMUD not handling telnet options wasn't the reason I was suggesting it.
27 Feb, 2009, Scandum wrote in the 19th comment:
Votes: 0
quixadhal said:
Hence my suggestion to either use snprintf (length-limited, since you don't seen to get it), or better yet, use varargs which are far simpler to maintain than countless "%c%s%c%s" cut-and-paste strings.

I see nowhere in the telnet protocol that it's alright to send incomplete negotiations if you run out of buffer space. Can you show me the rfc?

quixadhal said:
Ok, I'll inflate your ego a bit more (maybe it'll burst!) and bite. HOW does my suggesting the use of d_printf() imply that I've never dealt with advanced telnet option negotiation? I can't wait to hear this one.

For starters the silly notion of automatically escaping IAC characters, most muds are English and don't use it unless they're dealing with telnet. Next it's silly to create 2 utility functions that are only used in one function while the advantage to a general purpose function is close to zero. And obviously you didn't think of handling NUL bytes.
27 Feb, 2009, Scandum wrote in the 20th comment:
Votes: 0
Besides eor, terminal type, naws, and new environ, is there anything else that is of particular use to muds or mud clients?
0.0/154