09 Feb, 2010, Tlanuwa wrote in the 1st comment:
Votes: 0
Greetings, all!

I wanted to let you know (in addition to posts at TMC, TMS, and Mudlab) about the MUD lib/codebase I just released.

It's written in PHP and supports traditional telnet connections, but what's really cool (I think, anyway) is the native support for WebSockets, built into the HTML 5 specification. This means that clients in web browsers can connect to the game directly without need for Flash or Java, opening up the realm of possibilities for highly mobile, lightweight browser clients.

I've included one such client in the PHudBase package. It currently only functions in Google Chrome (as Chrome's the only one to support the WebSocket), but it does work. After talking with KaVir at TMC, I'm going to begin work today on a specification for implementing WebSocket communication in existing codebases, which would give your players, of course, the option of using a browser-based client (even on mobile devices, eventually).

The project (with a link to the demo) is hosted at http://www.phudbase.com, which links to the Google Code project where the codebase itself can be found.

I've also added it here (currently pending approval), and I'll do my best to keep current releases in the Code Repository.

I hope you folks will give it a try and let me know what you think or even offer some improvements of your own. This code is so far largely untested in live environments, and while I am very confident in its ability to scale, I just don't know how far or what could be done more efficiently in general.

Look forward to your comments!

- John
09 Feb, 2010, KaVir wrote in the 2nd comment:
Votes: 0
I know other people have put together web-based mud clients (Orrin's FMud springs to mind), but I'm not aware of any that are open source - and if you're looking to compete with browser games, customising the client's graphical interface is clearly going to be high on your list of priorities.

While reading a forum yesterday I saw a post referencing Stonesense - a graphical front-end for Dwarf Fortress. It got me thinking a bit. Simple graphics like that might not compete against the big MMORPGs, but it would definitely suffice on the browser game market - and when it comes to actual gameplay, I think we've got a huge edge over most browser games.

I'm definitely interested in this. The coordinate-based nature of my game would lend itself very well to a proper graphical display, I think.
09 Feb, 2010, Tlanuwa wrote in the 3rd comment:
Votes: 0
The thing about my client demo, even, is that what's done with the data is entirely arbitrary. I've built a pretty standard looking interface, but ANYTHING can be done with this stuff.

For example, in PHudBase itself, if the client is using a WebSocket-based connect, everything is delivered by JSON that the client reacts to through Javascript. It delivers new messages (says, tells, actions in the room) in an array like {"message" => "John said, 'Hi!'"} Map data is delivered as a big 'ole table-based grid in one fell swoop ({"map_data" => "HTML for Table"}). This stuff is simply written to the appropriate enclosing DIV.

Where it gets even more useful is, for example, updating the map with the player's location. In this case, the JSON would look like {"player_loc" => 25} (where "25" is the ID of the room the player is standing in). The client figures out which cell that is (by whatever mechanism) and updates the map, in this case by changing the border to white instead of black.

In this manner, as long as any MUD lib can figure out that the client is using a WebSocket interface (more on that to follow), ANYTHING can be sent to the client for it react to in any way that Javascript (and its many various libraries) is capable of handling.

I envision – as in your example – fully graphical maps, growl-like updates for actions in a room, separate chat windows, hell – the sky (and client-side browser performance) is literally the limit. And with the push towards extremely fast and optimized Javascript handling in modern browsers, the prospects only get better.

The first step is getting the WebSocket specification implemented in existing codebases, me thinks. More on that to follow.

- John
09 Feb, 2010, Orrin wrote in the 4th comment:
Votes: 0
Tlanuwa said:
I'm going to begin work today on a specification for implementing WebSocket communication in existing codebases, which would give your players, of course, the option of using a browser-based client

I think this is really the key to wide adoption of the client (assuming that's your goal of course!) In my experience mud owners want something they can "drop in" to their existing code as far as possible. Even long established and well supported protocols such as MXP suffer because implementation on the server side is not as straightforward as it could be.
09 Feb, 2010, Tlanuwa wrote in the 5th comment:
Votes: 0
What's truly funny is that I spent the last 5 years developing what culminated in the new codebase.

I wrote the client in about 6 hours. :biggrin:

In any case, I think this project is going to appeal to different folks for different reasons. New MUD developers can build a MUD on a very easy to learn platform, current browser game developers can add new depth to their games with real-time communication, and current MUD owners can take the "lessons learned" in adding WebSocket support alongside traditional Telnet and introduce their games to a new audience more receptive to the "pretties."

- John
09 Feb, 2010, KaVir wrote in the 6th comment:
Votes: 0
I'm sure there'll be people interested in the codebase as well - but the client is something of more direct benefit to a larger number of people, as it builds on what they've already got, rather than replacing it.
09 Feb, 2010, Orrin wrote in the 7th comment:
Votes: 0
Yes I didn't mean to imply that the codebase itself wasn't of any interest, I was just following on from KaVir's line of thought about the client really.
09 Feb, 2010, Idealiad wrote in the 8th comment:
Votes: 0
Great work Tlanuwa, I remember you talking about the precursors to this at TMC a while back. Grats!


edit: Just tried it out, looking good! I agree about the client spec – while I personally wouldn't delve into a php mud (sorry ;) ), I'd be very interested in adding client support to the codebase I'm working on.
09 Feb, 2010, Kjwah wrote in the 9th comment:
Votes: 0
Wow, this is really cool. I was playing with it last night(even if I had to install google chrome :p) and I have to say I'm rather impressed with how well the client was behaving.
09 Feb, 2010, Tlanuwa wrote in the 10th comment:
Votes: 0
I appreciate the compliments!

I'll add a thread in the clients forum when I have more on the specs ready to talk about – it's actually not turning out to be that difficult to get a server to behave with WebSockets (I just made it so on my first go round).

- John
11 Feb, 2010, kiasyn wrote in the 11th comment:
Votes: 0
class GameServer extends SocketServer
{
function on_connect($clientID)
{
$cObj = $this->getClientObject($clientID);

// Sleep for just a sec to allow for the client to finish writing (if it's WebSocket) //
usleep(75000);


this doesn't seem too wise, esp in a game expecting multiple people?
11 Feb, 2010, Tlanuwa wrote in the 12th comment:
Votes: 0
You're correct – if I can figure out a way around it, I will.

When you're allowing WebSocket clients – the server recognizes the connection, checks to see whether there's a WebSocket handshake request, and responds accordingly. If there ISN'T a WebSocket request, it reverts the client to Telnet-style connection (different data framing requirements).

The problem arrives when the WebSocket doesn't write the handshake request quickly enough. If you assume – because there's no data (handshake) – that the client is NOT websocket and send the opening game screen, it kills the WebSocket client. I haven't noticed too much trouble so far, though I haven't tested adding a new connection during high-traffic gameplay. That 3/4 of a second may be an ENORMOUS obstruction (and, thinking on it, probably would).

Keep in mind that the code – as provided – is more a demonstration than anything else. If you were to restrict the server to hosting ONLY WebSocket clients or ONLY telnet clients, things become easier to manage, and you wouldn't need that pause.

Let me know if you can think of a better way to handle it though – I don't claim to be an expert on any of this, just a guy who built something I think is pretty neat and useful.

- John
11 Feb, 2010, David Haley wrote in the 13th comment:
Votes: 0
You would have to defer the check. You would stick the sockets into a queue of some sort (like any generic event handling you have, really) and check later on if they've written the handshake yet. If not, assume it's telnet; if so, assume it's WebSocket. The server in the meantime happily chugs along doing its thing.
12 Feb, 2010, Tlanuwa wrote in the 14th comment:
Votes: 0
Hmm. Good idea – I'll get on it.

- John
09 Mar, 2010, Deimos wrote in the 15th comment:
Votes: 0
Extremely interesting. I'm going to keep an eye on this project for sure. One random question I had while sifting through your codebase was why you did this:

//$input = socket_read($this->clients[$i]->socket, 2048, PHP_BINARY_READ);
@socket_recv($this->clients[$i]->socket, $input, 2048, MSG_DONTWAIT);

I've written socket server code in PHP for non-MUD-related purposes, and I don't remember ever having a problem with socket_read(), though admittedly, I relied solely on vanilla Linux telnet during testing. It appears that you tried it the way I would expect, but had to change for some reason?

Anyway, great job. I look forward to seeing your progress.
09 Mar, 2010, David Haley wrote in the 16th comment:
Votes: 0
Just looking at the API docs for the two, it seems that there are two main differences:
- the recv version is non-blocking. (The API docs for socket_read don't make it clear if it's blocking or not, though.)
- the recv version doesn't require allocating a new string buffer, so you can save on performance by reusing the same string buffer after you're done with it the first time.
0.0/16