Implementing a Multi-Player XMPP Game – Part 2

In my previous blog, I looked at implementing a multi-player set game. Barring any bugs, the engine is working fine. We now turn our attention to writing the client and I’m faced with the following 2 questions:

Firstly what are we going to use to develop the client? What technology, language and platform are we going to implement this in?

Second question: once we’ve written the client, how are we going to get people to install and use it.

The answer I think is quite obvious: the web. By the web, we mean HTML(5), JavaScript and the browser.  So if this is the current thinking, is there a way that we can apply that here?

As you know, Vorpal applications are naturally web in the sense that they are masquerading as web application in a WAR file deployed into a web container. So far we have not really exploited this schizophrenic nature of Vorpal. I have flirted with it in a previous blog on Server Sent Events. It occurred to me that I could I could write the client for the Set game as a web application and deploy it along with server/engine component just like a regular web application.

The next question is how do you write do you write a HTML application that does XMPP? There are lots of JavaScript libraries that does this really well eg. Strophe.js. While these are excellent techniques for developing XMPP application on the web, they strike me as something of an add-on viz. running XMPP inside a browser whose primary conversation of choice is HTTP.

What I was thinking of was is there a XMPP client that has a browser component where the primary protocol is XMPP.  I could not find what I wanted so I wrote a prototype using JavaFX’s WebView. Here’s how it would work:

web_interface_1

A user would login to a XMPP server using this XMPP client (shown above on the left). The XMPP client performs the usual service discovery by sending  disco#info packet over to the server. If any Vorpal component (external component) has web interface enabled, then it’ll reply with the disco#info packet with the following as one of its <feature>

<feature var="urn:web:interface"/>

Web interface is enabled on the component by adding vorpal.component.web.interface property to the xep-0114.xml file. This property points to the URL of the landing page for the component (like the welcome page in web.xml). For example in the Set game we have the following setting

http://someserver:8080/{__context__}/set.html

In the tradition of Vorpal, the {__context__} is a macro for the context root (or application context)  of the WAR. Remember that even though Vorpal is not a web application, it  is packaged in a WAR file for deployment. The application server will treat it as a web application with a valid application context. So {__context__} will be replaced with the application context. The  unfortunate thing is that there is no way for me to use standard Servlet API to find out about the server portion (http://someserver:8080) at startup, so you’ll have to key this part in.

Once the XMPP client discovers that an external component supports web interface, the client will now send a <query xmlns=”urn:web:interface”/> to get the the URL of the interface. The component will now reply with the the URL. Once the client gets the URL, it then sends a HTTP GET to get the web page. See diagram above.

The Web Interface

The client exports a JavaScript object into the web interface call xmppConnection. As the name implies, this is the XMPP connection to the server. The xmppConnection object provides the following methods

xmppConnection.registerHandler(type, JavaScript_method_name) – the first parameter specifies the type of XMPP message that the JavaScript method (second parameter) should handle. The valid values for type are “message”, “presence”, “iq” and “selector”. For the second parameter, you can just enter the name of the JavaScript method name. The name has to be a String (sorry, limitation of the WebView). Say you have the following

xmppConnection.registerHandler("message", "handleMessage")

then whenever the client receives a XMPP message type, handleMessage method will be called. All JavaScript message handler has the following signature

function handlerName(msg)

where the msg is the XMPP message in String. I have written a few utilities to convert the String to XML. One of these is text2xml(). See Set Game example.

Every message send between the client and the external component is marked with the web interface’s name. This allows the XMPP client to know to which view a packet should be routed. In some cases packets arriving from some other sources that are not marked, then XMPP client will let the web view client decide if it should handle the packet. This is the “selector”. The selector behaves exactly like a message handler, has the same signature except that a message selector method returns a boolean telling the client if it wants to handle the message. If it is a true, then message will be routed to the appropriate handler.

xmppConnection.send(pkt) – sends a packet. The send() behaves like Vorpal client. It’ll try to use the default if certain information is missing from the packet eg. if you send a packet without the from, then it’ll use the current user’s name. There are also some macro from Vorpal for that you can use: {__domain__}, {__subdomain__}, {__self__}, {__username__} and {__resource__}.

xmppConnection.send(pkt, JavaScript_method_name) – If you’re sending an IQ packet and you want a specific method to handle the reply, then use this method to send. Otherwise the IQ reply will be routed to a general handler described above.

Finally, if your web page has a JavaScript function initVorpal(), then this function will be called after the HTML document have been loaded viz. if you’re using jQuery, then after $(document).ready(). initVorpal() is used to perform the web interface initialization, most notably registering message handlers. You cannot use xmppConnection until after the document has been loaded.

Set Game Web Interface

So lets look at how we go about writing a web interface by looking at an example. You can get the source here (Multiplayer Set Game). If you expand the zip file, the important files are

  • set.html – this the interface/web view for the set game
  • resources/set.js – most of the behaviour
  • resources/set.css – the stylesheet

I’ve also used

  • jQuery – for handling interaction. As it turns out jQuery is also extremely useful in manipulating and extracting information from XMPP packets
  • jStrophe – for creating XMPP message
  • vorpalutils – a set of homegrown utilities with functions culled from the Internet
    Lets walk through set.js

$(document).ready() – get jQuery to bind the action handlers to the clear, submit and refresh button. The clear button clears the Set selection; submit button sends the 3 cards that you’ve selected to the set game server in the external component and the refresh button, refreshes the 12 cards in your view. We also setup 12 blank cards

initVorpal() – does 2 things here. The first is that we setup the various message handlers.

The second is to constructs a disco#items to the JID of the subcomponent. If you recall, the first part of this describes the set game room’s name is discoverable under the external component’s JID. We set a reply handler for this IQ packet. When the reply returns (handleRoomName(msg)), the client enters the room by sending a presence packet. We get the room’s name using jQuery and then construct a presence packet with jStrophe.

Once we have joined the game room (handlePresence(msg)), we setup the set.html by displaying the number of players and also by sending a get_board message (see first part) to get the 12 cards to fill the view.

I’ve recorded a screencast of this

 

The latest Vorpal along with the experimental XMPP client can be downloaded from here. The Set Multiplayer can be downloaded from here. To run the XMPP client, type bin/lglass . Yeah its a bash script.

Let me know what you think.

%d bloggers like this: