Monkeypatching the CraftStudio Web player

This morning I released an update to the CraftStudio Web player adding sound support and fixing various other stuff. You can start CraftStudio to get the latest version and read more about the update. This isn’t the main subject of this blog post though!

Have you found yourself wishing a particular feature was available in CraftStudio?

For instance, maybe you’d like to make HTTP requests to download some dynamic data to display in your game or integrate with some Web API.

Sadly, there’s no HTTP request API currently in CraftStudio (this is something that I intend to address at some point). Well I’ve got good news: if you’ve got some Web development chops then instead of waiting for me to get there, you can expose your own functions in the CraftStudio Web player!

Monkeypatching to the rescue!

It’s a bit of a hack, but here’s how it works: we’re going to monkeypatch the Web player’s API setup function to inject our own API functions.

Export a dummy CraftStudio project for the Web and open player.html. We’ll be adding code just below this line:

<script src="CSPlayer.js"></script>

Insert the following:

<script>
var actualSetupAPI = CSPlayer.ScriptAPI.prototype.SetupAPI;

CSPlayer.ScriptAPI.prototype.SetupAPI = function(callback) {
  var _this = this;
  actualSetupAPI.apply( _this, [ function() {
    // Expose our custom API to CraftStudio scripts
    _this.lua.str["HTTP"] = lua_newtable2({
      "GetJSON": function(url, successCallback) {
        $.get( url, null, function(data) {
          successCallback( lua_newtable2(data) );
        }, "json" );
      }
    });
    callback();
  } ] );
}
</script>

This little script injects a new global variable named HTTP with a GetJSON function which uses jQuery to make a GET request and return the result as a Lua table to our script.

Using our shiny new API

Back to CraftStudio, let’s create a little script to use our new API:

function Behavior:Update()
  if CS.Input.WasButtonJustPressed( "Fire" ) then
    print( "Click!" )

    -- CraftStudio doesn't provide any HTTP APIs right now
    -- Good news is: we can monkeypatch features in the Web player!

    if HTTP ~= nil then
      print( "Making a request..." )
      -- Let's make an HTTP get request...
      HTTP.GetJSON( "https://graph.facebook.com/820499731", function(data)
        print( "Hi " .. data.first_name .. "!" )
      end )
    else
      print( "Boo. No HTTP module. We're probably running inside of CraftStudio rather than the Web player." )
    end
  end
end

Add this script as a component on a dummy object in a dummy scene, re-export while preserving your custom player.html file and voilà! You can now make HTTP calls from within CraftStudio.

Admittedly, this involves quite a bit of trickery and isn’t exactly the most elegant solution.

But still, it’s a cool little hack that should allow the more adventurous CraftStudians to do nifty stuff like integrating with APIs such as GameJolt, Kongregate, Newgrounds, Facebook or CoinWare until CraftStudio provides native support for such things.