Thursday 11 July 2013

How to dynamically inject debuggable javascript into Chrome Dev Tools

I love Chrome Dev tools, I love how you can insert breakpoints and step through your source code. However, during my escapades in re-writing js source code on the fly for the realtime coding feature of the 3d multiplayer game maker I'm writing (Multi). I found a few interesting pain points.

For the following examples, please imagine that the code in the variable scriptText has been loaded from a cache.


Using Eval
If you use eval, the injected code will not be shown in Chrome Dev Tools.

jstest.html
<html><head></head><body></body>

<script>
var scriptText = "console.log( 'hello' );";
eval( scriptText );
</script>

</html>


Using script.text
If you create a script element then include the javascript code in the text tag for parsing, again, the script will not be shown in Chrome Dev Tools.


jstest.html
<html><head></head><body></body>

<script type="text/javascript" src="jstest.js"></script>

</html>


jstest.js
var head = document.getElementsByTagName( 'head' )[0];
var script = document.createElement( 'script' );
script.type = 'text/javascript';
head.appendChild( script );

var scriptText = "console.log( 'hello' );";
script.text = scriptText;

There is an open bug from 2011 on this issue which I've left a comment towards. So hopefully when this gets fixed, you'll no longer be able to do this trick.


Using Blobs
If you would like to see your code in the sources tab, then you should use the .src field to point to a blob containing your script.


jstest.js
var head = document.getElementsByTagName( 'head' )[0];
var script = document.createElement( 'script' );
script.type = 'text/javascript';
head.appendChild( script );

var scriptText = "console.log( 'hello' );";
script.src = window.URL.createObjectURL( new Blob( [scriptText] ) );



Notes
If you would like to get up to nefarious activities, eval and script.text is a great approach. However, if you're trying to generate some dynamic coding environments, then you're going to run into some problems. While using blobs is great to see the injected script, there are a few issues I'm still working through with them. It seems that if you inject a script to override a class you've previously injected, the interpreter will ignore your new script. So what I've ended up doing in the meantime, is using .src for a server side generated url, which works, but requires server-side setup.

If you have any solutions around this problem, I'd love to hear.

Tuesday 9 July 2013

Multi - In-App Purchase API


In mobile games nowadays, players tend to upgrade or customize their character with the spending of gold coins they collect through gameplay or money. I wanted to make it super-easy for you to be able to introduce your own virtual economy to your games by adding an item shop api to the 3d multiplayer games maker - Multi.

If you add the following line of code
 new SceneItemShop( "Get more coins", "topup_1", true, 1000, 10, 10, function (type, itemCode, value)
 {
      alert( type + " " + value );
 }); 

This screen will appear, asking for either a Facebook like, an in-app purchase or a tweet for payment.

The function SceneItemShop takes in 7 parameters.
title,
itemCode,
isConsumable,
inAppPurhcaseValue,
facebookLikeValue,
tweetValue,
onCompleteFunctionCallback

Allowing you to customise the in-app purchase id, type, value and the values for tweeting and liking (or completely remove them).

Once a payment is made, the function callback is triggered with the type of payment ("facebook","twitter","in-app"), and the itemCode and value you specified for it.

In my use case for World of Fighters, I used that value to top up the coins balance of the player.
new SceneItemShop( "Get more coins", "topup_1", true, 1000, 10, 10, function (type, itemCode, value)
{
      WOF.AddCoins( value, "Thanks +" + value );
}); 

And that's it, the idea is that if you publish the games via the app stores yourself you can use your own custom in-app purchase ids. Or, if you publish the games with Multi, you can use our generic ids and the revenue once cleared will be funneled to your accounts.

Ash :)