Tutorials/helloworldJsClient

= JavaScript API Tutorial - Client =

Before we Start
Before you start, make sure you have a Firebase server up and running. If not, please follow the server part first and then come back here.

For the Impatient
If you are impatient or just want to see the finished product, you can go straight here and check the source code. Note that the server has to be up and running on your machine for this to work! You can also download a zip file with the finished example here.

Getting Started
Start by creating an empty HTML file. In the HEAD tag, add these two scripts:

  The first script is the Firebase JavaScript API, and the second defines the Firebase protocol. You can download these files from here:


 * firebase-js-api-1.8.0-CE-javascript.js
 * firebase-protocol-1.8.0-CE-javascript.js

The API is |documented here.

These are the minimal JavaScript you will need provided your browser support WebSockets, which for example Google Chrome does. For browser support without WebSockets you need to enable Comet.

Connecting
The key component in the JavaScript API is called the. To create a connector, you will need to pass in callback functions for packets, lobby packets, logins and status updates. Here's an example with empty callback functions:

connector = new FIREBASE.Connector(packetCallback, lobbyCallback, loginCallback, statusCallback); function lobbyCallback(lobbyPacket) { }

function packetCallback(packet) { }

function loginCallback(status, playerId, name) { }

function statusCallback(status) { console.log("Status received: " + status); } Then, you call the  function to connect to Firebase:

connector.connect("FIREBASE.WebSocketAdapter", 'localhost', '8080', "/socket"); The first parameter says that we want to use web sockets. If you want to target non HTML 5 compliant browsers, we also offer support for Comet, more of which below. The second and third parameters specify the host and the port where Firebase is listening, 8080 is the default port. The last parameter is where the Firebase WebSocket support is mounted on the server.

Try it Out
Run this in Chrome (or any browser that supports web sockets). You should see something like this:



If you open the JavaScript console. You should see two "status received" messages, 1 followed by 2, which means you're 'connecting' and 'connected'. The statuses are:


 * 1 - CONNECTING
 * 2 - CONNECTED
 * 3 - DISCONNECTED
 * 4 - RECONNECTING
 * 5 - RECONNECTED
 * 6 - FAIL
 * 7 - CANCELLED

If the connection fails you will get 1 followed by 3. The API will not try to reconnect automatically. To enable reconnection attempts, say 10, add the following before you try to connect:

FIREBASE.ReconnectStrategy.MAX_ATTEMPTS=10

Logging in
Now, we have successfully connected our client to Firebase. The next step is to log in so that we can start playing. Logging in is a simple matter of calling: connector.login(username, password); If the login is successful, you'll get a callback to the  function with a status param that is "OK".

To try this out, please head over to this link and try login in with abc / 123. It assumes that you have a Firebase started on your localhost.

If you check the source code, you'll se that we handle the login response like this: function loginCallback(status, playerId, name) { console.log("Login status " + status + " playerId " + playerId + " name " + name); if (status === 'OK') { message("Login OK!"); } else { message("Login failed! " + status); } }

Requesting the Lobby List
In order for the player to find a suitable game to play, we need some kind of lobby. To keep things easy, we will just create a list of all available tables. In a real client, you may of course design the lobby in a completely different way, if you have a visible lobby at all. To get a list of available tables, send a subscription request with the gameId you chose when you created your server side logic, like so: connector.lobbySubscribe(1, "/"); The slash means that you want the entire tree of tables, starting from the root. It is possible to partition the lobby into sub nodes when it starts to grow. Firebase will respond with a list of all tables and the API will invoke your  function with a. You can read more about lobby packets in the protocol documentation.

In the finished example, we are using jQuery to construct a grid that shows all the tables. Check the source code and follow the link to helloworld.js to see the code.

If you try this and your lobby is empty, double check that the gameId that you are requesting the lobby for corresponds with the game-definition-id in the game.xml for your server logic module (under ).

Joining a Game
When a player chooses to join a specific game, you call the  function. If you don't care which seat you get, just pass -1. If all goes well, you will get a  via the packetCallback function with an OK status. You will also receive s for all seated players. Again, see the protocol documentation for more information.

Sending an Action
Now we are ready to send our first game action! The JavaScript API provides three methods for doing this:



To keep it simple we will be using the first method in this tutorial. However, for better efficiency and speed we recommend using a binary protocol, which the second function helps you with. The last function will send a packet that has been generated by the Styx tool, which is a tool for generating a binary protocol from an XML definition.

In this case, all we need to do to shoot a message to the server is: The first parameter is playerId, but can be ignored because Firebase will use the playerId you are logged in as (to avoid cheating). The second parameter is the tableId you are playing at and the third is the text you want to send.

The  method will first create a byte array from the string and then base 64 encode it before sending it to Firebase. The reason for the base 64 encoding is that this is currently recommended when transferring binary data over a WebSocket.

Receiving Data
The way we have written the  method on the server side, all it will do is echo the incoming message to all players. This means that the player (and any other player at this table) will receive a  via the   function. To parse the data, we need to first base 64 decode the contents, and then convert it from binary to a string. Like so: function handleGameTransport(packet) { // We need to first base64 decode the message. var byteArray = FIREBASE.ByteArray.fromBase64String(packet.gamedata); // And then convert the byte array to a string. var message = utf8.fromByteArray(byteArray); gameMessage("Player " + packet.pid + " sent: " + message); } Here's a screenshot of the client, showing an incoming message:



Adding Comet Support
To catch browsers that don't have WebSocket support, you can use Comet. Firebase comes with an implementation of CometD, which uses ordinary HTTP calls and will work on almost any device. First you need to add the jQuery or Dojo framework. This is a requirement, but you can chose which framework to use, this tutorial will assume jQuery.



You need to add the CometD JavaScripts (which you can find in the in the CometD download):

          

(Adding all of the above is a bit cumbersome, if you have the distribution, you can create a minified version and include that instead.)

Having done that, you need to add the jQuery binding for CometD (also found in the above download):



Now, given all the above Scripts, using Comet instead of WebSockets is trivial. Simply replace the "connect" line with the following:

connector.connect("FIREBASE.CometdAdapter", 'localhost', '8080', "/cometd", false, function { return $.cometd });

The last two arguments are for HTTPS (false for this tutorial, we're not using it) and an access to the bound CometD instance (via jQuery). And that's all!

Minor note: If you run from the file system you will get warnings as Firebase is checking for cross domain accesss, and the file system sets 'Origin' to 'null', which is not allowed.

What you may want to do now is to first check if WebSockets are supported, and then fall back on Comet if it is not. A simple way of doing this might be:

if(window.WebSocket && window.WebSocket.prototype && window.WebSocket.prototype.send) { connector.connect("FIREBASE.WebSocketAdapter", 'localhost', '8080', "/socket"); } else { connector.connect("FIREBASE.CometdAdapter", 'localhost', '8080', "/cometd", false, function { return $.cometd }); } The above checks if the WebSpocket object is properly defined by checking for its prototype and "send" method.