├── README.md ├── file ├── LICENCE.txt ├── bin │ ├── newgroundsio.js │ └── newgroundsio.min.js ├── ng_medals.html ├── ng_medals.js ├── ng_medals.p8 └── src │ ├── core.js │ ├── events.js │ ├── include │ └── aes.js │ ├── license.txt │ ├── model │ ├── call.js │ ├── debug.js │ ├── error.js │ ├── input.js │ ├── medal.js │ ├── output.js │ ├── result.js │ ├── score.js │ ├── scoreboard.js │ ├── session.js │ ├── user.js │ └── usericons.js │ ├── namespaces.js │ ├── sessionloader.js │ └── validators.js └── images ├── fig1.png ├── fig2.png ├── fig3.PNG ├── fig4.PNG ├── fig5.PNG ├── fig6.PNG ├── fig7.PNG └── ng_medals.p8.png /README.md: -------------------------------------------------------------------------------- 1 | Hello ! Today, I’m going to try to teach you something : how to use the Newgrounds Medals system with your PICO-8 game. 2 | 3 | /!\ I'm going to explain you how I've setup medals for my game, Rush. I haven't used all the possibilities of the medals, therefore the system can be improved. But as a basic integration, this is very good! /!\ 4 | 5 | ## What do you need? 6 | 7 | - PICO-8 (of course) 8 | - The [Newgrounds.io Javascript API](https://bitbucket.org/newgrounds/newgrounds.io-for-javascript-html5) 9 | - A text editor (For this guide, I'm going to use [Brackets](http://brackets.io/)) 10 | - Your own account on Newgrounds 11 | 12 | ## Setup 13 | 14 | The first things you have to do is to download the Newgrounds.io Javascript API ([Download here](https://bitbucket.org/newgrounds/newgrounds.io-for-javascript-html5/downloads/)). Open the `.zip` and drag the `src` and the `bin` in a new folder. 15 | 16 | ![](images/fig1.png) 17 | *__Fig 1 :__ The content of the `.zip` you download* 18 | 19 | 20 | ![](images/fig2.png) 21 | *__Fig 2 :__ The file you need to drag on your new folder* 22 | 23 | ## On PICO-8 24 | 25 | You have your game on PICO-8. For the transfer, we are going to use the GPIO system (if you don't know how it's working, you can read the [Sean explanation](https://www.lexaloffle.com/bbs/?tid=3909), but don't worry, I'm going to explain how to simply use it here). 26 | 27 | So in PICO-8 you can use 128 pin which can get a value between 0 and 255. Normaly it's for the Raspberry Pi and the Pocketchip, but you can get it too thanks to Javascript! You have to poke value on the adress from 0x5f80 to 0x6000. We are going to setup two small functions, that way it'll be easier to peek and poke the value. 28 | 29 | ```Lua 30 | function set_pin(pin,value) --pin : pin between 0 and 127 31 | poke(0x5f80+pin, value) --value : the value between 0 and 255 32 | end 33 | 34 | function get_pin(pin) --pin : the pin do you want to get the value 35 | return peek(0x5f80+pin) 36 | end 37 | ``` 38 | 39 | The methode I've use is not the best one or the most optimised but it's working and it's not that bad! 40 | 41 | We are going to setup a second function, with this function you can ask to the API to unlock a new function. We are going to use the pin "0" to say we need to unlock a medals, and the pin 1 to say which medal we want to unlock. I use 2 pin because if you want to create another system, like a sharable score, you can change the value of the pin 0 so you don't have conflicts with that. 42 | 43 | So the function is very simple : 44 | 45 | ```Lua 46 | function unlock_medals(num) --num : the number of the medals we are 47 | set_pin(0,1) --going to combine the number and the medals 48 | set_pin(1,num) --ID with Javascript 49 | end 50 | ``` 51 | 52 | Now, we are going to setup the Unlock Medals sound and visual effect in PICO-8. We are going to use the pin 0 for the trigger and the pin 1 for the number of the medals. 53 | 54 | Let us setup a function to detect that. You have to put it in the `_update` function. 55 | 56 | ```Lua 57 | function test_medals() 58 | if get_pin(0)==2 then --trigger 59 | set_pin(0,0) --reset the trigger 60 | med_num=get_pin(1) --get the number of the medals 61 | med_tic=0 --set a tic, for the display function 62 | 63 | if med_num==1 then --if you had more medals, add it here 64 | med_inf={122,"easy finisher"} 65 | --[[ 66 | elseif med_num==2 then 67 | med_inf={sprite to display, "name of the medals"} ]] 68 | end 69 | end 70 | end 71 | ``` 72 | 73 | The `med_inf` variable contains the information about the medals, this information can be use in the next function, the `draw_medals` function. You have to put this function in the last line of `_draw` function of PICO-8. 74 | 75 | ```Lua 76 | function draw_medals() 77 | if med_num!=0 then --trigger 78 | med_tic+=1 --add 1 to the tic value 79 | rectfill(-1,116,10+#med_inf[2]*4,128,0) --draw a black background 80 | rect(-1,116,10+#med_inf[2]*4,128,5) --draw a gray square 81 | spr(med_inf[1],1,118) --draw the sprite who represent the medals 82 | print(med_inf[2],10,120,5) --print the medals' name 83 | 84 | if med_tic>=70 then --reset. you can change the duration here 85 | med_num=0 --reset 86 | end 87 | end 88 | end 89 | ``` 90 | 91 | We just need a last function, to "init" the variable. Put it in the `_init` function. 92 | 93 | ```Lua 94 | function init_medals() 95 | med_num=0 96 | med_tin=0 97 | end 98 | ``` 99 | 100 | For the test, we are going to setup a basic interaction to test the medals. When you press the ❎ button, we unlock a new medal. So all of our PICO-8 Code is : 101 | 102 | ``` 103 | --basic medals tutorial 104 | --by bigaston 105 | 106 | function _init() 107 | init_medals() 108 | end 109 | 110 | function _update() 111 | if btnp(❎) then 112 | unlock_medals(1) 113 | end 114 | end 115 | 116 | function _draw() 117 | cls() 118 | print("press ❎ to unlock medals",1,1,7) 119 | draw_medals() 120 | end 121 | 122 | function set_pin(pin,value) 123 | poke(0x5f80+pin, value) 124 | end 125 | 126 | function get_pin(pin) 127 | return peek(0x5f80+pin) 128 | end 129 | 130 | function unlock_medals(num) 131 | set_pin(0,1) 132 | set_pin(1,num) 133 | end 134 | 135 | function init_medals() 136 | med_num=0 137 | med_tin=0 138 | end 139 | 140 | function test_medals() 141 | if get_pin(0)==2 then 142 | set_pin(0,0) 143 | med_num=get_pin(1) 144 | med_tic=0 145 | 146 | if med_num==1 then 147 | med_inf={1, "yeah"} 148 | end 149 | end 150 | end 151 | 152 | function draw_medals() 153 | if med_num!=0 then 154 | med_tic+=1 155 | rectfill(-1,116,10+#med_inf[2]*4,128,0) 156 | rect(-1,116,10+#med_inf[2]*4,128,5) 157 | spr(med_inf[1],1,118) 158 | print(med_inf[2],10,120,5) 159 | 160 | if med_tic>=70 then 161 | med_num=0 162 | end 163 | end 164 | end 165 | ``` 166 | 167 | Just copy this sprite in the first place of your sprite sheet : 168 | 169 | ``` 170 | [gfx]0808555555555bbbbbb55bbbbbb55bbbb7b55b7b7bb55bb7bbb55bbbbbb555555555[/gfx] 171 | ``` 172 | 173 | Or, you can just download the cartridge : 174 | ![](images/ng_medals.p8.png) 175 | 176 | To finish, just export the game in HTML5. After that, just copy your `.html` and `.js` file and it's done! You have finished the job with PICO-8! 177 | 178 | ## On Newgrounds 179 | 180 | Now we are going to setup the game on Newgrounds to have access to the API. Create a new games [here](https://www.newgrounds.com/projects/games). 181 | 182 | Now you have to complete the information about the game (as the picture, the description, ...). We will upload the games files later. 183 | 184 | Jump to the **API Tool** line (on the left). Read and aprove the text. Now just click on `Click here to use the Newgrounds.io API for this game!` 185 | 186 | ![](images/fig3.PNG) 187 | *__Fig 3 :__ Where you have to click* 188 | 189 | You have to get the App ID and the Base64 Encryption Keys. 190 | 191 | ![](images/fig4.PNG) 192 | *__Fig 4 :__ The App ID* 193 | 194 | ![](images/fig5.PNG) 195 | *__Fig 5 :__ The Encryption Keys* 196 | 197 | Note it somewhere, you'll need it later. Now we are going to setup the medals. We have already made one medals in PICO-8 so we are going to add it on Newgrounds. 198 | 199 | Go to `Medals` line under the `API Tools` line. Here you can setup the medals. 200 | 201 | Add a new medals. 202 | 203 | ![](images/fig6.PNG) 204 | *__Fig 6 :__ Some medals information* 205 | 206 | Click on Submit and take the Medals ID. If you want the medals to appear on the game's page, you have to unlock it once with your game. 207 | 208 | ![](images/fig7.PNG) 209 | *__Fig 7 :__ The Medal ID* 210 | 211 | We have finish with Newgrounds for now. Now we need to use a text editor to edit the `.html` of the game. 212 | 213 | ## On the Text Editor 214 | 215 | So! We have to edit the `.html` export by PICO-8. I'm going to share with you some premade code. You can find the Newgrounds part on the [bitbucket page of the Javascript API](https://bitbucket.org/newgrounds/newgrounds.io-for-javascript-html5). 216 | 217 | We need to import the `newgroundsio.js` file. Add a line on the `` part of your document. And you need the JQuery module. 218 | 219 | ```Javascript 220 | 221 | 222 | ``` 223 | 224 | Now I'm going to share you a premade code that you can use to enable medals. You can read the comment to understand how it's work. You just have to put this code on `` 225 | 226 | ```Javascript 227 | var pico8_gpio = new Array(128); //Enable the PICO-8 GPIO 228 | 229 | var ngio = new Newgrounds.io.core("NG App ID", "Base64 Encryption Keys"); 230 | 231 | function onLoggedIn() { 232 | console.log("Welcome " + ngio.user.name + "!"); 233 | } 234 | 235 | function onLoginFailed() { 236 | console.log("There was a problem logging in: " . ngio.login_error.message ); 237 | } 238 | 239 | function onLoginCancelled() { 240 | console.log("The user cancelled the login."); 241 | } 242 | 243 | /* 244 | * Before we do anything, we need to get a valid Passport session. If the player 245 | * has previously logged in and selected 'remember me', we may have a valid session 246 | * already saved locally. 247 | */ 248 | function initSession() { 249 | ngio.getValidSession(function() { 250 | if (ngio.user) { 251 | /* 252 | * If we have a saved session, and it has not expired, 253 | * we will also have a user object we can access. 254 | * We can go ahead and run our onLoggedIn handler here. 255 | */ 256 | onLoggedIn(); 257 | } else { 258 | /* 259 | * If we didn't have a saved session, or it has expired 260 | * we should have been given a new one at this point. 261 | * This is where you would draw a 'sign in' button and 262 | * have it execute the following requestLogin function. 263 | */ 264 | requestLogin(); 265 | } 266 | }); 267 | } 268 | 269 | function requestLogin() { 270 | ngio.requestLogin(onLoggedIn, onLoginFailed, onLoginCancelled); 271 | /* you should also draw a 'cancel login' buton here */ 272 | } 273 | 274 | function cancelLogin() { 275 | /* 276 | * This cancels the login request made in the previous function. 277 | * This will also trigger your onLoginCancelled callback. 278 | */ 279 | ngio.cancelLoginRequest(); 280 | } 281 | 282 | function logOut() { 283 | ngio.logOut(function() { 284 | /* 285 | * Because we have to log the player out on the server, you will want 286 | * to handle any post-logout stuff in this function, wich fires after 287 | * the server has responded. 288 | */ 289 | }); 290 | } 291 | 292 | initSession(); 293 | 294 | /* vars to record any medals and scoreboards that get loaded */ 295 | var medals, scoreboards; 296 | 297 | /* handle loaded medals */ 298 | function onMedalsLoaded(result) { 299 | if (result.success) medals = result.medals; 300 | } 301 | 302 | /* load our medals and scoreboards from the server */ 303 | ngio.queueComponent("Medal.getList", {}, onMedalsLoaded); 304 | ngio.executeQueue(); 305 | 306 | /* You could use this function to draw the medal notification on-screen */ 307 | function onMedalUnlocked(medal) { 308 | console.log('MEDAL GET:', medal.name); 309 | if (medal.id==your medal ID) { 310 | pico8_gpio[1]=Your medals number (on PICO-8); 311 | } 312 | pico8_gpio[0]=2; //Enable the Trigger on PICO-8 313 | } 314 | 315 | function UnlockMedal(medal_id) { 316 | /* unlock the medal from the server */ 317 | ngio.callComponent('Medal.unlock', {id:medal_id}, function(result) { 318 | 319 | if (result.success) onMedalUnlocked(result.medal); 320 | 321 | }); 322 | } 323 | 324 | (function main(){ 325 | if (pico8_gpio[0]==1) { 326 | pico8_gpio[0]=0; 327 | if (pico8_gpio[1]==Your Medal Number) { 328 | UnlockMedal(Your Medal ID); 329 | } 330 | } 331 | }()) // call immediately to start the loop 332 | ``` 333 | 334 | Now you just have to rename your HTML file to `index.html`, create a ZIP Archive with your `.js` file, your `.html` file, the `bin` and `src` folder. Just upload the whole archive on Newgrounds and it's done! Just unlock the medals to validate it. 335 | 336 | If you like this tutorial, you can [follow me on Twitter](https://twitter.com/Bigaston), visit [my Itch page](https://bigaston.itch.io). 337 | 338 | [![ko-fi](https://www.ko-fi.com/img/donate_sm.png)](https://ko-fi.com/A0A05WS6) 339 | 340 | ## Sources and thanks 341 | 342 | - The Sean explanation of the PICO-8 GPIO ([here](https://www.lexaloffle.com/bbs/?tid=3909)) 343 | - The Newgrounds.io Javascript API, for the Javascript code ([here](https://bitbucket.org/newgrounds/newgrounds.io-for-javascript-html5)) 344 | 345 | 346 | -------------------------------------------------------------------------------- /file/LICENCE.txt: -------------------------------------------------------------------------------- 1 | Newgrounds.IO Licence 2 | 3 | Copyright (c) 2015 Newgrounds Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /file/bin/newgroundsio.min.js: -------------------------------------------------------------------------------- 1 | "undefined"==typeof Newgrounds&&(Newgrounds={}),Newgrounds.io={GATEWAY_URI:"//newgrounds.io/gateway_v3.php"},Newgrounds.io.events={},Newgrounds.io.call_validators={},Newgrounds.io.model={checkStrictValue:function(e,t,r,n,o,s,i){if("mixed"==n)return!0 2 | if(null===r||"undefined"==typeof r)return!0 3 | if(n&&r.constructor===n)return!0 4 | if(n==Boolean&&r.constructor===Number)return!0 5 | if(o&&r.constructor===Newgrounds.io.model[o])return!0 6 | if(r.constructor===Array&&(s||i)){for(var u=0;u=0?(this._event_listeners[e].splice(r,1),!0):!1}},removeAllEventListeners:function(e){if("undefined"==typeof this._event_listeners[e])return 0 13 | var t=this._event_listeners[e].length 14 | return this._event_listeners[e]=[],t},dispatchEvent:function(e){var t,r=!1 15 | for(var n in Newgrounds.io.events)if(e.constructor===Newgrounds.io.events[n]){r=!0 16 | break}if(!r)throw new Error("Unsupported event object") 17 | if("undefined"==typeof this._event_listeners[e.type])return!1 18 | for(var o=0;o value for '"+n+"' in '"+e+"' data, got "+typeof t[n]) 53 | continue}for(s=[],o=0;o0)for(r=0;ro;o++)t[n+o>>>2]|=(r[o>>>2]>>>24-8*(o%4)&255)<<24-8*((n+o)%4) 234 | else if(65535o;o+=4)t[n+o>>>2]=r[o>>>2] 235 | else t.push.apply(t,r) 236 | return this.sigBytes+=e,this},clamp:function(){var t=this.words,r=this.sigBytes 237 | t[r>>>2]&=4294967295<<32-8*(r%4),t.length=e.ceil(r/4)},clone:function(){var e=s.clone.call(this) 238 | return e.words=this.words.slice(0),e},random:function(t){for(var r=[],n=0;t>n;n+=4)r.push(4294967296*e.random()|0) 239 | return new i.init(r,t)}}),u=r.enc={},l=u.Hex={stringify:function(e){var t=e.words 240 | e=e.sigBytes 241 | for(var r=[],n=0;e>n;n++){var o=t[n>>>2]>>>24-8*(n%4)&255 242 | r.push((o>>>4).toString(16)),r.push((15&o).toString(16))}return r.join("")},parse:function(e){for(var t=e.length,r=[],n=0;t>n;n+=2)r[n>>>3]|=parseInt(e.substr(n,2),16)<<24-4*(n%8) 243 | return new i.init(r,t/2)}},a=u.Latin1={stringify:function(e){var t=e.words 244 | e=e.sigBytes 245 | for(var r=[],n=0;e>n;n++)r.push(String.fromCharCode(t[n>>>2]>>>24-8*(n%4)&255)) 246 | return r.join("")},parse:function(e){for(var t=e.length,r=[],n=0;t>n;n++)r[n>>>2]|=(255&e.charCodeAt(n))<<24-8*(n%4) 247 | return new i.init(r,t)}},c=u.Utf8={stringify:function(e){try{return decodeURIComponent(escape(a.stringify(e)))}catch(t){throw Error("Malformed UTF-8 data")}},parse:function(e){return a.parse(unescape(encodeURIComponent(e)))}},d=n.BufferedBlockAlgorithm=s.extend({reset:function(){this._data=new i.init,this._nDataBytes=0},_append:function(e){"string"==typeof e&&(e=c.parse(e)),this._data.concat(e),this._nDataBytes+=e.sigBytes},_process:function(t){var r=this._data,n=r.words,o=r.sigBytes,s=this.blockSize,u=o/(4*s),u=t?e.ceil(u):e.max((0|u)-this._minBufferSize,0) 248 | if(t=u*s,o=e.min(4*t,o),t){for(var l=0;t>l;l+=s)this._doProcessBlock(n,l) 249 | l=n.splice(0,t),r.sigBytes-=o}return new i.init(l,o)},clone:function(){var e=s.clone.call(this) 250 | return e._data=this._data.clone(),e},_minBufferSize:0}) 251 | n.Hasher=d.extend({cfg:s.extend(),init:function(e){this.cfg=this.cfg.extend(e),this.reset()},reset:function(){d.reset.call(this),this._doReset()},update:function(e){return this._append(e),this._process(),this},finalize:function(e){return e&&this._append(e),this._doFinalize()},blockSize:16,_createHelper:function(e){return function(t,r){return new e.init(r).finalize(t)}},_createHmacHelper:function(e){return function(t,r){return new p.HMAC.init(e,r).finalize(t)}}}) 252 | var p=r.algo={} 253 | return r}(Math) 254 | !function(){var e=CryptoJS,t=e.lib.WordArray 255 | e.enc.Base64={stringify:function(e){var t=e.words,r=e.sigBytes,n=this._map 256 | e.clamp(),e=[] 257 | for(var o=0;r>o;o+=3)for(var s=(t[o>>>2]>>>24-8*(o%4)&255)<<16|(t[o+1>>>2]>>>24-8*((o+1)%4)&255)<<8|t[o+2>>>2]>>>24-8*((o+2)%4)&255,i=0;4>i&&r>o+.75*i;i++)e.push(n.charAt(s>>>6*(3-i)&63)) 258 | if(t=n.charAt(64))for(;e.length%4;)e.push(t) 259 | return e.join("")},parse:function(e){var r=e.length,n=this._map,o=n.charAt(64) 260 | o&&(o=e.indexOf(o),-1!=o&&(r=o)) 261 | for(var o=[],s=0,i=0;r>i;i++)if(i%4){var u=n.indexOf(e.charAt(i-1))<<2*(i%4),l=n.indexOf(e.charAt(i))>>>6-2*(i%4) 262 | o[s>>>2]|=(u|l)<<24-8*(s%4),s++}return t.create(o,s)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}}(),function(e){function t(e,t,r,n,o,s,i){return e=e+(t&r|~t&n)+o+i,(e<>>32-s)+t}function r(e,t,r,n,o,s,i){return e=e+(t&n|r&~n)+o+i,(e<>>32-s)+t}function n(e,t,r,n,o,s,i){return e=e+(t^r^n)+o+i,(e<>>32-s)+t}function o(e,t,r,n,o,s,i){return e=e+(r^(t|~n))+o+i,(e<>>32-s)+t}for(var s=CryptoJS,i=s.lib,u=i.WordArray,l=i.Hasher,i=s.algo,a=[],c=0;64>c;c++)a[c]=4294967296*e.abs(e.sin(c+1))|0 263 | i=i.MD5=l.extend({_doReset:function(){this._hash=new u.init([1732584193,4023233417,2562383102,271733878])},_doProcessBlock:function(e,s){for(var i=0;16>i;i++){var u=s+i,l=e[u] 264 | e[u]=16711935&(l<<8|l>>>24)|4278255360&(l<<24|l>>>8)}var i=this._hash.words,u=e[s+0],l=e[s+1],c=e[s+2],d=e[s+3],p=e[s+4],_=e[s+5],f=e[s+6],h=e[s+7],m=e[s+8],g=e[s+9],y=e[s+10],v=e[s+11],w=e[s+12],N=e[s+13],S=e[s+14],b=e[s+15],E=i[0],O=i[1],k=i[2],j=i[3],E=t(E,O,k,j,u,7,a[0]),j=t(j,E,O,k,l,12,a[1]),k=t(k,j,E,O,c,17,a[2]),O=t(O,k,j,E,d,22,a[3]),E=t(E,O,k,j,p,7,a[4]),j=t(j,E,O,k,_,12,a[5]),k=t(k,j,E,O,f,17,a[6]),O=t(O,k,j,E,h,22,a[7]),E=t(E,O,k,j,m,7,a[8]),j=t(j,E,O,k,g,12,a[9]),k=t(k,j,E,O,y,17,a[10]),O=t(O,k,j,E,v,22,a[11]),E=t(E,O,k,j,w,7,a[12]),j=t(j,E,O,k,N,12,a[13]),k=t(k,j,E,O,S,17,a[14]),O=t(O,k,j,E,b,22,a[15]),E=r(E,O,k,j,l,5,a[16]),j=r(j,E,O,k,f,9,a[17]),k=r(k,j,E,O,v,14,a[18]),O=r(O,k,j,E,u,20,a[19]),E=r(E,O,k,j,_,5,a[20]),j=r(j,E,O,k,y,9,a[21]),k=r(k,j,E,O,b,14,a[22]),O=r(O,k,j,E,p,20,a[23]),E=r(E,O,k,j,g,5,a[24]),j=r(j,E,O,k,S,9,a[25]),k=r(k,j,E,O,d,14,a[26]),O=r(O,k,j,E,m,20,a[27]),E=r(E,O,k,j,N,5,a[28]),j=r(j,E,O,k,c,9,a[29]),k=r(k,j,E,O,h,14,a[30]),O=r(O,k,j,E,w,20,a[31]),E=n(E,O,k,j,_,4,a[32]),j=n(j,E,O,k,m,11,a[33]),k=n(k,j,E,O,v,16,a[34]),O=n(O,k,j,E,S,23,a[35]),E=n(E,O,k,j,l,4,a[36]),j=n(j,E,O,k,p,11,a[37]),k=n(k,j,E,O,h,16,a[38]),O=n(O,k,j,E,y,23,a[39]),E=n(E,O,k,j,N,4,a[40]),j=n(j,E,O,k,u,11,a[41]),k=n(k,j,E,O,d,16,a[42]),O=n(O,k,j,E,f,23,a[43]),E=n(E,O,k,j,g,4,a[44]),j=n(j,E,O,k,w,11,a[45]),k=n(k,j,E,O,b,16,a[46]),O=n(O,k,j,E,c,23,a[47]),E=o(E,O,k,j,u,6,a[48]),j=o(j,E,O,k,h,10,a[49]),k=o(k,j,E,O,S,15,a[50]),O=o(O,k,j,E,_,21,a[51]),E=o(E,O,k,j,w,6,a[52]),j=o(j,E,O,k,d,10,a[53]),k=o(k,j,E,O,y,15,a[54]),O=o(O,k,j,E,l,21,a[55]),E=o(E,O,k,j,m,6,a[56]),j=o(j,E,O,k,b,10,a[57]),k=o(k,j,E,O,f,15,a[58]),O=o(O,k,j,E,N,21,a[59]),E=o(E,O,k,j,p,6,a[60]),j=o(j,E,O,k,v,10,a[61]),k=o(k,j,E,O,c,15,a[62]),O=o(O,k,j,E,g,21,a[63]) 265 | i[0]=i[0]+E|0,i[1]=i[1]+O|0,i[2]=i[2]+k|0,i[3]=i[3]+j|0},_doFinalize:function(){var t=this._data,r=t.words,n=8*this._nDataBytes,o=8*t.sigBytes 266 | r[o>>>5]|=128<<24-o%32 267 | var s=e.floor(n/4294967296) 268 | for(r[(o+64>>>9<<4)+15]=16711935&(s<<8|s>>>24)|4278255360&(s<<24|s>>>8),r[(o+64>>>9<<4)+14]=16711935&(n<<8|n>>>24)|4278255360&(n<<24|n>>>8),t.sigBytes=4*(r.length+1),this._process(),t=this._hash,r=t.words,n=0;4>n;n++)o=r[n],r[n]=16711935&(o<<8|o>>>24)|4278255360&(o<<24|o>>>8) 269 | return t},clone:function(){var e=l.clone.call(this) 270 | return e._hash=this._hash.clone(),e}}),s.MD5=l._createHelper(i),s.HmacMD5=l._createHmacHelper(i)}(Math),function(){var e=CryptoJS,t=e.lib,r=t.Base,n=t.WordArray,t=e.algo,o=t.EvpKDF=r.extend({cfg:r.extend({keySize:4,hasher:t.MD5,iterations:1}),init:function(e){this.cfg=this.cfg.extend(e)},compute:function(e,t){for(var r=this.cfg,o=r.hasher.create(),s=n.create(),i=s.words,u=r.keySize,r=r.iterations;i.lengtha;a++)l=o.finalize(l),o.reset() 274 | s.concat(l)}return s.sigBytes=4*u,s}}) 275 | e.EvpKDF=function(e,t,r){return o.create(r).compute(e,t)}}(),CryptoJS.lib.Cipher||function(e){var t=CryptoJS,r=t.lib,n=r.Base,o=r.WordArray,s=r.BufferedBlockAlgorithm,i=t.enc.Base64,u=t.algo.EvpKDF,l=r.Cipher=s.extend({cfg:n.extend(),createEncryptor:function(e,t){return this.create(this._ENC_XFORM_MODE,e,t)},createDecryptor:function(e,t){return this.create(this._DEC_XFORM_MODE,e,t)},init:function(e,t,r){this.cfg=this.cfg.extend(r),this._xformMode=e,this._key=t,this.reset()},reset:function(){s.reset.call(this),this._doReset()},process:function(e){return this._append(e),this._process()},finalize:function(e){return e&&this._append(e),this._doFinalize()},keySize:4,ivSize:4,_ENC_XFORM_MODE:1,_DEC_XFORM_MODE:2,_createHelper:function(e){return{encrypt:function(t,r,n){return("string"==typeof r?f:_).encrypt(e,t,r,n)},decrypt:function(t,r,n){return("string"==typeof r?f:_).decrypt(e,t,r,n)}}}}) 276 | r.StreamCipher=l.extend({_doFinalize:function(){return this._process(!0)},blockSize:1}) 277 | var a=t.mode={},c=function(t,r,n){var o=this._iv 278 | o?this._iv=e:o=this._prevBlock 279 | for(var s=0;n>s;s++)t[r+s]^=o[s]},d=(r.BlockCipherMode=n.extend({createEncryptor:function(e,t){return this.Encryptor.create(e,t)},createDecryptor:function(e,t){return this.Decryptor.create(e,t)},init:function(e,t){this._cipher=e,this._iv=t}})).extend() 280 | d.Encryptor=d.extend({processBlock:function(e,t){var r=this._cipher,n=r.blockSize 281 | c.call(this,e,t,n),r.encryptBlock(e,t),this._prevBlock=e.slice(t,t+n)}}),d.Decryptor=d.extend({processBlock:function(e,t){var r=this._cipher,n=r.blockSize,o=e.slice(t,t+n) 282 | r.decryptBlock(e,t),c.call(this,e,t,n),this._prevBlock=o}}),a=a.CBC=d,d=(t.pad={}).Pkcs7={pad:function(e,t){for(var r=4*t,r=r-e.sigBytes%r,n=r<<24|r<<16|r<<8|r,s=[],i=0;r>i;i+=4)s.push(n) 283 | r=o.create(s,r),e.concat(r)},unpad:function(e){e.sigBytes-=255&e.words[e.sigBytes-1>>>2]}},r.BlockCipher=l.extend({cfg:l.cfg.extend({mode:a,padding:d}),reset:function(){l.reset.call(this) 284 | var e=this.cfg,t=e.iv,e=e.mode 285 | if(this._xformMode==this._ENC_XFORM_MODE)var r=e.createEncryptor 286 | else r=e.createDecryptor,this._minBufferSize=1 287 | this._mode=r.call(e,this,t&&t.words)},_doProcessBlock:function(e,t){this._mode.processBlock(e,t)},_doFinalize:function(){var e=this.cfg.padding 288 | if(this._xformMode==this._ENC_XFORM_MODE){e.pad(this._data,this.blockSize) 289 | var t=this._process(!0)}else t=this._process(!0),e.unpad(t) 290 | return t},blockSize:4}) 291 | var p=r.CipherParams=n.extend({init:function(e){this.mixIn(e)},toString:function(e){return(e||this.formatter).stringify(this)}}),a=(t.format={}).OpenSSL={stringify:function(e){var t=e.ciphertext 292 | return e=e.salt,(e?o.create([1398893684,1701076831]).concat(e).concat(t):t).toString(i)},parse:function(e){e=i.parse(e) 293 | var t=e.words 294 | if(1398893684==t[0]&&1701076831==t[1]){var r=o.create(t.slice(2,4)) 295 | t.splice(0,4),e.sigBytes-=16}return p.create({ciphertext:e,salt:r})}},_=r.SerializableCipher=n.extend({cfg:n.extend({format:a}),encrypt:function(e,t,r,n){n=this.cfg.extend(n) 296 | var o=e.createEncryptor(r,n) 297 | return t=o.finalize(t),o=o.cfg,p.create({ciphertext:t,key:r,iv:o.iv,algorithm:e,mode:o.mode,padding:o.padding,blockSize:e.blockSize,formatter:n.format})},decrypt:function(e,t,r,n){return n=this.cfg.extend(n),t=this._parse(t,n.format),e.createDecryptor(r,n).finalize(t.ciphertext)},_parse:function(e,t){return"string"==typeof e?t.parse(e,this):e}}),t=(t.kdf={}).OpenSSL={execute:function(e,t,r,n){return n||(n=o.random(8)),e=u.create({keySize:t+r}).compute(e,n),r=o.create(e.words.slice(t),4*r),e.sigBytes=4*t,p.create({key:e,iv:r,salt:n})}},f=r.PasswordBasedCipher=_.extend({cfg:_.cfg.extend({kdf:t}),encrypt:function(e,t,r,n){return n=this.cfg.extend(n),r=n.kdf.execute(r,e.keySize,e.ivSize),n.iv=r.iv,e=_.encrypt.call(this,e,t,r.key,n),e.mixIn(r),e},decrypt:function(e,t,r,n){return n=this.cfg.extend(n),t=this._parse(t,n.format),r=n.kdf.execute(r,e.keySize,e.ivSize,t.salt),n.iv=r.iv,_.decrypt.call(this,e,t,r.key,n)}})}(),function(){for(var e=CryptoJS,t=e.lib.BlockCipher,r=e.algo,n=[],o=[],s=[],i=[],u=[],l=[],a=[],c=[],d=[],p=[],_=[],f=0;256>f;f++)_[f]=128>f?f<<1:f<<1^283 298 | for(var h=0,m=0,f=0;256>f;f++){var g=m^m<<1^m<<2^m<<3^m<<4,g=g>>>8^255&g^99 299 | n[h]=g,o[g]=h 300 | var y=_[h],v=_[y],w=_[v],N=257*_[g]^16843008*g 301 | s[h]=N<<24|N>>>8,i[h]=N<<16|N>>>16,u[h]=N<<8|N>>>24,l[h]=N,N=16843009*w^65537*v^257*y^16843008*h,a[g]=N<<24|N>>>8,c[g]=N<<16|N>>>16,d[g]=N<<8|N>>>24,p[g]=N,h?(h=y^_[_[_[w^y]]],m^=_[_[m]]):h=m=1}var S=[0,1,2,4,8,16,32,64,128,27,54],r=r.AES=t.extend({_doReset:function(){for(var e=this._key,t=e.words,r=e.sigBytes/4,e=4*((this._nRounds=r+6)+1),o=this._keySchedule=[],s=0;e>s;s++)if(r>s)o[s]=t[s] 302 | else{var i=o[s-1] 303 | s%r?r>6&&4==s%r&&(i=n[i>>>24]<<24|n[i>>>16&255]<<16|n[i>>>8&255]<<8|n[255&i]):(i=i<<8|i>>>24,i=n[i>>>24]<<24|n[i>>>16&255]<<16|n[i>>>8&255]<<8|n[255&i],i^=S[s/r|0]<<24),o[s]=o[s-r]^i}for(t=this._invKeySchedule=[],r=0;e>r;r++)s=e-r,i=r%4?o[s]:o[s-4],t[r]=4>r||4>=s?i:a[n[i>>>24]]^c[n[i>>>16&255]]^d[n[i>>>8&255]]^p[n[255&i]]},encryptBlock:function(e,t){this._doCryptBlock(e,t,this._keySchedule,s,i,u,l,n)},decryptBlock:function(e,t){var r=e[t+1] 304 | e[t+1]=e[t+3],e[t+3]=r,this._doCryptBlock(e,t,this._invKeySchedule,a,c,d,p,o),r=e[t+1],e[t+1]=e[t+3],e[t+3]=r},_doCryptBlock:function(e,t,r,n,o,s,i,u){for(var l=this._nRounds,a=e[t]^r[0],c=e[t+1]^r[1],d=e[t+2]^r[2],p=e[t+3]^r[3],_=4,f=1;l>f;f++)var h=n[a>>>24]^o[c>>>16&255]^s[d>>>8&255]^i[255&p]^r[_++],m=n[c>>>24]^o[d>>>16&255]^s[p>>>8&255]^i[255&a]^r[_++],g=n[d>>>24]^o[p>>>16&255]^s[a>>>8&255]^i[255&c]^r[_++],p=n[p>>>24]^o[a>>>16&255]^s[c>>>8&255]^i[255&d]^r[_++],a=h,c=m,d=g 305 | h=(u[a>>>24]<<24|u[c>>>16&255]<<16|u[d>>>8&255]<<8|u[255&p])^r[_++],m=(u[c>>>24]<<24|u[d>>>16&255]<<16|u[p>>>8&255]<<8|u[255&a])^r[_++],g=(u[d>>>24]<<24|u[p>>>16&255]<<16|u[a>>>8&255]<<8|u[255&c])^r[_++],p=(u[p>>>24]<<24|u[a>>>16&255]<<16|u[c>>>8&255]<<8|u[255&d])^r[_++],e[t]=h,e[t+1]=m,e[t+2]=g,e[t+3]=p},keySize:8}) 306 | e.AES=t._createHelper(r)}() 307 | -------------------------------------------------------------------------------- /file/ng_medals.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | PICO-8 Cartridge 6 | 7 | 8 | 9 | 10 | 54 | 55 | 56 | 57 | 58 | 59 |


60 | 61 |
62 | 63 | 64 | 65 | 194 | 195 | 196 | 197 | 215 | 216 |
217 | 218 |
219 | 220 | Reset 221 | 222 | Reset
223 | 224 |
225 | 226 | Pause 227 | 228 | Pause
229 |
230 | Fullscreen 231 | 232 | Fullscreen
233 |
234 | Toggle Sound 235 | 236 | Sound
237 | 241 | 242 |
243 | 244 |
245 |

246 | 247 | 248 | 249 | 250 | -------------------------------------------------------------------------------- /file/ng_medals.p8: -------------------------------------------------------------------------------- 1 | pico-8 cartridge // http://www.pico-8.com 2 | version 16 3 | __lua__ 4 | --basic medals tutorial 5 | --by bigaston 6 | 7 | function _init() 8 | init_medals() 9 | end 10 | 11 | function _update() 12 | if btnp(❎) then 13 | unlock_medals(1) 14 | end 15 | end 16 | 17 | function _draw() 18 | cls() 19 | print("press ❎ to unlock medals",1,1,7) 20 | draw_medals() 21 | end 22 | 23 | function set_pin(pin,value) 24 | poke(0x5f80+pin, value) 25 | end 26 | 27 | function get_pin(pin) 28 | return peek(0x5f80+pin) 29 | end 30 | 31 | function unlock_medals(num) 32 | set_pin(0,1) 33 | set_pin(1,num) 34 | end 35 | 36 | function init_medals() 37 | med_num=0 38 | med_tin=0 39 | end 40 | 41 | function test_medals() 42 | if get_pin(0)==2 then 43 | set_pin(0,0) 44 | med_num=get_pin(1) 45 | med_tic=0 46 | 47 | if med_num==1 then 48 | med_inf={1, "yeah"} 49 | end 50 | end 51 | end 52 | 53 | function draw_medals() 54 | if med_num!=0 then 55 | med_tic+=1 56 | rectfill(-1,116,10+#med_inf[2]*4,128,0) 57 | rect(-1,116,10+#med_inf[2]*4,128,5) 58 | spr(med_inf[1],1,118) 59 | print(med_inf[2],10,120,5) 60 | 61 | if med_tic>=70 then 62 | med_num=0 63 | end 64 | end 65 | end 66 | __gfx__ 67 | 00000000555555550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 68 | 000000005bbbbbb50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 69 | 007007005bbbbbb50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 70 | 000770005bbbb7b50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 71 | 000770005b7b7bb50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 72 | 007007005bb7bbb50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 73 | 000000005bbbbbb50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 74 | 00000000555555550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 75 | __label__ 76 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 77 | 07770777077700770077000000777770000007770077000007070770070000770077070700000777077707700777070000770000000000000000000000000000 78 | 07070707070007000700000007707077000000700707000007070707070007070700070700000777070007070707070007000000000000000000000000000000 79 | 07770770077007770777000007770777000000700707000007070707070007070700077000000707077007070777070007770000000000000000000000000000 80 | 07000707070000070007000007707077000000700707000007070707070007070700070700000707070007070707070000070000000000000000000000000000 81 | 07000707077707700770000000777770000000700770000000770707077707700077070700000707077707770707077707700000000000000000000000000000 82 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 83 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 84 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 85 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 86 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 87 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 88 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 89 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 90 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 91 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 92 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 93 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 94 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 95 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 96 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 97 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 98 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 99 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 100 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 101 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 102 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 103 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 104 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 105 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 106 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 107 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 108 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 109 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 110 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 111 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 112 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 113 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 114 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 115 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 116 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 117 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 118 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 119 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 120 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 121 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 122 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 123 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 124 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 125 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 126 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 127 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 128 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 129 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 130 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 131 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 132 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 133 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 134 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 135 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 136 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 137 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 138 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 139 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 140 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 141 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 142 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 143 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 144 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 145 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 146 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 147 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 148 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 149 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 150 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 151 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 152 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 153 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 154 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 155 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 156 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 157 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 158 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 159 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 160 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 161 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 162 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 163 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 164 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 165 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 166 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 167 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 168 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 169 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 170 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 171 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 172 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 173 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 174 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 175 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 176 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 177 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 178 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 179 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 180 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 181 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 182 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 183 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 184 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 185 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 186 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 187 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 188 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 189 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 190 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 191 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 192 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 193 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 194 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 195 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 196 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 197 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 198 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 199 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 200 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 201 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 202 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 203 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 204 | 205 | -------------------------------------------------------------------------------- /file/src/core.js: -------------------------------------------------------------------------------- 1 | /* start core.js */ 2 | 3 | /** 4 | * Handles making calls and processing results to the Newgrounds.io server 5 | * @constructor 6 | * @memberof Newgrounds.io 7 | * @property {boolean} debug - Set to true to operate in debug mode 8 | * @property {string} app_id - Your unique app ID (found in the 'API Tools' section of your Newgrounds.com project). 9 | * @property {Newgrounds.io.model.user} user - A user associated with an active session id. Use getSessionLoader to load. 10 | * @property {string} session_id - A user session id (acquire with App.startSession call). 11 | * @param {string} [app_id] - Your unique app ID (found in the 'API Tools' section of your Newgrounds.com project). 12 | * @param {string} [aes_key] - Your AES-128 encryption key (in Base64 format). 13 | */ 14 | Newgrounds.io.core = function(app_id, aes_key) { 15 | 16 | var _app_id; 17 | var _session_id; 18 | var _user; 19 | var _debug; 20 | var ngio = this; 21 | var _aes_key; 22 | 23 | var _urlhelper = new Newgrounds.io.urlHelper(); 24 | if (_urlhelper.getRequestQueryParam("ngio_session_id")) { 25 | _session_id = _urlhelper.getRequestQueryParam("ngio_session_id"); 26 | } 27 | 28 | Object.defineProperty(this, 'app_id', { 29 | get: function() { 30 | return _app_id; 31 | } 32 | }); 33 | 34 | Object.defineProperty(this, 'user', { 35 | get: function() { 36 | return this.getCurrentUser(); 37 | } 38 | }); 39 | 40 | Object.defineProperty(this, 'session_id', { 41 | set: function(id) { 42 | if (id && typeof(id) != 'string') throw new Error("'session_id' must be a string value."); 43 | _session_id = id ? id : null; 44 | }, 45 | get: function() { 46 | return _session_id ? _session_id : null; 47 | } 48 | }); 49 | 50 | Object.defineProperty(this, 'debug', { 51 | set: function(debug) { 52 | _debug = debug ? true:false; 53 | }, 54 | get: function() { 55 | return _debug; 56 | } 57 | }); 58 | 59 | if (!app_id) throw new Error("Missing required 'app_id' in Newgrounds.io.core constructor"); 60 | if (typeof(app_id) != 'string') throw new Error("'app_id' must be a string value in Newgrounds.io.core constructor"); 61 | _app_id = app_id; 62 | 63 | if (aes_key) _aes_key = CryptoJS.enc.Base64.parse(aes_key); 64 | else console.warn("You did not set an encryption key. Some calls may not work without this."); 65 | 66 | var _session_storage_key = "Newgrounds-io-app_session-"+(_app_id.split(":").join("-")); 67 | 68 | function checkLocalStorage() { 69 | if (typeof(localStorage) != 'undefined' && localStorage && localStorage.getItem.constructor == Function) return true; 70 | console.warn('localStorage unavailable. Are you running from a web server?'); 71 | return false; 72 | } 73 | 74 | function getStoredSession() { 75 | if (!checkLocalStorage()) return null; 76 | var id = localStorage.getItem(_session_storage_key); 77 | return id ? id : null; 78 | } 79 | 80 | function setStoredSession(id) { 81 | if (!checkLocalStorage()) return null; 82 | localStorage.setItem(_session_storage_key, id); 83 | } 84 | 85 | function clearStoredSession() { 86 | if (!checkLocalStorage()) return null; 87 | localStorage.removeItem(_session_storage_key); 88 | } 89 | 90 | if (!_session_id && getStoredSession()) _session_id = getStoredSession(); 91 | 92 | this.addEventListener('App.endSession', function(e) { 93 | ngio.session_id = null; 94 | clearStoredSession(); 95 | }); 96 | 97 | this.addEventListener('App.startSession', function(e) { 98 | if (e.success) ngio.session_id = e.data.session.id; 99 | }); 100 | 101 | this.addEventListener('App.checkSession', function(e) { 102 | if (e.success) { 103 | if (e.data.session.expired) { 104 | clearStoredSession(); 105 | this.session_id = null; 106 | } else if (e.data.session.remember) { 107 | setStoredSession(e.data.session.id); 108 | } 109 | } else { 110 | this.session_id = null; 111 | clearStoredSession(); 112 | } 113 | }); 114 | 115 | this._encryptCall = function(call_model) { 116 | if (!call_model || !call_model.constructor == Newgrounds.io.model.call_model) throw new Error("Attempted to encrypt a non 'call' object"); 117 | var iv = CryptoJS.lib.WordArray.random(16); 118 | var encrypted = CryptoJS.AES.encrypt(JSON.stringify(call_model.toObject()), _aes_key, { iv: iv }); 119 | var output = CryptoJS.enc.Base64.stringify(iv.concat(encrypted.ciphertext)); 120 | 121 | call_model.secure = output; 122 | call_model.parameters = null; 123 | return call_model; 124 | }; 125 | } 126 | 127 | Newgrounds.io.core.prototype = { 128 | 129 | _session_loader: null, 130 | _call_queue: [], 131 | _event_listeners: {}, 132 | 133 | /** 134 | * Adds a listener function to the specified event. 135 | * @instance 136 | * @memberof Newgrounds.io.core 137 | * @function addEventListener 138 | * @param {string} type - The event to listen for. Typically a component name like 'Gateway.getVersion'. 139 | * @param {function} listener - A function to call when the event is triggered. 140 | */ 141 | addEventListener: Newgrounds.io.events.EventDispatcher.prototype.addEventListener, 142 | 143 | /** 144 | * Removes a listener function from the specified event. 145 | * @instance 146 | * @memberof Newgrounds.io.core 147 | * @function removeEventListener 148 | * @param {string} type - The event you want to remove a listener from. Typically a component name like 'Gateway.getVersion'. 149 | * @param {function} listener - The listener function you want to remove. 150 | * @return {boolean} Returns true if a matching listener was removed. 151 | */ 152 | removeEventListener: Newgrounds.io.events.EventDispatcher.prototype.removeEventListener, 153 | 154 | /** 155 | * Removes ALL listener functions from the specified event. 156 | * @instance 157 | * @memberof Newgrounds.io.core 158 | * @function removeAllEventListeners 159 | * @param {string} type - The event you want to remove listeners from. 160 | * @return {number} The number of listeners that were removed. 161 | */ 162 | removeAllEventListeners: Newgrounds.io.events.EventDispatcher.prototype.removeAllEventListeners, 163 | 164 | /** 165 | * Dispatches an event to any listener functions. 166 | * @instance 167 | * @memberof Newgrounds.io.core 168 | * @function dispatchEvent 169 | * @param {Newgrounds.io.events.OutputEvent} event - The event to dispatch. 170 | * @return {boolean} 171 | */ 172 | dispatchEvent: Newgrounds.io.events.EventDispatcher.prototype.dispatchEvent, 173 | 174 | /** 175 | * Gets an initialized Newgrounds.io.SessionLoader instance. 176 | * @instance 177 | * @memberof Newgrounds.io.core 178 | * @function getSessionLoader 179 | * @return {Newgrounds.io.SessionLoader} 180 | */ 181 | getSessionLoader: function() { 182 | if (this._session_loader == null) this._session_loader = new Newgrounds.io.SessionLoader(this); 183 | return this._session_loader; 184 | }, 185 | /** 186 | * Gets the current active session, if any. 187 | * @instance 188 | * @memberof Newgrounds.io.core 189 | * @function getSession 190 | * @return {Newgrounds.io.model.session} 191 | */ 192 | getSession: function() { 193 | return this.getSessionLoader().session; 194 | }, 195 | 196 | /** 197 | * Gets the current logged in user, if available. 198 | * @instance 199 | * @memberof Newgrounds.io.core 200 | * @function getCurrentUser 201 | * @return {Newgrounds.io.model.user} 202 | */ 203 | getCurrentUser: function() { 204 | var sl = this.getSessionLoader(); 205 | if (sl.session) return sl.session.user; 206 | return null; 207 | }, 208 | 209 | /** 210 | * Gets the last login error (if any). 211 | * @instance 212 | * @memberof Newgrounds.io.core 213 | * @function getLoginError 214 | * @return {Newgrounds.io.model.error} 215 | */ 216 | getLoginError: function() { 217 | return this.getSessionLoader().last_error; 218 | }, 219 | 220 | /** 221 | * Gets an active session. If one does not already exist, one will be created. 222 | * @instance 223 | * @memberof Newgrounds.io.core 224 | * @function getValidSession 225 | * @param {Newgrounds.io.SessionLoader~onStatusUpdate} [callback] - An optional callback function. 226 | * @param {object} [context] - The context under which to call the callback. Optional. 227 | */ 228 | getValidSession: function(callback, context) { 229 | this.getSessionLoader().getValidSession(callback, context); 230 | }, 231 | 232 | /** 233 | * Loads Newgrounds Passport and waits for the user to log in, or cancel their login. 234 | * @instance 235 | * @memberof Newgrounds.io.core 236 | * @function requestLogin 237 | * @param {function} [on_logged_in] - A function that will execute when the user is logged in 238 | * @param {function} [on_login_failed] - A function that will execute if the login fails 239 | * @param {function} [on_login_cancelled] - A function that will execute if the user cancels the login. 240 | * @param {object} [context] - The context under which the callbacks will be called. Optional. 241 | */ 242 | requestLogin: function(on_logged_in, on_login_failed, on_login_cancelled, context) { 243 | 244 | if (!on_logged_in || on_logged_in.constructor !== Function) throw ("Missing required callback for 'on_logged_in'."); 245 | if (!on_login_failed || on_login_failed.constructor !== Function) throw ("Missing required callback for 'on_login_failed'."); 246 | 247 | var io = this; 248 | var loader = this.getSessionLoader(); 249 | var login_interval; 250 | 251 | function end_request() { 252 | if (login_interval) clearInterval(login_interval); 253 | io.removeEventListener("cancelLoginRequest", cancel_request); 254 | loader.closePassport(); 255 | } 256 | 257 | function cancel_request() { 258 | on_login_cancelled && on_login_cancelled.constructor === Function ? on_login_cancelled.call(context) : on_login_failed.call(context); 259 | end_request(); 260 | } 261 | 262 | io.addEventListener("cancelLoginRequest", cancel_request); 263 | 264 | if (io.getCurrentUser()) { 265 | on_logged_in.call(context); 266 | } else { 267 | loader.loadPassport(); 268 | login_interval = setInterval(function(){ 269 | loader.checkSession(function(session) { 270 | if (!session || session.expired) { 271 | if (loader.last_error.code == 111) { 272 | cancel_request(); 273 | } else { 274 | end_request(); 275 | on_login_failed.call(context); 276 | } 277 | } else if (session.user) { 278 | end_request(); 279 | on_logged_in.call(context); 280 | } 281 | }); 282 | }, 3000); 283 | } 284 | }, 285 | 286 | /** 287 | * Cancels any pending login request created via requestLogin() 288 | * @instance 289 | * @memberof Newgrounds.io.core 290 | * @function cancelLoginRequest 291 | */ 292 | cancelLoginRequest: function() { 293 | event = new Newgrounds.io.events.OutputEvent("cancelLoginRequest",null,null); 294 | this.dispatchEvent(event); 295 | }, 296 | 297 | /** 298 | * Ends any active user session and logs the user out of Newgrounds Passport. 299 | * @instance 300 | * @memberof Newgrounds.io.core 301 | * @function logOut 302 | * @param {Newgrounds.io.SessionLoader~onStatusUpdate} [callback] - An optional callback function. 303 | * @param {object} [context] - The context under which to call the callback. Optional. 304 | */ 305 | logOut: function(callback, context) { 306 | this.getSessionLoader().endSession(callback, context); 307 | }, 308 | 309 | /** 310 | * Adds a component call to the queue. Will be executed later with executeCall. 311 | * @instance 312 | * @memberof Newgrounds.io.core 313 | * @function queueComponent 314 | * @param {string} component - The component to call, ie 'Gateway.ping' 315 | * @param {(object|object[])} [parameters] - Parameters being passed to the component. You may also pass multiple parameters objects in an array to execute the component multiple times. 316 | * @param {Newgrounds.io.core~onCallResult} [callback] - A function that will execute when this call has executed. 317 | * @param {object} [context] - The context under which the callback will be executed. Optional. 318 | */ 319 | queueComponent: function(component, parameters, callback, context) { 320 | if (parameters && parameters.constructor === Function && !callback) { 321 | callback = parameters; 322 | parameters = null; 323 | } 324 | 325 | var call_model = new Newgrounds.io.model.call(this); 326 | call_model.component = component; 327 | if (typeof(parameters) != 'undefined') call_model.parameters = parameters; 328 | this._validateCall(call_model); 329 | 330 | this._call_queue.push([call_model,callback,context]); 331 | }, 332 | 333 | /** 334 | * Executes any queued calls and resets the queue. 335 | * @instance 336 | * @memberof Newgrounds.io.core 337 | * @function executeQueue 338 | */ 339 | executeQueue: function() { 340 | var calls = []; 341 | var callbacks = []; 342 | var contexts = []; 343 | for(var i=0; i value for '"+i+"' in '"+component+"' data, got "+typeof(result_object[i])); 476 | continue; 477 | } 478 | models = []; 479 | for(j=0; j 0) { 607 | for(i=0; i= 0) { 105 | this._event_listeners[type].splice(index,1); 106 | return true; 107 | } 108 | return false; 109 | }, 110 | 111 | /** 112 | * Removes ALL listener functions from the specified event. 113 | * @instance 114 | * @memberof Newgrounds.io.events.EventDispatcher 115 | * @function removeAllEventListeners 116 | * @param {string} type - The event name you want to remove listeners from. 117 | * @return {number} The number of listeners that were removed. 118 | */ 119 | removeAllEventListeners: function(type) { 120 | if (typeof(this._event_listeners[type]) == 'undefined') return 0; 121 | var removed = this._event_listeners[type].length; 122 | this._event_listeners[type] = []; 123 | return removed; 124 | }, 125 | 126 | /** 127 | * Dispatches an event to any listener functions. 128 | * @instance 129 | * @memberof Newgrounds.io.events.EventDispatcher 130 | * @function dispatchEvent 131 | * @param event - The event to dispatch. 132 | * @return {boolean} 133 | */ 134 | dispatchEvent: function(event) { 135 | var valid = false; 136 | var listener; 137 | for(var e in Newgrounds.io.events) { 138 | if(event.constructor === Newgrounds.io.events[e]) { 139 | valid = true; 140 | break; 141 | } 142 | } 143 | if (!valid) throw new Error('Unsupported event object'); 144 | if (typeof(this._event_listeners[event.type]) == 'undefined') return false; 145 | for(var i=0; i>>2]|=(e[k>>>2]>>>24-8*(k%4)&255)<<24-8*((j+k)%4);else if(65535>>2]=e[k>>>2];else c.push.apply(c,e);this.sigBytes+=a;return this},clamp:function(){var a=this.words,c=this.sigBytes;a[c>>>2]&=4294967295<< 9 | 32-8*(c%4);a.length=u.ceil(c/4)},clone:function(){var a=t.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var c=[],e=0;e>>2]>>>24-8*(j%4)&255;e.push((k>>>4).toString(16));e.push((k&15).toString(16))}return e.join("")},parse:function(a){for(var c=a.length,e=[],j=0;j>>3]|=parseInt(a.substr(j, 10 | 2),16)<<24-4*(j%8);return new r.init(e,c/2)}},b=w.Latin1={stringify:function(a){var c=a.words;a=a.sigBytes;for(var e=[],j=0;j>>2]>>>24-8*(j%4)&255));return e.join("")},parse:function(a){for(var c=a.length,e=[],j=0;j>>2]|=(a.charCodeAt(j)&255)<<24-8*(j%4);return new r.init(e,c)}},x=w.Utf8={stringify:function(a){try{return decodeURIComponent(escape(b.stringify(a)))}catch(c){throw Error("Malformed UTF-8 data");}},parse:function(a){return b.parse(unescape(encodeURIComponent(a)))}}, 11 | q=l.BufferedBlockAlgorithm=t.extend({reset:function(){this._data=new r.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=x.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var c=this._data,e=c.words,j=c.sigBytes,k=this.blockSize,b=j/(4*k),b=a?u.ceil(b):u.max((b|0)-this._minBufferSize,0);a=b*k;j=u.min(4*a,j);if(a){for(var q=0;q>>2]>>>24-8*(r%4)&255)<<16|(l[r+1>>>2]>>>24-8*((r+1)%4)&255)<<8|l[r+2>>>2]>>>24-8*((r+2)%4)&255,v=0;4>v&&r+0.75*v>>6*(3-v)&63));if(l=t.charAt(64))for(;d.length%4;)d.push(l);return d.join("")},parse:function(d){var l=d.length,s=this._map,t=s.charAt(64);t&&(t=d.indexOf(t),-1!=t&&(l=t));for(var t=[],r=0,w=0;w< 15 | l;w++)if(w%4){var v=s.indexOf(d.charAt(w-1))<<2*(w%4),b=s.indexOf(d.charAt(w))>>>6-2*(w%4);t[r>>>2]|=(v|b)<<24-8*(r%4);r++}return p.create(t,r)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}})(); 16 | (function(u){function p(b,n,a,c,e,j,k){b=b+(n&a|~n&c)+e+k;return(b<>>32-j)+n}function d(b,n,a,c,e,j,k){b=b+(n&c|a&~c)+e+k;return(b<>>32-j)+n}function l(b,n,a,c,e,j,k){b=b+(n^a^c)+e+k;return(b<>>32-j)+n}function s(b,n,a,c,e,j,k){b=b+(a^(n|~c))+e+k;return(b<>>32-j)+n}for(var t=CryptoJS,r=t.lib,w=r.WordArray,v=r.Hasher,r=t.algo,b=[],x=0;64>x;x++)b[x]=4294967296*u.abs(u.sin(x+1))|0;r=r.MD5=v.extend({_doReset:function(){this._hash=new w.init([1732584193,4023233417,2562383102,271733878])}, 17 | _doProcessBlock:function(q,n){for(var a=0;16>a;a++){var c=n+a,e=q[c];q[c]=(e<<8|e>>>24)&16711935|(e<<24|e>>>8)&4278255360}var a=this._hash.words,c=q[n+0],e=q[n+1],j=q[n+2],k=q[n+3],z=q[n+4],r=q[n+5],t=q[n+6],w=q[n+7],v=q[n+8],A=q[n+9],B=q[n+10],C=q[n+11],u=q[n+12],D=q[n+13],E=q[n+14],x=q[n+15],f=a[0],m=a[1],g=a[2],h=a[3],f=p(f,m,g,h,c,7,b[0]),h=p(h,f,m,g,e,12,b[1]),g=p(g,h,f,m,j,17,b[2]),m=p(m,g,h,f,k,22,b[3]),f=p(f,m,g,h,z,7,b[4]),h=p(h,f,m,g,r,12,b[5]),g=p(g,h,f,m,t,17,b[6]),m=p(m,g,h,f,w,22,b[7]), 18 | f=p(f,m,g,h,v,7,b[8]),h=p(h,f,m,g,A,12,b[9]),g=p(g,h,f,m,B,17,b[10]),m=p(m,g,h,f,C,22,b[11]),f=p(f,m,g,h,u,7,b[12]),h=p(h,f,m,g,D,12,b[13]),g=p(g,h,f,m,E,17,b[14]),m=p(m,g,h,f,x,22,b[15]),f=d(f,m,g,h,e,5,b[16]),h=d(h,f,m,g,t,9,b[17]),g=d(g,h,f,m,C,14,b[18]),m=d(m,g,h,f,c,20,b[19]),f=d(f,m,g,h,r,5,b[20]),h=d(h,f,m,g,B,9,b[21]),g=d(g,h,f,m,x,14,b[22]),m=d(m,g,h,f,z,20,b[23]),f=d(f,m,g,h,A,5,b[24]),h=d(h,f,m,g,E,9,b[25]),g=d(g,h,f,m,k,14,b[26]),m=d(m,g,h,f,v,20,b[27]),f=d(f,m,g,h,D,5,b[28]),h=d(h,f, 19 | m,g,j,9,b[29]),g=d(g,h,f,m,w,14,b[30]),m=d(m,g,h,f,u,20,b[31]),f=l(f,m,g,h,r,4,b[32]),h=l(h,f,m,g,v,11,b[33]),g=l(g,h,f,m,C,16,b[34]),m=l(m,g,h,f,E,23,b[35]),f=l(f,m,g,h,e,4,b[36]),h=l(h,f,m,g,z,11,b[37]),g=l(g,h,f,m,w,16,b[38]),m=l(m,g,h,f,B,23,b[39]),f=l(f,m,g,h,D,4,b[40]),h=l(h,f,m,g,c,11,b[41]),g=l(g,h,f,m,k,16,b[42]),m=l(m,g,h,f,t,23,b[43]),f=l(f,m,g,h,A,4,b[44]),h=l(h,f,m,g,u,11,b[45]),g=l(g,h,f,m,x,16,b[46]),m=l(m,g,h,f,j,23,b[47]),f=s(f,m,g,h,c,6,b[48]),h=s(h,f,m,g,w,10,b[49]),g=s(g,h,f,m, 20 | E,15,b[50]),m=s(m,g,h,f,r,21,b[51]),f=s(f,m,g,h,u,6,b[52]),h=s(h,f,m,g,k,10,b[53]),g=s(g,h,f,m,B,15,b[54]),m=s(m,g,h,f,e,21,b[55]),f=s(f,m,g,h,v,6,b[56]),h=s(h,f,m,g,x,10,b[57]),g=s(g,h,f,m,t,15,b[58]),m=s(m,g,h,f,D,21,b[59]),f=s(f,m,g,h,z,6,b[60]),h=s(h,f,m,g,C,10,b[61]),g=s(g,h,f,m,j,15,b[62]),m=s(m,g,h,f,A,21,b[63]);a[0]=a[0]+f|0;a[1]=a[1]+m|0;a[2]=a[2]+g|0;a[3]=a[3]+h|0},_doFinalize:function(){var b=this._data,n=b.words,a=8*this._nDataBytes,c=8*b.sigBytes;n[c>>>5]|=128<<24-c%32;var e=u.floor(a/ 21 | 4294967296);n[(c+64>>>9<<4)+15]=(e<<8|e>>>24)&16711935|(e<<24|e>>>8)&4278255360;n[(c+64>>>9<<4)+14]=(a<<8|a>>>24)&16711935|(a<<24|a>>>8)&4278255360;b.sigBytes=4*(n.length+1);this._process();b=this._hash;n=b.words;for(a=0;4>a;a++)c=n[a],n[a]=(c<<8|c>>>24)&16711935|(c<<24|c>>>8)&4278255360;return b},clone:function(){var b=v.clone.call(this);b._hash=this._hash.clone();return b}});t.MD5=v._createHelper(r);t.HmacMD5=v._createHmacHelper(r)})(Math); 22 | (function(){var u=CryptoJS,p=u.lib,d=p.Base,l=p.WordArray,p=u.algo,s=p.EvpKDF=d.extend({cfg:d.extend({keySize:4,hasher:p.MD5,iterations:1}),init:function(d){this.cfg=this.cfg.extend(d)},compute:function(d,r){for(var p=this.cfg,s=p.hasher.create(),b=l.create(),u=b.words,q=p.keySize,p=p.iterations;u.length>>2]&255}};d.BlockCipher=v.extend({cfg:v.cfg.extend({mode:b,padding:q}),reset:function(){v.reset.call(this);var a=this.cfg,b=a.iv,a=a.mode;if(this._xformMode==this._ENC_XFORM_MODE)var c=a.createEncryptor;else c=a.createDecryptor,this._minBufferSize=1;this._mode=c.call(a, 28 | this,b&&b.words)},_doProcessBlock:function(a,b){this._mode.processBlock(a,b)},_doFinalize:function(){var a=this.cfg.padding;if(this._xformMode==this._ENC_XFORM_MODE){a.pad(this._data,this.blockSize);var b=this._process(!0)}else b=this._process(!0),a.unpad(b);return b},blockSize:4});var n=d.CipherParams=l.extend({init:function(a){this.mixIn(a)},toString:function(a){return(a||this.formatter).stringify(this)}}),b=(p.format={}).OpenSSL={stringify:function(a){var b=a.ciphertext;a=a.salt;return(a?s.create([1398893684, 29 | 1701076831]).concat(a).concat(b):b).toString(r)},parse:function(a){a=r.parse(a);var b=a.words;if(1398893684==b[0]&&1701076831==b[1]){var c=s.create(b.slice(2,4));b.splice(0,4);a.sigBytes-=16}return n.create({ciphertext:a,salt:c})}},a=d.SerializableCipher=l.extend({cfg:l.extend({format:b}),encrypt:function(a,b,c,d){d=this.cfg.extend(d);var l=a.createEncryptor(c,d);b=l.finalize(b);l=l.cfg;return n.create({ciphertext:b,key:c,iv:l.iv,algorithm:a,mode:l.mode,padding:l.padding,blockSize:a.blockSize,formatter:d.format})}, 30 | decrypt:function(a,b,c,d){d=this.cfg.extend(d);b=this._parse(b,d.format);return a.createDecryptor(c,d).finalize(b.ciphertext)},_parse:function(a,b){return"string"==typeof a?b.parse(a,this):a}}),p=(p.kdf={}).OpenSSL={execute:function(a,b,c,d){d||(d=s.random(8));a=w.create({keySize:b+c}).compute(a,d);c=s.create(a.words.slice(b),4*c);a.sigBytes=4*b;return n.create({key:a,iv:c,salt:d})}},c=d.PasswordBasedCipher=a.extend({cfg:a.cfg.extend({kdf:p}),encrypt:function(b,c,d,l){l=this.cfg.extend(l);d=l.kdf.execute(d, 31 | b.keySize,b.ivSize);l.iv=d.iv;b=a.encrypt.call(this,b,c,d.key,l);b.mixIn(d);return b},decrypt:function(b,c,d,l){l=this.cfg.extend(l);c=this._parse(c,l.format);d=l.kdf.execute(d,b.keySize,b.ivSize,c.salt);l.iv=d.iv;return a.decrypt.call(this,b,c,d.key,l)}})}(); 32 | (function(){for(var u=CryptoJS,p=u.lib.BlockCipher,d=u.algo,l=[],s=[],t=[],r=[],w=[],v=[],b=[],x=[],q=[],n=[],a=[],c=0;256>c;c++)a[c]=128>c?c<<1:c<<1^283;for(var e=0,j=0,c=0;256>c;c++){var k=j^j<<1^j<<2^j<<3^j<<4,k=k>>>8^k&255^99;l[e]=k;s[k]=e;var z=a[e],F=a[z],G=a[F],y=257*a[k]^16843008*k;t[e]=y<<24|y>>>8;r[e]=y<<16|y>>>16;w[e]=y<<8|y>>>24;v[e]=y;y=16843009*G^65537*F^257*z^16843008*e;b[k]=y<<24|y>>>8;x[k]=y<<16|y>>>16;q[k]=y<<8|y>>>24;n[k]=y;e?(e=z^a[a[a[G^z]]],j^=a[a[j]]):e=j=1}var H=[0,1,2,4,8, 33 | 16,32,64,128,27,54],d=d.AES=p.extend({_doReset:function(){for(var a=this._key,c=a.words,d=a.sigBytes/4,a=4*((this._nRounds=d+6)+1),e=this._keySchedule=[],j=0;j>>24]<<24|l[k>>>16&255]<<16|l[k>>>8&255]<<8|l[k&255]):(k=k<<8|k>>>24,k=l[k>>>24]<<24|l[k>>>16&255]<<16|l[k>>>8&255]<<8|l[k&255],k^=H[j/d|0]<<24);e[j]=e[j-d]^k}c=this._invKeySchedule=[];for(d=0;dd||4>=j?k:b[l[k>>>24]]^x[l[k>>>16&255]]^q[l[k>>> 34 | 8&255]]^n[l[k&255]]},encryptBlock:function(a,b){this._doCryptBlock(a,b,this._keySchedule,t,r,w,v,l)},decryptBlock:function(a,c){var d=a[c+1];a[c+1]=a[c+3];a[c+3]=d;this._doCryptBlock(a,c,this._invKeySchedule,b,x,q,n,s);d=a[c+1];a[c+1]=a[c+3];a[c+3]=d},_doCryptBlock:function(a,b,c,d,e,j,l,f){for(var m=this._nRounds,g=a[b]^c[0],h=a[b+1]^c[1],k=a[b+2]^c[2],n=a[b+3]^c[3],p=4,r=1;r>>24]^e[h>>>16&255]^j[k>>>8&255]^l[n&255]^c[p++],s=d[h>>>24]^e[k>>>16&255]^j[n>>>8&255]^l[g&255]^c[p++],t= 35 | d[k>>>24]^e[n>>>16&255]^j[g>>>8&255]^l[h&255]^c[p++],n=d[n>>>24]^e[g>>>16&255]^j[h>>>8&255]^l[k&255]^c[p++],g=q,h=s,k=t;q=(f[g>>>24]<<24|f[h>>>16&255]<<16|f[k>>>8&255]<<8|f[n&255])^c[p++];s=(f[h>>>24]<<24|f[k>>>16&255]<<16|f[n>>>8&255]<<8|f[g&255])^c[p++];t=(f[k>>>24]<<24|f[n>>>16&255]<<16|f[g>>>8&255]<<8|f[h&255])^c[p++];n=(f[n>>>24]<<24|f[g>>>16&255]<<16|f[h>>>8&255]<<8|f[k&255])^c[p++];a[b]=q;a[b+1]=s;a[b+2]=t;a[b+3]=n},keySize:8});u.AES=p._createHelper(d)})(); -------------------------------------------------------------------------------- /file/src/license.txt: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright (c) 2015 Newgrounds Inc. 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in all 13 | * copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | -------------------------------------------------------------------------------- /file/src/model/call.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains all the information needed to execute an API component. 3 | * @name Newgrounds.io.model.call 4 | * @constructor 5 | * @memberof Newgrounds.io.model 6 | * @property {string} component - The name of the component you want to call, ie 'App.connect'. 7 | * @property {object} echo - An optional value that will be returned, verbatim, in the #result object. 8 | * @property {(object|object[])} parameters - An object of parameters you want to pass to the component. 9 | * @property {string} secure - A an encrypted #call object or array of #call objects. 10 | * @param {Newgrounds.io.core} [ngio] - A Newgrounds.io.core instance associated with the model object. 11 | * @param {object} [from_object] - A literal object used to populate this model's properties. 12 | */ 13 | Newgrounds.io.model.call = function(ngio, from_object) { 14 | 15 | /* private vars */ 16 | var _component, _echo, _parameters, _secure; 17 | this.__property_names = ["component","echo","parameters","secure"]; 18 | this.__classname = "Newgrounds.io.model.call"; 19 | this.__ngio = ngio; 20 | 21 | 22 | var _component; 23 | Object.defineProperty(this, 'component', { 24 | get: function() { return typeof(_component) == 'undefined' ? null : _component; }, 25 | set: function(__vv__) { 26 | Newgrounds.io.model.checkStrictValue(this.__classname, 'component', __vv__, String, null, null, null); 27 | _component = __vv__; 28 | } 29 | }); 30 | 31 | var _echo; 32 | Object.defineProperty(this, 'echo', { 33 | get: function() { return typeof(_echo) == 'undefined' ? null : _echo; }, 34 | set: function(__vv__) { 35 | _echo = __vv__; 36 | } 37 | }); 38 | 39 | var _parameters; 40 | Object.defineProperty(this, 'parameters', { 41 | get: function() { return typeof(_parameters) == 'undefined' ? null : _parameters; }, 42 | set: function(__vv__) { 43 | Newgrounds.io.model.checkStrictValue(this.__classname, 'parameters', __vv__, Object, null, Object, null); 44 | _parameters = __vv__; 45 | } 46 | }); 47 | 48 | var _secure; 49 | Object.defineProperty(this, 'secure', { 50 | get: function() { return typeof(_secure) == 'undefined' ? null : _secure; }, 51 | set: function(__vv__) { 52 | Newgrounds.io.model.checkStrictValue(this.__classname, 'secure', __vv__, String, null, null, null); 53 | _secure = __vv__; 54 | } 55 | }); 56 | if(from_object) this.fromObject(from_object); 57 | }; 58 | 59 | Newgrounds.io.model.call.prototype._has_ngio_user = function() { 60 | return (this.__ngio && this.__ngio.user); 61 | } 62 | 63 | /** 64 | * Converts the model instance to a literal object. 65 | * @instance 66 | * @memberof Newgrounds.io.model.call 67 | * @function toObject 68 | * @return {object} 69 | */ 70 | Newgrounds.io.model.call.prototype.toObject = function() { 71 | var object = {}; 72 | for(var i=0; i