Webstream,


Venture the Void is a Custom Served App

First some nuts and bolts. In Venture the Void I used a simple client/server model with a custom protocol. The server listens on port NNNN for connections and once those are established the protocol for communication is very simple. And it works. Except:

  1. I need to have my very own special dedicated server because it's a special protocol that runs over TCP. I can't run the VtV server over webhosting.
  2. I didn't really model it in terms of (query, response) pairs.

As a result of 1, I will probably one day have to shut down the server and end online play. Maybe then I'll release the server code? Hmn...?

@p As a result of 2, the client code is a unreliable mishmash of code to interpret responses. The doesn't send responses to a query, it sends commands. So for instance, you might ask it to validate the username "Bono" for a certain game. Call this query "username Bono OK?". The server doesn't really reference this query when it responds. Instead, it just sends a command "Username Bono is OK." This means that the specific modules that use the client/server module have to handle the query/response pairings themselves. It works but it's kind of hideous to look at.

Webstream

What I want instead, for projects going forward, is a "webstream". I want to be able to code the server in PHP and have it run on shared webhosting, which is cheap and super reliable in comparison to my own gameserver. I'll send a query to the webstream, represented by a url, in the form of a string->string mapping. In C++ the query data type looks like this:

typedef map message;

The responses look like this:

struct response {

// what is the current state of the response; updated by the webstream; wait

@p // means it's waiting for the response, ok means the response was recv'd,

@p // and fail means it failed for some reason.

@p enum states { rs_none, rs_wait, rs_ok, rs_fail } state;

@p // this is the data returned by the webserver, assuming rs_ok

@p message data;

@p };


@p What you do then, is query the webstream with your message. You get back a response immediately, but it's state will be set to "wait" until the data is returned. Depending on the context you are using it, you just hold onto this response and each update () cycle check to see if it's got data.

Natural Use Case

This is a lot more natural to use, for example:

... in a function like validate_user (Name)

if (user_validation_response ()) return; // we've already got an outstanding query!

@p webstream::message Q;

@p Q["command"] = "username_valid";

@p Q["username"] = Name;

@p user_validation_response = server_webstream->query (Q);

@p ... somewhere in update ()

@p if (user_validation_response->state == rs_ok) {

@p if (Q["valid"] == "yep") cout << "Username is valid!"

@p else cout << "Username isn't valid!";

@p user_validation_response.clear ();

@p }


@p Voila!

Replay Submitter

I'm actually using this for The Real Texas. Why? I want to automatically submit replays from the open beta, so I can "watch" people playing. When you play the open beta, you agree to have your replays submitted for me to review. This way I can see where people run into problems, and will guarantee Texas to be a ***SMASH HIT***! Well...

@p I could probably have gotten away with something a bit simpler but, ce'st la vie! I've got my reasons. I'd like to use this kind of communications channel for other things, too...

2009-08-21


◀ Back