Today, I continue working on the faye branch of my (fab) game. Having solved a minor mystery last night, I would like remove comet entirely and get through as much replacement with faye as possible.
The best laid plans...
Removing the comet stuff is easy. I start with the client and will rip out the server stuff later. It is easy to identify comet in the client—it is the
<iframe>
:<script type="application/javascript">With that removed what breaks?
$(function() {
// Other initialization...
$('#iframe')[0].src = '/comet_view?player=' + me.id + '&x=' + me.x + '&y=' + me.y;
});
</script>
</head>
<body>
<form id="login" method="get">
<label>Name
<input type="text" name="player">
</label>
<input type="submit" value="Play">
</form>
<div id="room-container"></div>
<iframe id="iframe"></iframe>
</body>
</html>
Not too surprisingly, moving the player about the room does not break. I got that converted over to faye two days ago. What does break is getting other players in the room to show up on my screen. Prior to converting to faye, all of the comet communication went through the PlayerList class on the client side. Now that I am on faye, I do not necessarily have to limit myself to a single pipe for communication. Still, until I know for sure that I have good reason to do otherwise, I will start faye integration in that same class.
To build up the player list in the backend, I need to listen for new player announcements in my fab.js backend:
// Ensure that the faye server has fully established by waiting half aEasy-peasy: I can make use of the
// second before subscribing to channels
setTimeout(function(){
client.subscribe("/players/create", function(player) {
puts("adding player:" + player.id);
add_player(player);
});
}, 500);
add_player
backend function to add players to the data store.Similarly, in the client side, I need to broadcast the new player to the "/players/create" channel. Doing this in the PlayerList initialization seems reasonable:
var PlayerList = function(me, room, options) {Here is where I run into problems. That looks to be a perfectly legitimate faye
// other initialization...
this.faye = new Faye.Client('/faye');
this.faye.publish('/players/create', me);
};
publish()
call, but... nothing happens in the backend. Specifically, that puts
statement never fires:// Ensure that the faye server has fully established by waiting half aThat never fires and querying my local store produces empty results. Ugh. I had such high hopes for progress tonight.
// second before subscribing to channels
setTimeout(function(){
client.subscribe("/players/create", function(player) {
puts("adding player:" + player.id);
add_player(player);
});
}, 500);
My troubleshooting steps include:
- adding a timeout around the publish (it worked on the backend)
- adding console.debug statements around the publish to ensure that statement and beyond was reached (it was)
- publishing to that same channel with a simple string
So what gives?
The
me
object being published is a full-blown object (with a prototype and all), not a simple object literal:this.faye.publish('/players/create', me);There is no way to convert a prototyped object into JSON to be transferred via faye, so things silently fail. Not great, but understandable.
To resolve, I add an
attrs()
method to the Player
class and then publish that:var PlayerList = function(me, room, options) {With that, I finally see activity in the backend. Better still, it is the right kind of activity—the player really is added to the local store. Tomorrow, I will continue replacing comet communication with faye. Hopefully things will go a bit smoother.
// Other class initialization
this.faye = new Faye.Client('/faye');
this.faye.publish('/players/create', me.attrs());
};
Day #184
No comments:
Post a Comment