Sharing session state in Node.js between your HTTP server and websockets server
At first, sharing your session state between your Node.js HTTP server and websockets server might seem difficult. However, if you're using Express and NowJS (or the technologies they're built on, Connect and Socket.IO, respectively), most of the work has already been done for you -- it's just a matter of connecting the right pieces together. An example follows, written in Coffeescript.
CoffeeScript in Node.js
Here's a couple common development patterns I've come across in Node.JS+CoffeeScript.
Requiring Coffeescripts without compiling
So for the last couple weeks I've been doing Node.js development while using CoffeeScript, but I've been using `coffee -cwb .` in one console (which compiles, watches, and "bare bones"-style on the current directory) while running `node app.js` in another tab. This works okay, but whenever you add a new file you have to restart coffee, and it just seems...noisy. All these extra js files everywhere! Fortunately there's a better way, but it's not really documented.
Before:
require "./my_other_file.js" # compiled from "my_other_file.coffee"
After:
require "coffee-script"
require "./my_other_file"
CoffeeScript registers the .coffee extension automatically. This means no more lingering js files.
Bootstrapping Coffeescripts
Another trick I've discovered applies to times that you have to execute a js file -- `node --debug myapp.js` comes to mind. Well, here you can just make a bootstrap.js file that contains two lines:
require "coffee-script"
require "./myapp"
Now you can `node --debug bootstrap.js` and everything works. Simple stuff.
Loading exports from a module efficiently
Thanks to Coffeescript's destructuring assignments capability, you don't have to write code that looks like this:
MyClass = require("./my_class").MyClass
you can simply write
{MyClass} = require("./my_class")
and it will do the same thing. You can even pull out multiple exports (i.e. {MyClass1,MyClass2}) at a time, though this doesn't come up for me that often.
Conclusion
Hope that was helpful. There are certainly a number of undocumented tricks that you discover when looking at other people's source code
p.s. sorry about the lack of source highlighting; don't feel like embedding gists in here. Code is pretty simple anyway!
Recovering your submitted form data in Chrome
Have you ever submitted form on a website after filling in a lot of text (maybe a comment), only to get an error on the other side? And when you hit back, your nice long response is gone? There's a (sort of easy) way of retrieving it, if you don't stray from the landing page after you submit the form -- at least in Chrome.
1) Wrench icon > Tools > Developer Tools
2) Network tab
3) Click on the network request with the same name as the current page (that matches the URL)
4) Click the Headers tab in the right section of the developer tools
5) Scroll down to the section "Form Data" (you may need to Expand this section by clicking the > arrow)
6) Copy and paste your previous response into somewhere safe (Notepad?) while you attempt to resubmit the form or frame your amazing writing for later.
I'm pretty sure you can do the same thing with Firefox, but it would require you to install Firebug.
ACID Cloud databases to keep an eye on
So far, "database in the cloud" options have been pretty limited. You have Amazon's SimpleDB, which is slow, eventually consistent, and not really a database except in the loosest sense of the word; there's Amazon RDS, which is a managed MySQL instance and scales up, but not out; and of course you can run database server yourself on any of the cloud servers out there (Amazon EC2, Rackspace, GoGrid, Linode, Slicehost, etc etc). But none of these offer one-click scale out ability, which is really the hardest part of database scaling. However, there are a few options cropping up, most of which are in beta.
Quasi-turn-based game design: movement
I'm fiddling around with building an online browser-based game right now, but am having some trouble trying to figure out how and when different units should move (since they can move at different speeds). The game is turn-based, i.e. actions happen in fixed time intervals, but it has real-time elements, since each unit is on its own clock -- actions that happen every 5 minutes for one unit don't necessarily coincide with actions for another unit that also has a 5-minute tick interval. In my mind, these are the requirements:
- No unit should move multiple tiles in a single turn -- in a given turn/tick/whatever, they move at most one tile.
- Some units can move faster than others -- namely, cavalry can move 3x as fast as infantry, for example.
- Units that have varying movements speeds could have the same attack speed -- just because they move faster, doesn't mean they do everything else faster.
- The speed of units can change dynamically -- if they are Haste'd by magic spell, or Slow'd by a bog, then...they do what you'd expect.
So far I've come up with three strategies for how one might implement these in a game.
Ye Olde Key-Value Store: BerkeleyDB
This weekend I explored the possibility of implementing something resembling Redis but on top of an existing, mature database engine. It's a key-value store, it has transactions, it supports locks and concurrent writes, replication, etc. While it ultimately didn't end up panning out (trying to get sets to work efficiently just wasn't working out), it was an interesting learning experience for me familiarizing myself with the Java DPL (Direct Persistence Layer) in BerkeleyDB. (Let that be your warning that there's Java in this post!)
AutoPull: you push, it pulls
So you use GitHub and some compiled language, but not everyone can or wants to compile the source, they just want the artifacts. I made a tiny app that aids in this sort of thing. If you have ever wanted to execute an event in Ruby in response to a push to a repo via GitHub's Post-Receive URL hooks, this is probably a good starting point.
Additionally, it doesn't have to just be used with GitHub (anything that can automatically hit a URL works), and it doesn't even have to be used for pulling down source -- it can send an email or something. Right now I'm using it for HydrateJS -- when I push some new CoffeeScript to GitHub, it automatically pulls and rebuilds the .js file on my server.
HydrateJS: Smarter Javascript Serialization
Finally, here it is: HydrateJS.
It's a library that helps you serialize proper Javascript objects, more than just hash-like objects like JSON.stringify can handle. Anyway, I put a lot of time into the documentation inside the library as well as on the Github Pages link, so check those out! There is also a full suite of specs.
For some of the technical challenges, see my previous post.
Let me know what you think in the comments, and if you're using it, feature requests, etc.
Javascript Serialization
Note: RSS subscribers, I've (finally) enabled summary-only feed entries, so you will have to click through to see the full post.
Have you ever wanted to serialize entire Javascript objects? When I say objects here, I don't mean the simple hashes that you get by saying {foo: "bar"} -- I mean instances of your User, Product, Query, etc prototypal Javascript instances. JSON.stringify gets you part of the way there, but notice this doesn't work:
function Person(){}Person.prototype.greet = function(){ alert("Hi!"); };
var p = new Person();
JSON.parse(JSON.stringify(p)).greet(); // throws Object #<an Object> has no method 'greet' in Chromevar a = {"foo": "bar"};var b = [a, a];b[0] == b[1] // truevar c = JSON.parse(JSON.stringify(b));c[0] == c[1] // false// Step 1: setupfunction Person(){}Person.prototype.greet = function(){ alert("Hi!"); };
var p = new Person();p.name = "Bob";
var object = JSON.parse(JSON.stringify(p));try { object.greet(); // still throws exception} catch(e){ console.log("error calling #greet, %o", e);}
// Step 2: change __proto__object.__proto__ = Person.prototype;
// Step 3: verifyobject.greet(); // now it works!// Step 1: same as before
// Step 2: copy propertiesvar tmp = function(){};tmp.prototype = Person.prototype;var t = new tmp;for (k in object) { t[k] = object[k];}object = t;// not that it matters, but object.constructor == Person now. A good thing, so you can reserialize easily.
// Step 3: verifyobject.greet(); // now it works!object instanceof Person // this is also true
Inconvenient, to be sure -- and to make matters worse, there don't appear to be, well, any libraries out there that handles intelligent serialization of Javascript objects. So that's what I'm writing now (but it's not ready yet). Look for it soon though!
MVC, Games, and a message bus
It seems to me that many approach the use of MVC in games with skepticism, but the more I develop a game in MVC, the more I am reassured in my decision to do so. I operate by the principle that models should absolutely not know about their view(s) (or controllers) -- models should be completely standalone chunks of state and logic that can only reference other models. However, this can present us with a few problems.