ID:109225
 
Keywords: bmud, byond
So I had the nostalgic urge the other day to start whipping up a MUD. I was looking around on MUDConnector, trying to see if it was still active in some shape, size or form. Much to my not-surprise, almost no one posts on the forums anymore, neither do they post on other would-be websites such as mudfiles.com.

I downloaded a few different sources (vampire wars, masters of hatred and socketmud) and played around a bit with them, and then remembered I had something on here.

After spending a few minutes trying to find the download link (wtb maintained package, please?? Its not as if there is a daily release...), and spending an hour trodding through my own code to figure out how to even log in properly, I finally got it working. I had two conclusions at the end of that session:

1) If you insist on implementing a module system that loads modules so you can segment code into just that, you may want to mention, in documentation, the 'bare minimum' modules. That way you won't spend 35 minutes trying to figure out why nothing comes up until you figure out the config file format and what modules to load; after which you spend 20 minutes more trying to figure out why nothing happens in-game, until you realize that the parser is a module too and should be loaded if you want things, well, parsed.

2) Some of the BYOND bugs related to telnet that originally left the project in the dark back then seem to be gone. (Hit enter to continue) seems to resolve itself for telnet clients, both standard linux telnet and two different MUD clients; ANSI escape-codes no longer seem to count towards the automatic word-wrap (Although it still pains me that one exists).

It still remains to be seen whether characters still idle out by themselves after a time period (Why would you assume someone would want this, with no way to control its behavior?), and whether input() can cause the VM to leak memory.

Fun fun.
I've recently found an interesting bug myself.

/*
escape codes preceeding whitespace (at the beginning of a string only? not verified) result in said whitespace going poof.
------------------------------------------------------------------------
example:
"[ANSI_YELLOW] blah blah blah"
when sent to a telnet client will draw:
"[ANSI_YELLOW]blah blah blah"

To combat this, I have set all outgoing messages to be colored via
HTML and HTML only. BYOND automatically converts some messages to
escape sequence, but I think it only functions like so:

"if there is red, send the default red. if there is blue, send the
default blue. if there is red and blue, send the default magenta. etc..."

that means we'll be suffering only dark colors in telnet for a little
while.
------------------------------------------------------------------------
*/


Funnily enough, the problem does not exist when you let BYOND filter out HTML color stuff. I never reported it, because I wanted to make sure it was an error on my part.
Oof, thats pretty bad. I'm not really willing to settle for only dark colors. Grah :( Luckily, with the exception of 'floating' boxes with ASCII art or similar, I can't envision a situation where I'd need [COLOR_CODE](whitespace)(text). Even then, you can do (whitespace)[COLOR_CODE](text) instead. Or am I misunderstanding?

This may be related to the fix that discounts ANSI color codes as going towards the wordwrap; maybe it greedily swallows spaces and anything valid for a color code, until it meets something else. That reminds me: Why is there still a *forced* wordwrap? This has been a *CLIENT* preference in telnet clients for OVER 10 years.
I also managed to encounter a BYOND Bug error earlier today while connecting with the MUDlet MUD client:

'BUG: TELNET SB incomplete', or similar.
Interesting...

Mudlet is probably a lot more strict with its stuff than say zMUD or MUSHclient.

Can you recreate the bug?
I can't envision a situation where I'd need [COLOR_CODE](whitespace)(text).

One example: "{R[mb_pad("some string", 20, PAD_CENTER)]{x"

Here, {R is eventually replaced with the appropriate character to show a bright red, based on the client type. In the case of telnet, \[1;31m. You can see the issue, I think. The only way to resolve it is to stick the color code onto the front of the string in the padding function, which is kind of an inconvenience...

I've also encountered some other non-color-related errors with whitespace at the beginning of strings disappearing (like it used to), but I haven't worked on my project in a couple of weeks, and would need to check it out a bit before saying anything about that.

Also, doesn't it stop forcing wordwrap after the client sends input?
Keeth wrote:
The only way to resolve it is to stick the color code onto the front of the string in the padding function, which is kind of an inconvenience...

Yeah, thats what I meant - Its an inconvenience, but only using dark colors is worse. Regardless, it should be flagged as a bug - Did you?

I've also encountered some other non-color-related errors with whitespace at the beginning of strings disappearing (like it used to), but I haven't worked on my project in a couple of weeks, and would need to check it out a bit before saying anything about that.

Thats no fun :( Let me know if you find out anything.

Also, doesn't it stop forcing wordwrap after the client sends input?

I'm not sure what you mean?

As to reproducing the TELNET SB bug: I can't seem to reliably reproduce it yet, but it happens on occasion when creating a character (So a set of input() as command_text one after the other). It truncates the input by one character.

One other annoyance with input() I've found is that, even doing two input() in a row, you can end up sending text 'past' the second input() if you send text fast enough. That really shouldn't happen.

More and more, I'm convincing myself input() really never should be used in a telnet MUD on BYOND :(
I haven't reported it as a bug just yet. I'll probably do it later this afternoon.

I'm not sure what you mean?

In the past it auto-wrapped at 80 characters, I do believe, until the client sent input... I guess they bumped it up to 101? Sending input doesn't do anything about it, though... I guess I've just never tried to send a single line of 100 characters before... I always tend to format each line of my descriptions and stuff to be about 60-70ish characters long at max, as a convenience for users of simpler mud clients, like normal old telnet.

One other annoyance with input() I've found is that, even doing two input() in a row, you can end up sending text 'past' the second input() if you send text fast enough. That really shouldn't happen.

http://www.byond.com/members/ BYONDHelp?command=view_tracker_issue&tracker_issue=2586

Also, don't even think about sending multiple lines in the same tick. Some mud clients do this for you, using special separators like ;. If you do this, it'll catch the first one, and the rest will be completely uncaught.

In a client like zMUD, you can literally just hold enter and it'll all be caught. In a DS client that is connected to a remote world (IE: not running a DS client that is its own world), you can make a macro for a command and hold it, and it'll all be caught.

In the case of running a world in DS, it'll probably catch every other command, or maybe every 3rd command, at best.
Keeth wrote:
One other annoyance with input() I've found is that, even doing two input() in a row, you can end up sending text 'past' the second input() if you send text fast enough. That really shouldn't happen.

http://www.byond.com/members/ BYONDHelp?command=view_tracker_issue&tracker_issue=2586

Also, don't even think about sending multiple lines in the same tick. Some mud clients do this for you, using special separators like ;. If you do this, it'll catch the first one, and the rest will be completely uncaught.

Right; Thats the problem. input() will catch the first one, and then client/Command() will receive the second line before it registers that a second input() was there.

In retrospect, there isn't much to do about it. You shouldn't be using both client/Command() and input(), and between the two Command() is the one to go for.

I just have to wrap my head around using a stateful parser instead :s
I've tried a couple of methods myself. My first attempt involved sending ALL input to a queue, where an outside loop would grab input as it became available for command processing. If a special state was set, the command processing would halt, and another function would halt whatever thread was asking for the input until some was available, then it would return it.

On my current project, I decided I wanted as much control as possible (things like being able to jump between input states, switching back and forth between the "login" menu and "playing") so I don't try to do any thread halting stuff anymore. I could design the game around the threading stuff, but I didn't want to deal with it... so I'm using a pretty standard state machine for input processing. But I'm in the beginning phase for it.

I actually tried to create a Java-like Thread object that functioned similarly, but I ran into some issues with that, and that's why I switched to the current setup.
I haven't started work on a replacement for input(), but I'm guessing the easiest way is to write a very basic state machine that, if a datum *target* is set, sends input to the target (which is responsible for spawning and waiting for the user input itself) and if not sends it to the command parser.

I'll make a little blog entry on it if I get something up and running.
It looks like BYOND sends an IAC message on connection...

IAC WONT IAC DO

I don't believe this is a valid IAC message, but I could be wrong... I'm pretty certain that WONT and DO must precede a character representing the protocol to be negotiated, where as here we have IAC WONT IAC (which is most likely not correct), then DO.

I wrote a simple client application to connect to a BYOND world, and after sending a couple hundred lines of input, I can't find any reason it would be sending an error (as there is no SB message sent, from what I can see). The only reason I could imagine is some lingering thing with the IAC WONT IAC DO message.
I did a little bit of testing and filed a bug report. (color/escape issue)

You can check it out here if you want.

Also, I did some more testing...
BYOND seems to be sending something like...

255 252 1 (IAC WONT something)
255 253 31 (IAC DO "negotiate window size")

Then after the hit enter to continue screen, it seems to instantly send IAC DO "negotiate window size" again, followed by the ANSI "clear page" code.

I'll do some more testing later.